找回密码
 立即注册

QQ登录

只需一步,快速开始

开启左侧

请问 为何我使用M480 EADC DMA 只能获取2个通道?谢谢!

[复制链接]
匿名  发表于 2023-9-12 20:58:15 |阅读模式
/*************************************************************************//**
* @file     main.c
* @version  V1.00
* @brief    A project template for M480 MCU.
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "NuMicro.h"

#define ADC_PDMA_CH                                         (4)
#define ADC_PDMA_OPENED_CH                           (1 << ADC_PDMA_CH)
#define ADC_DMA_SAMPLE_COUNT                         (4)

uint16_t pdmaConvertedData[ADC_DMA_SAMPLE_COUNT] = {0};


enum
{
    ADC0_CH0 = 0,
    ADC0_CH1,
    ADC0_CH2,
    ADC0_CH3,
    ADC0_CH4,
    ADC0_CH5,
    ADC0_CH6,
    ADC0_CH7,
    ADC0_CH8,
    ADC0_CH9,
    ADC0_CH10,
    ADC0_CH11,
    ADC0_CH12,
    ADC0_CH13,
    ADC0_CH14,
    ADC0_CH15,

    ADC0_CH16_BAND_GAP_VOLT,
    ADC0_CH17_TEMP_SENSOR,
    ADC0_CH18_VBAT,

    ADC_CH_DEFAULT
} ADC_CH_TypeDef;

typedef enum
{

    flag_ADC_Band_GAP = 0,
    flag_ADC_Data_Ready,
    flag_ADC_Sensor_Ready,

    flag_PDMA_Trans_Data_Ready,

    flag_DEFAULT
} Flag_Index;

uint32_t BitFlag = 0;
#define BitFlag_ON(flag)                                                        (BitFlag|=flag)
#define BitFlag_OFF(flag)                                                        (BitFlag&=~flag)
#define BitFlag_READ(flag)                                                        ((BitFlag&flag)?1:0)
#define ReadBit(bit)                                                                (uint32_t)(1<<bit)

#define is_flag_set(idx)                                                        (BitFlag_READ(ReadBit(idx)))
#define set_flag(idx,en)                                                        ( (en == 1) ? (BitFlag_ON(ReadBit(idx))) : (BitFlag_OFF(ReadBit(idx))))

void ReloadPDMA(void)
{
    /* transfer width is half word(16 bit) and transfer count is ADCDatalenght+1 */
    PDMA_SetTransferCnt(PDMA, ADC_PDMA_CH, PDMA_WIDTH_16, ADC_DMA_SAMPLE_COUNT);

    /* Select PDMA request source as ADC RX */
    PDMA_SetTransferMode(PDMA, ADC_PDMA_CH, PDMA_EADC0_RX, FALSE, (uint32_t) 0);
}

void PDMA_IRQHandler(void)
{
    uint32_t status = PDMA_GET_INT_STATUS(PDMA);

    if (status & PDMA_INTSTS_ABTIF_Msk)   /* abort */
    {
#if 0
        PDMA_CLR_ABORT_FLAG(PDMA, PDMA_GET_ABORT_STS(PDMA));
#else
        if (PDMA_GET_ABORT_STS(PDMA) & ADC_PDMA_OPENED_CH)
        {
            printf("ABTSTS\r\n");
        }
        PDMA_CLR_ABORT_FLAG(PDMA, ADC_PDMA_OPENED_CH);

#endif
    }
    else if (status & PDMA_INTSTS_TDIF_Msk)     /* done */
    {
        if(PDMA_GET_TD_STS(PDMA) & ADC_PDMA_OPENED_CH)
        {
            //insert process
            set_flag(flag_PDMA_Trans_Data_Ready, ENABLE);
            printf("TDIF\r\n");
        }

        /* Clear PDMA transfer done interrupt flag */
        PDMA_CLR_TD_FLAG(PDMA, ADC_PDMA_OPENED_CH);
    }
    else if (status & (PDMA_INTSTS_REQTOF1_Msk))     /* Check the DMA time-out interrupt flag */
    {
        PDMA_CLR_TMOUT_FLAG(PDMA, ADC_PDMA_CH);
        printf("REQTOF\r\n");

    }
    else
    {

    }

}


void PDMA_Init(void)
{
    SYS_ResetModule(PDMA_RST);

    /* Configure PDMA peripheral mode form ADC to memory */
    /* Open PDMA Channel 1 based on ADC_PDMA_CH setting*/
//    PDMA_Open(PDMA, BIT0 << ADC_PDMA_CH);
    PDMA_Open(PDMA, 0);

    /* transfer width is half word(16 bit) and transfer count is ADCDatalenght+1 */
    PDMA_SetTransferCnt(PDMA, ADC_PDMA_CH, PDMA_WIDTH_16, ADC_DMA_SAMPLE_COUNT);

    /* Set source address as ADC data register (no increment) and destination address as g_i32ConversionData array (increment) */
    PDMA_SetTransferAddr(PDMA, ADC_PDMA_CH, (uint32_t) & (EADC->CURDAT), PDMA_SAR_FIX, (uint32_t)pdmaConvertedData, PDMA_DAR_INC);

    /* Select PDMA request source as ADC RX */
    PDMA_SetTransferMode(PDMA, ADC_PDMA_CH, PDMA_EADC0_RX, FALSE, 0);

    /* Set PDMA as single request type for ADC */
    PDMA_SetBurstType(PDMA, ADC_PDMA_CH, PDMA_REQ_SINGLE, PDMA_BURST_128);

    PDMA_EnableInt(PDMA, ADC_PDMA_CH, PDMA_INT_TRANS_DONE);
    NVIC_EnableIRQ(PDMA_IRQn);

    PDMA_Trigger(PDMA, ADC_PDMA_CH);

    /* ADC enable PDMA transfer */
    EADC_ENABLE_PDMA(EADC);
}

void EADC00_IRQHandler(void)
{
//    printf(" EADC00_IRQHandler\r\n");
    EADC_CLR_INT_FLAG(EADC, EADC_STATUS2_ADIF0_Msk);      /* Clear the A/D ADINT0 interrupt flag */
}


void ADC_Convert_Ext_Channel(void)
{

    /* Set input mode as single-end, and Single mode*/
    EADC_Open(EADC, EADC_CTL_DIFFEN_SINGLE_END);

    EADC_SetExtendSampleTime(EADC, 0x0f, 0x3F);

    EADC_ConfigSampleModule(EADC, 0, EADC_ADINT0_TRIGGER, 0);
    EADC_ConfigSampleModule(EADC, 1, EADC_ADINT0_TRIGGER, 1);
    EADC_ConfigSampleModule(EADC, 2, EADC_ADINT0_TRIGGER, 2);
    EADC_ConfigSampleModule(EADC, 3, EADC_ADINT0_TRIGGER, 3);


    EADC_CLR_INT_FLAG(EADC, EADC_STATUS2_ADIF0_Msk);
    EADC_ENABLE_INT(EADC, (BIT0 << 0));

    EADC_ENABLE_SAMPLE_MODULE_INT(EADC, 0, 0x7FF);

    NVIC_EnableIRQ(EADC00_IRQn);

    PDMA_Init();

    EADC_START_CONV(EADC, 0x0F);

}


void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
    PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);

    /* Enable External XTAL (4~24 MHz) */
    CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);

    /* Waiting for 12MHz clock ready */
    CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);

    /* Set core clock as PLL_CLOCK from PLL */
    CLK_SetCoreClock(FREQ_192MHZ);
    /* Set PCLK0/PCLK1 to HCLK/2 */
    CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);

    /* Enable UART clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Select UART clock source from HXT */
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HXT, CLK_CLKDIV0_UART0(1));

    /* Enable EADC module clock */
    CLK_EnableModuleClock(EADC_MODULE);

    /* EADC clock source is 96MHz, set divider to 8, EADC clock is 96/8 MHz */
    CLK_SetModuleClock(EADC_MODULE, 0, CLK_CLKDIV0_EADC(8));

    CLK_EnableModuleClock(PDMA_MODULE);

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
    SystemCoreClockUpdate();

    /* Set GPB multi-function pins for UART0 RXD and TXD */
    SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk);
    SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

    PB->MODE &= ~(GPIO_MODE_MODE0_Msk | GPIO_MODE_MODE1_Msk | GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
    SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB0MFP_Msk | SYS_GPB_MFPL_PB1MFP_Msk | SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk);
    SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB0MFP_EADC0_CH0 | SYS_GPB_MFPL_PB1MFP_EADC0_CH1 | SYS_GPB_MFPL_PB2MFP_EADC0_CH2 | SYS_GPB_MFPL_PB3MFP_EADC0_CH3);
    GPIO_DISABLE_DIGITAL_PATH(PB, BIT0 | BIT1 | BIT2 | BIT3);



    /* Set reference voltage to external pin (3.3V) */
    SYS_SetVRef(SYS_VREFCTL_VREF_PIN);

    /* Lock protected registers */
    SYS_LockReg();
}

/*
* This is a template project for M480 series MCU. Users could based on this project to create their
* own application without worry about the IAR/Keil project settings.
*
* This template application uses external crystal as HCLK source and configures UART0 to print out
* "Hello World", users may need to do extra system configuration based on their system design.
*/

int main()
{

    SYS_Init();
    /* Init UART to 115200-8n1 for print message */
    UART_Open(UART0, 115200);

    printf("\r\nCLK_GetCPUFreq : %8d\r\n", CLK_GetCPUFreq());
    printf("CLK_GetHXTFreq : %8d\r\n", CLK_GetHXTFreq());
    printf("CLK_GetLXTFreq : %8d\r\n", CLK_GetLXTFreq());
    printf("CLK_GetPCLK0Freq : %8d\r\n", CLK_GetPCLK0Freq());
    printf("CLK_GetPCLK1Freq : %8d\r\n", CLK_GetPCLK1Freq());

    ADC_Convert_Ext_Channel();

    /* Got no where to go, just loop forever */
    while(1)
    {


        pdmaConvertedData[0] = EADC_GET_CONV_DATA(EADC, 0);
        pdmaConvertedData[1] = EADC_GET_CONV_DATA(EADC, 1);
        pdmaConvertedData[2] = EADC_GET_CONV_DATA(EADC, 2);
        pdmaConvertedData[3] = EADC_GET_CONV_DATA(EADC, 3);

        printf("%04d,%04d,%04d,%04d \r\n", pdmaConvertedData[0], pdmaConvertedData[1], pdmaConvertedData[2], pdmaConvertedData[3] );

    }
}

/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/


M480BSP_ADC_测试有问题的.zip

1.57 MB, 下载次数: 238

回复

使用道具

admin 发表于 2023-9-13 11:32:16 | 显示全部楼层
设置不对导致逻辑错误。
1、设置采样模块0~3由中断触发,
2、设置采样模块0~10作为中断触发源
3、然后手动启动了0~3采样模块。

第一次:软件设置的通道0采样==》完成后PDMA搬走数据。  此时产生中断,中断又触发0~3采样模块采样
第二次:不确定是软件设置的采样模块1还是中断触发的采样模块0采样==》采样完===》搬运数据    产生中断==》再触发采样
第三次及以后:情况同第二次


中断触发采样:一般选用最大编号的采样模块作为中断源
过程:软件启动最高编号采样模块==》采样完==》产生中断==》触发采样模块依次采样==》最大编号采样模块采样结束==》产生中断==》重复上面动作



建议
建议采用软件按触发,不要使用中断触发,中断触发相当于触发源那个通道会多采样依次。同时使能0~3通道,会依次采样0~3通道==》结束
  
牛卧堂
回复 支持 反对

使用道具 举报

admin 发表于 2023-9-13 11:34:27 | 显示全部楼层
微信图片_20230913113122.png
牛卧堂
回复 支持 反对

使用道具 举报

admin 发表于 2023-9-13 11:34:44 | 显示全部楼层
微信图片_20230913113136.png
牛卧堂
回复 支持 反对

使用道具 举报

匿名  发表于 2023-9-13 12:37:50

#admin
您好!感谢指点!
我的疑问是:这样的话,在while循环中,岂不是会占用了很多资源?与我们的初衷期望相违背了?
另外,我尝试按照您的意见进行一下修改!
回复 支持 反对

使用道具

admin 发表于 2023-9-19 10:30:43 | 显示全部楼层
游客 101.24.238.x 发表于 2023-9-13 04:37
#admin
您好!感谢指点!
我的疑问是:这样的话,在while循环中,岂不是会占用了很多资源?与我们的初衷 ...

如果采样中断触发的话, 模块号最大的那一路会多采样一次,多出的一次你们自己看根据需要处理。
牛卧堂
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

新唐MCU