HDL136 adc采用dma方式来采样的方式和Stm32相差不多,但是目前使用下来,感觉华大芯片的adc软件触发比较鸡肋,每次启动之后只能进行一次转换,要进行持续的转换需要在adc转换完成中断之后再次启动adc转换。而stm32的adc软件触发之后就可以持续不断的进行转换,除非进行停止操作。
///< 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中断服务函数
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();
}