chipon芯旺微KF32A156/150系列ADC模块的使用教程
请尊重原创,转载需要注明源出处!!!
hello大家好,今天主要来说一下芯旺微32位机的AD模块的使用。本篇文章较长,如有需要不同模式,请耐心仔细看完。首先看一下官方手册提供的AD模块的简介:
可以看到,AD模块对于常规的使用完全能够覆盖。我们最常用的也就是普通AD通道的采样方式。
AD普通通道同一个ADC模块可以同时配置16个普通通道和4个高优先级通道,在我们使用过程中,不建议两种通道混合使用,本篇以普通通道来讲解。
本次主要讲解三种模式:单通道采样,单通道循环采样,多通道单次扫描采样,多通道循环扫描采样。
说在前面:首先AD电路采样电压不建议超过VDDA的电压。
在进行软件配置之前:
首先要对引脚是否能够实现进行确认。通过数据手册的 模拟功能引脚表 进行查询,如图1
通过上图可以看到,144pin的第36脚可实现AD通道号96(ADC_CH96)。第44脚就无法实现AD通道的配置。
正文
使用说明:pin脚上的AD通道是属于硬件通道,这个标号是固定的,比如ADC_CH96,在每个ADC模块进行配置的时候,还需要进行配置采样通道标号(也就是前面说的一个ADC模块最多只能配置16个普通采样通道)。这个是通过软件自行配置。在后面的讲解中有所涉及,需要进行区分。
一、单通道采样配置(以PA1为例,轮询的方式查询结果),此模式触发一次开始采一个通道结束。
老三步:配置引脚,配置外设,配置中断。
1、进行引脚模式配置:配置为模拟端口
GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); ADC_CH66
2、AD模块配置,这里关键参数,时钟,扫描模式失能,循环模式失能,触发源全部失能,通道长度为1,配置1个通道顺序号
ADC_InitTypeDef adcStruct;
ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟
/* 初始化 ADC时钟源选择 */
adcStruct.m_Clock = ADC_HFCLK;
/* 初始化 ADC时钟分频 */
adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
/* 初始化 ADC扫描模式使能 */
adcStruct.m_ScanMode = FALSE; //扫描模式,一次触发只转换第一个通道
/* 初始化 ADC连续转换模式 */
adcStruct.m_ContinuousMode = ADC_SINGLE_MODE; //不使用连续转换功能,只对设置的通道采样一遍
/* 初始化 ADC转换结果输出格式 */
adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
/* 初始化 ADC常规通道外部触发转换模式使能 */
adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
/* 初始化 ADC常规通道外部触发事件 */
adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
/* 初始化 ADC高优先级通道外部触发转换模式使能 */
adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
/* 初始化 高优先级通道外部触发事件 */
adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
/* 初始化 ADC常规通道扫描长度 */
adcStruct.m_NumOfConv = 1; //扫描的长度配置为1个通道
/* 初始化 ADC高优先级通道扫描长度 */
adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
ADC_Configuration (ADC0_SFR, &adcStruct);
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
ADC_Cmd (ADC0_SFR, TRUE); //ADC使能
3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收:
unsigned short adc_value ;
/*software triger adc Conversion*/
ADC_Software_Start_Conv(ADC0_SFR);
/*wait for the adc conversion to complete*/
while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
{
;
}
/*sampling GPIO PG4 adc value */
adc_value = ADC_Get_Conversion_Value(ADC0_SFR);
提示:如果是使用中断,只需要将adc和adc的EOC中断打开即可,也就是单次采样结束中断。
二、单通道循环采样配置(以PA1为例,轮询的方式查询结果),此模式触发一次开始一直不间断采一个通道
1、进行引脚模式配置:配置为模拟端口
GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); //ADC_CH66
2、AD模块配置,这里关键参数,时钟,扫描模式失能,循环模式使能,触发源全部失能,通道长度为1,配置1个通道顺序号
ADC_InitTypeDef adcStruct;
ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟
/* 初始化 ADC时钟源选择 */
adcStruct.m_Clock = ADC_HFCLK;
/* 初始化 ADC时钟分频 */
adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
/* 初始化 ADC扫描模式使能 */
adcStruct.m_ScanMode = FALSE; //扫描模式,一次触发只转换第一个通道
/* 初始化 ADC连续转换模式 */
adcStruct.m_ContinuousMode = ADC_CONTINUOUS_MODE; //不使用连续转换功能,只对设置的通道采样一遍
/* 初始化 ADC转换结果输出格式 */
adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
/* 初始化 ADC常规通道外部触发转换模式使能 */
adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
/* 初始化 ADC常规通道外部触发事件 */
adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
/* 初始化 ADC高优先级通道外部触发转换模式使能 */
adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
/* 初始化 高优先级通道外部触发事件 */
adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
/* 初始化 ADC常规通道扫描长度 */
adcStruct.m_NumOfConv = 1; //扫描的长度配置为1个通道
/* 初始化 ADC高优先级通道扫描长度 */
adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
ADC_Configuration (ADC0_SFR, &adcStruct);
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
ADC_Cmd (ADC0_SFR, TRUE); //ADC使能
3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收,注意,普通通道AD通道采样后数据放在同一个寄存器,故而当上一个采样完成后应及时取走。
unsigned short adc_value ;
/*software triger adc Conversion*/
ADC_Software_Start_Conv(ADC0_SFR);
/*wait for the adc conversion to complete*/
while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
{
;
}
/*sampling GPIO PG4 adc value */
adc_value = ADC_Get_Conversion_Value(ADC0_SFR);
三、多通道单次扫描采样(以PA1/PE7为例,轮询的方式查询结果),此模式触发一次开始采2个通道后结束。
1、进行引脚模式配置:配置为模拟端口
GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); //ADC_CH66
GPIO_Write_Mode_Bits (GPIOB_SFR,GPIO_PIN_MASK_7, GPIO_MODE_AN); //ADC_CH67
2、AD模块配置,这里关键参数,时钟,扫描模式使能,循环模式失能,触发源全部失能,通道长度为2。配置2个通道顺序号
ADC_InitTypeDef adcStruct;
ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟
/* 初始化 ADC时钟源选择 */
adcStruct.m_Clock = ADC_HFCLK;
/* 初始化 ADC时钟分频 */
adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
/* 初始化 ADC扫描模式使能 */
adcStruct.m_ScanMode = TRUE; //扫描模式,一次触发只转换第一个通道
/* 初始化 ADC连续转换模式 */
adcStruct.m_ContinuousMode = ADC_SINGLE_MODE; //不使用连续转换功能,只对设置的通道采样一遍
/* 初始化 ADC转换结果输出格式 */
adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
/* 初始化 ADC常规通道外部触发转换模式使能 */
adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
/* 初始化 ADC常规通道外部触发事件 */
adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
/* 初始化 ADC高优先级通道外部触发转换模式使能 */
adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
/* 初始化 高优先级通道外部触发事件 */
adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
/* 初始化 ADC常规通道扫描长度 */
adcStruct.m_NumOfConv = 2; //扫描的长度配置为1个通道
/* 初始化 ADC高优先级通道扫描长度 */
adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
ADC_Configuration (ADC0_SFR, &adcStruct);
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_67, 0x02);
ADC_Cmd (ADC0_SFR, TRUE); //ADC使能
3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收:注意,普通通道AD通道采样后数据放在同一个寄存器,故而当上一个采样完成后应及时取走。
unsigned short adc_value ;
/*software triger adc Conversion*/
ADC_Software_Start_Conv(ADC0_SFR);
/*wait for the adc conversion to complete*/
while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
{
;
}
/*sampling GPIO PG4 adc value */
adc_value = ADC_Get_Conversion_Value(ADC0_SFR);
四、多通道单次扫描采样(以PA1/PE7为例,轮询的方式查询结果),此模式触发一次开始不间断采2个通道。
1、进行引脚模式配置:配置为模拟端口
GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); //ADC_CH66
GPIO_Write_Mode_Bits (GPIOB_SFR,GPIO_PIN_MASK_7, GPIO_MODE_AN); //ADC_CH67
2、AD模块配置,这里关键参数,时钟,扫描模式使能,循环模式使能,触发源全部失能,通道长度为2。配置2个通道顺序号
ADC_InitTypeDef adcStruct;
ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟
/* 初始化 ADC时钟源选择 */
adcStruct.m_Clock = ADC_HFCLK;
/* 初始化 ADC时钟分频 */
adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
/* 初始化 ADC扫描模式使能 */
adcStruct.m_ScanMode = TRUE; //扫描模式,一次触发只转换第一个通道
/* 初始化 ADC连续转换模式 */
adcStruct.m_ContinuousMode = ADC_CONTINUOUS_MODE; //不使用连续转换功能,只对设置的通道采样一遍
/* 初始化 ADC转换结果输出格式 */
adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
/* 初始化 ADC常规通道外部触发转换模式使能 */
adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
/* 初始化 ADC常规通道外部触发事件 */
adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
/* 初始化 ADC高优先级通道外部触发转换模式使能 */
adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
/* 初始化 高优先级通道外部触发事件 */
adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
/* 初始化 ADC常规通道扫描长度 */
adcStruct.m_NumOfConv = 2; //扫描的长度配置为1个通道
/* 初始化 ADC高优先级通道扫描长度 */
adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
ADC_Configuration (ADC0_SFR, &adcStruct);
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_67, 0x02);
ADC_Cmd (ADC0_SFR, TRUE); //ADC使能
3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收:注意,普通通道AD通道采样后数据放在同一个寄存器,故而当上一个采样完成后应及时取走。
unsigned short adc_value ;
/*software triger adc Conversion*/
ADC_Software_Start_Conv(ADC0_SFR);
/*wait for the adc conversion to complete*/
while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
{
;
}
/*sampling GPIO PG4 adc value */
adc_value = ADC_Get_Conversion_Value(ADC0_SFR);
以上就是ADC的基本使用了。
总结:使用中断来取普通通道转换的数据的方式也都是可以的,芯旺微提供了两个中断源来进行使用,一次采样完成中中断,全部采样完成中断。可以根据自身需求进行选择。
建议:当我们使用多通道扫描或者循环采样的时候,尽可能选择DMA搬运的方式,一来节省CPU资源,二来也能及时的取走数据的以免被下一次的采样数据覆盖导致错误数据。 DMA搬运的方式后续再更。可自行研究一下。
好啦,本次ADC使用就讲解完了。如有待完善的点,欢迎指正。
本次更新时间:2023.12.15