HDL136 adc uses dma to sample in the same way as Stm32, but when used at present, it feels that the adc software triggering of the Huada chip is quite tasteless, and only one conversion can be performed after each startup. Continuous conversion needs to be completed in adc After the interruption, start the adc conversion again. After the stm32 adc software is triggered, the conversion can be continuously performed, unless the stop operation is performed.
///< ADC中断服务函数
void ADC_IRQHandler(void)
{
//大概10us进入一次中断
if(TRUE == Adc_GetIrqStatus(AdcMskIrqSqr))
{
Adc_ClrIrqStatus(AdcMskIrqSqr);
//进入中断之后,再次开启adc转换
Adc_SQR_Start();
}
}
///< ADC采样端口初始化
static void Adc_Gpio_Config(void)
{
///< 开启ADC/BGR GPIO外设时钟
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
Gpio_SetAnalogMode(GpioPortA, GpioPin0); //PA00 (AIN0)
Gpio_SetAnalogMode(GpioPortA, GpioPin1); //PA01 (AIN1)
Gpio_SetAnalogMode(GpioPortA, GpioPin2); //PA02 (AIN2)
Gpio_SetAnalogMode(GpioPortA, GpioPin3); //PA03 (AIN3)
Gpio_SetAnalogMode(GpioPortA, GpioPin4); //PA04 (AIN4)
Gpio_SetAnalogMode(GpioPortA, GpioPin5); //PA05 (AIN5)
Gpio_SetAnalogMode(GpioPortA, GpioPin6); //PA06 (AIN6)
Gpio_SetAnalogMode(GpioPortA, GpioPin7); //PA07 (AIN7)
Gpio_SetAnalogMode(GpioPortB, GpioPin0); //PB00 (AIN8)
Gpio_SetAnalogMode(GpioPortB, GpioPin1); //PB01 (AIN9)
}
///< ADC模块初始化
static void Adc_Config(void)
{
stc_adc_cfg_t stcAdcCfg;
stc_adc_sqr_cfg_t stcAdcSqrCfg;
DDL_ZERO_STRUCT(stcAdcCfg);
Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);
Bgr_BgrEnable(); ///< 开启BGR
///< ADC 初始化配置
//adc每次转换单个通道需要24个时钟,adc采样频率是1m sps
//每次转换10个通道的adc数据,则每次顺序采样需要10个us
stcAdcCfg.enAdcMode = AdcScanMode; ///<采样模式-扫描
stcAdcCfg.enAdcClkDiv = AdcMskClkDiv1; ///<采样分频-1
stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle8Clk; ///<采样周期数-8
stcAdcCfg.enAdcRefVolSel = AdcMskRefVolSelAVDD; ///<参考电压选择-VCC
stcAdcCfg.enAdcOpBuf = AdcMskBufDisable; ///<OP BUF配置-关
stcAdcCfg.enInRef = AdcMskInRefDisable; ///<内部参考电压使能-关
stcAdcCfg.enAdcAlign = AdcAlignRight; ///<转换结果对齐方式-右
Adc_Init(&stcAdcCfg);
DDL_ZERO_STRUCT(stcAdcSqrCfg);
///< 顺序扫描模式功能及通道配置
///< 注意:扫描模式下,当配置转换次数为n时,转换通道的配置范围必须为[SQRCH(0)MUX,SQRCH(n-1)MUX]
//转换完成后触发dma
stcAdcSqrCfg.bSqrDmaTrig = TRUE;
stcAdcSqrCfg.enResultAcc = AdcResultAccDisable;
stcAdcSqrCfg.u8SqrCnt = 10;
Adc_SqrModeCfg(&stcAdcSqrCfg);
Adc_CfgSqrChannel(AdcSQRCH0MUX, AdcExInputCH0);
Adc_CfgSqrChannel(AdcSQRCH1MUX, AdcExInputCH1);
Adc_CfgSqrChannel(AdcSQRCH2MUX, AdcExInputCH2);
Adc_CfgSqrChannel(AdcSQRCH3MUX, AdcExInputCH3);
Adc_CfgSqrChannel(AdcSQRCH4MUX, AdcExInputCH4);
Adc_CfgSqrChannel(AdcSQRCH5MUX, AdcExInputCH5);
Adc_CfgSqrChannel(AdcSQRCH6MUX, AdcExInputCH6);
Adc_CfgSqrChannel(AdcSQRCH7MUX, AdcExInputCH7);
Adc_CfgSqrChannel(AdcSQRCH8MUX, AdcExInputCH8);
Adc_CfgSqrChannel(AdcSQRCH9MUX, AdcExInputCH9);
///< ADC 中断使能
Adc_EnableIrq();
EnableNvic(ADC_IRQn, IrqLevel3, TRUE);
///< 启动顺序扫描采样
Adc_SQR_Start();
}
//DMA参数配置
static void Dma_Config(void)
{
stc_dma_cfg_t stcDmaCfg;
DDL_ZERO_STRUCT(stcDmaCfg); //初始化变量
Sysctrl_SetPeripheralGate(SysctrlPeripheralDma,TRUE); //使能DMAC外设时钟门控开关
//rx dma配置
stcDmaCfg.u32SrcAddress = 0x40002450; //源地址
stcDmaCfg.u32DstAddress = (uint32_t)ADC_DATA.Conversion_Value; //目标地址
stcDmaCfg.enSrcAddrReloadCtl = DmaMskSrcAddrReloadEnable; //使能DMA源地址重载
stcDmaCfg.enSrcBcTcReloadCtl = DmaMskBcTcReloadEnable; //使能BC[3:0]和CONFA:TC[15:0]的重载功能
stcDmaCfg.enDestAddrReloadCtl = DmaMskDstAddrReloadEnable; //使能DMA目的地址重载
stcDmaCfg.enTransferMode = DmaMskContinuousTransfer; //连续传输,DMAC传输完成时不清除CONFA:ENS位
stcDmaCfg.enDstAddrMode = DmaMskDstAddrInc; //目的地址自增
stcDmaCfg.enSrcAddrMode = DmaMskSrcAddrInc; //源地址自增
//块传输个数,一共转换10个通道,所以设置为9个
stcDmaCfg.u16BlockSize = 10;
//块传输次数,只有1个块,所以只传输一次
stcDmaCfg.u16TransferCnt = 1;
stcDmaCfg.enMode = DmaMskBlock; //块(Block)传输
// 32 bit 字节传输,因为adc数据寄存器为32位,所以设置为32bit
stcDmaCfg.enTransferWidth = DmaMsk32Bit;
stcDmaCfg.enRequestNum = DmaADCSQRTrig; //DMA硬件触发源位Uart1Rx
stcDmaCfg.enPriority = DmaMskPriorityFix; //DMA 各通道优先级固定 (CH0>CH1)
Dma_Enable(); //DMA模块使能
Dma_InitChannel(DmaCh0, &stcDmaCfg); //DMA通道0初始化
Dma_EnableChannel(DmaCh0); //使能通道1
}
void ADC_Init(void)
{
Adc_Gpio_Config();
Adc_Config();
Dma_Config();
}
///< ADC interrupt service function
void ADC_IRQHandler(void)
{
//About 10us enters an interrupt
if(TRUE == Adc_GetIrqStatus(AdcMskIrqSqr))
{
Adc_ClrIrqStatus(AdcMskIrqSqr);
//After entering the interrupt, turn on the adc conversion again
Adc_SQR_Start();
}
}
///< ADC sampling port initialization
static void Adc_Gpio_Config(void)
{
///< Turn on ADC/BGR GPIO peripheral clock
Sysctrl_SetPeripheralGate (SysctrlPeripheralGpio, TRUE);
Gpio_SetAnalogMode (GpioPortA, GpioPin0); // PA00 (AIN0)
Gpio_SetAnalogMode (GpioPortA, GpioPin1); // PA01 (AIN1)
Gpio_SetAnalogMode (GpioPortA, GpioPin2); // PA02 (AIN2)
Gpio_SetAnalogMode (GpioPortA, GpioPin3); // PA03 (AIN3)
Gpio_SetAnalogMode (GpioPortA, GpioPin4); // PA04 (AIN4)
Gpio_SetAnalogMode (GpioPortA, GpioPin5); // PA05 (AIN5)
Gpio_SetAnalogMode (GpioPortA, GpioPin6); // PA06 (AIN6)
Gpio_SetAnalogMode (GpioPortA, GpioPin7); // PA07 (AIN7)
Gpio_SetAnalogMode (GpioPortB, GpioPin0); // PB00 (AIN8)
Gpio_SetAnalogMode (GpioPortB, GpioPin1); // PB01 (AIN9)
}
///< ADC module initialization
static void Adc_Config(void)
{
stc_adc_cfg_t stcAdcCfg;
stc_adc_sqr_cfg_t stcAdcSqrCfg;
DDL_ZERO_STRUCT(stcAdcCfg);
Sysctrl_SetPeripheralGate (SysctrlPeripheralAdcBgr, TRUE);
Bgr_BgrEnable(); ///< Turn on BGR
///< ADC initialization configuration
//Adc needs 24 clocks to convert a single channel each time, and the sampling frequency of adc is 1m sps
//Each conversion of 10 channels of adc data, each sequential sampling requires 10 us
stcAdcCfg.enAdcMode = AdcScanMode; ///<Sampling mode-scan
stcAdcCfg.enAdcClkDiv = AdcMskClkDiv1; ///<Sampling division -1
stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle8Clk; ///<Number of sampling cycles-8
stcAdcCfg.enAdcRefVolSel = AdcMskRefVolSelAVDD; ///<reference voltage selection-VCC
stcAdcCfg.enAdcOpBuf = AdcMskBufDisable; ///<OP BUF configuration-off
stcAdcCfg.enInRef = AdcMskInRefDisable; ///<Internal reference voltage enable-off
stcAdcCfg.enAdcAlign = AdcAlignRight; ///<Conversion result alignment-right
Adc_Init(&stcAdcCfg);
DDL_ZERO_STRUCT(stcAdcSqrCfg);
///< Sequential scan mode function and channel configuration
///< Note: In scan mode, when the configuration conversion times is n, the configuration range of the conversion channel must be [SQRCH(0)MUX,SQRCH(n-1)MUX]
//Trigger dma after the conversion is completed
stcAdcSqrCfg.bSqrDmaTrig = TRUE;
stcAdcSqrCfg.enResultAcc = AdcResultAccDisable;
stcAdcSqrCfg.u8SqrCnt = 10;
Adc_SqrModeCfg(&stcAdcSqrCfg);
Adc_CfgSqrChannel(AdcSQRCH0MUX, AdcExInputCH0);
Adc_CfgSqrChannel(AdcSQRCH1MUX, AdcExInputCH1);
Adc_CfgSqrChannel(AdcSQRCH2MUX, AdcExInputCH2);
Adc_CfgSqrChannel(AdcSQRCH3MUX, AdcExInputCH3);
Adc_CfgSqrChannel(AdcSQRCH4MUX, AdcExInputCH4);
Adc_CfgSqrChannel(AdcSQRCH5MUX, AdcExInputCH5);
Adc_CfgSqrChannel(AdcSQRCH6MUX, AdcExInputCH6);
Adc_CfgSqrChannel(AdcSQRCH7MUX, AdcExInputCH7);
Adc_CfgSqrChannel(AdcSQRCH8MUX, AdcExInputCH8);
Adc_CfgSqrChannel(AdcSQRCH9MUX, AdcExInputCH9);
///< ADC interrupt enable
Adc_EnableIrq();
EnableNvic(ADC_IRQn, IrqLevel3, TRUE);
///< Start sequential scan sampling
Adc_SQR_Start();
}
//DMA parameter configuration
static void Dma_Config(void)
{
stc_dma_cfg_t stcDmaCfg;
DDL_ZERO_STRUCT(stcDmaCfg); //Initialize variables
Sysctrl_SetPeripheralGate(SysctrlPeripheralDma,TRUE); //Enable DMAC peripheral clock gating switch
//rx dma configuration
stcDmaCfg.u32SrcAddress = 0x40002450; //Source address
stcDmaCfg.u32DstAddress = (uint32_t)ADC_DATA.Conversion_Value; //Target address
stcDmaCfg.enSrcAddrReloadCtl = DmaMskSrcAddrReloadEnable; //Enable DMA source address reload
stcDmaCfg.enSrcBcTcReloadCtl = DmaMskBcTcReloadEnable; //Enable the reload function of BC[3:0] and CONFA:TC[15:0]
stcDmaCfg.enDestAddrReloadCtl = DmaMskDstAddrReloadEnable; //Enable DMA destination address reload
stcDmaCfg.enTransferMode = DmaMskContinuousTransfer; //Continuous transfer, the CONFA:ENS bit is not cleared when the DMAC transfer is completed
stcDmaCfg.enDstAddrMode = DmaMskDstAddrInc; //Destination address self-increment
stcDmaCfg.enSrcAddrMode = DmaMskSrcAddrInc; //source address self-increment
//The number of block transfers, a total of 10 channels are converted, so it is set to 9
stcDmaCfg.u16BlockSize = 10;
//The number of block transfers, there is only 1 block, so only transfer once
stcDmaCfg.u16TransferCnt = 1;
stcDmaCfg.enMode = DmaMskBlock; //Block transmission
// 32 bit byte transmission, because the adc data register is 32 bits, it is set to 32bit
stcDmaCfg.enTransferWidth = DmaMsk32Bit;
stcDmaCfg.enRequestNum = DmaADCSQRTrig; //DMA hardware trigger source bit Uart1Rx
stcDmaCfg.enPriority = DmaMskPriorityFix; //The priority of each DMA channel is fixed (CH0>CH1)
Dma_Enable(); //DMA module enable
Dma_InitChannel(DmaCh0, &stcDmaCfg); //DMA channel 0 initialization
Dma_EnableChannel(DmaCh0); //Enable channel 1
}
void ADC_Init(void)
{
Adc_Gpio_Config();
Adc_Config();
Dma_Config();
}