作者:马一飞 QQ:791729359
在学习过程中有什么问题可以联系
(原本资料是以网盘的方式公开提供给任何蓝桥杯爱好者进行下载的,但是最近临近蓝桥杯考试,遇到了很多伸手党,我无偿给爱好者们解答学习上的问题,回复得比较慢居然还有同学来说我这样那样,所以决定不再随意提供自己写的源码和资料。博主已经开始参加工作了,也不是闲着没事干盯着电脑手机为你们服务。记住,不要成为伸手党,要自己多动手实现。)
大家都已经学到嵌入式了,那么就应该清楚什么叫ADC。ADC就是模数转换,把模拟的电压信号,转化为我们控制器所能识别的数字信号,这就叫ADC。
那么我就来讲解CT117E开发板的ADC是怎么配置的。我们先观察一下CT117E开发板上的外设资源,我们能看到,在LED旁边有一个可变电阻器,那个可变电阻器就是拿来做ADC检测实验的。
其次,我们再找到电路图变阻器所对应的引脚。
我们能看到这个可变电阻的另一端连接的是PB0引脚,同时我们查看下stm32f103rbt6的数据手册,发现PB0引脚可复用成ADC_IN8。
我们可以通过软件把PB0设置成ADC输入引脚,就可以采集PB0引脚上的电压数据了。
那么我们开始对这个引脚进行编程,我们当然要先对PB0引脚进行初始化设置为模拟输入,同时还要吧PB时钟和ADC1时钟使能。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); 这条语句的作用实际上就是对ADC时钟进行6分频,实际上我们不添加这条语句也可以,因为ADC时钟过快的话,可能会导致测得的AD值不准确,但是我们的蓝桥杯比赛倒不会影响,我的个人是习惯加上分频系数。(这个函数在RCC库函数里可以找到原型)
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1,&ADC_InitStructure);
在配置好引脚之后,我们就可以开始对ADC进行配置了,我们在蓝桥杯的比赛中,只需要开启独立模式就OK了,我们并不需要用到连续转换模式,因此我们要把连续转换模式关闭,数据右对齐。 我们对stm32的ADC还要有一个概念,stm32的ADC分为规则组和注入组,具体两个类别有什么不同可以看看正点原子官方关于ADC的视频。但是我们对于蓝桥杯所用的ADC就比较简单,大家只需要按照我上面那样配置就可以了。
在配置好ADC后我们还需要对ADC进行一个校准,具体的校准过程也比较简单。
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus( ADC1));
ADC_StartCalibration( ADC1);
while(ADC_GetCalibrationStatus(ADC1));
先复位校正,再开启校正。 有一点是需要注意的,我们在对ADC校准的前,必须把ADC使能ADC_Cmd(ADC1, ENABLE); 否则将卡在校准处程序卡死。
ADC1初始化完毕,那我们应该如何读取AD值呢?
u16 Get_Adc(u8 channel)
{
u16 temp;
ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd( ADC1,ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0);
temp = ADC_GetConversionValue( ADC1);
ADC_SoftwareStartConvCmd( ADC1,DISABLE);
return temp;
}
我们先使用规则组通道初始化这个库函数来对ADC通道配置
第一个入口参数为选的配置的ADC,第二个入口参数为选择配置的通道,第三个入口参数则配置ADC编号(例如使用ADC1,那么就写1),第四个入口参数则代表单次采样的时钟周期数。
我们就直接选择最大的周期(239周期),因为周期数越大,采样出来的信号就约准确,蓝桥杯比赛中并没有对速度的要求,因此我们确保采样准确。
而后我们就可以通过程序软件启动AD转换。
我们开启转换后,我们通过EOC标志位来判断转换是否完成。
我们查看stm32中文参考手册(第170页)
当AD转换完成后,EOC标志位会置1,当我们AD转换未完成时,我们就一直等待,直到ADC采样结束后才读取AD数据。
采样结束后就可以通过获取ADC数据库函数对数据进行读取,在读取前我们还得知道,stm32f103rbt6的ADC是精度是12位了(也就是0~4096),因此我们读出来的AD值数据是12位的,用通俗的话来讲就是把3.3V分成4096份。
然后返回AD值,那么我们一个ADC采样函数就写好了,我们可以对PB0引脚进行AD采样。
在主函数中:
我们用定时器先设定每500ms读取一次AD值。 我们事先知道PB0引脚对应的是第8通道,我们直接Get_Adc(8)即可获取PB0的AD值。
我们再把获取出来的AD值经过公式换算成电压值,显示到我们的LCD显示屏上。
我们把程序烧录到开发板里看看。
转动可变电阻,我们发现ADC的值随着我们的转动而改变,那么我们这个ADC采样程序是没有问题了。
(以上仅属于个人观点)