想学会如何在STM8上使用ADC这个功能,我们先得了解单片机中ADC究竟是什么。

ADC是模拟信号转成数值信号,单片机只能识别TTL电平,其实就是 1 或者 0 ,但是如果我们给它一个3.3V电压,单片机就无法识别,,若想使用单片机读取出来得时候,它必须将模拟量变成数字量。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

了解完后,我们就开始讲解了。

 

编译环境:

我的编译环境是IAR,这款软件是现在STM8的主流平台,比较推荐。不过我打算等到STCubeMX更新出比较方便的版本后再去使用Keil5,因为我在用STM32的时候就是利用Keil5,的确很方便,你们也可以学着用一下。

 

主芯片:

我的主芯片是STM8S系列中的003,其中STM8S的003、005、和103、105,配置一样(外设和CPU频率,FLASH),在代码相同的情况下均可进行烧写。

 

库文件的添加:

我们的工程可以在IAR的例程中复制,操作过程:打开STM8S_StdPeriph_Lib(这是一个官方的库文件,下载IAR STM8包的时候就携带,里面有库文件和相对应的例程),将Libraries文件复制到你工程所在的文件下,并将里面的库函数添加到你的IAR工程列表当中,如图。

基于STM8的ADC读取 随笔 第1张

添加完成后,有可能你会看到一些C文件会有红色的小点报错,这是因为你选的芯片上没有该功能,你需要将其删掉才能不报错。

添加成功后,我们需要将头文件添加进来,如图。

基于STM8的ADC读取 随笔 第2张

 

你们也可以跟我一样,将不同功能的函数分开写成C文件和H文件,如图。

基于STM8的ADC读取 随笔 第3张

 

 

代码编写:

首先,我们需要配置一下内部晶振,并且初始化你所要使用的GPIO、串口。其次,配置ADC,最后对ADC读取函数的进行一个调用,获取ADC值,再用Uart输出。

 

晶振配置:

将所有的晶振幅值都写成枚举,这样的话可以直接通过在主函数调用再传参改变它的晶振大小。

 1 void Clk_Config(uint8_t SYS_CLOCK)
 2 { 
 3   switch(SYS_CLOCK)
 4   {
 5     case  SYS_CLOCK_2MHZ : CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8); break;
 6     case  SYS_CLOCK_4MHZ : CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV4); break;
 7     case  SYS_CLOCK_8MHZ : CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2); break;
 8     case  SYS_CLOCK_16MHZ: CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); break;
 9     default:                                                              break;  
10   }
11 }

 

GPIO配置:

这里将一些所要用到基础的的引角初始化,特殊的GPIO口我们就另外再说。

1 void MX_GPIO_Init(void)
2 {
3   //LED
4   GPIO_Init(Led_Opt_GPIO_Port,Led_Opt_Pin, GPIO_MODE_OUT_PP_HIGH_FAST);
5 
6 }

 

Uart配置:

在STM8S003中,Uart只有 Uart1 可用,所以在这里就只使用这个。将Uart的发送、接收引角在Uart初始化函数里面初始,主要的配置参数为:115200波特率、1个停止位、无奇偶校验位、同步模式禁用、SLK PIN禁用、发送和接收都开启。

调用UART1_ITConfig( )函数令Uart开启中断。

 1 void MX_UART1_Init(void)
 2 {
 3   UART1_DeInit();
 4   GPIO_Init(Uart_TX_GPIO_Port, Uart_TX,GPIO_MODE_OUT_PP_HIGH_FAST);
 5   GPIO_Init(Uart_RX_GPIO_Port, Uart_RX,GPIO_MODE_IN_PU_IT);  
 6   UART1_Init(115200,UART1_WORDLENGTH_8D,UART1_STOPBITS_1,UART1_PARITY_NO,UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TXRX_ENABLE);
 7   UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE);
 8   UART1_Cmd(ENABLE);//启用串口
 9   
10   enableInterrupts(); 
11 }

 

ADC:

STM8SF003这款芯片能用的是5个AD采样通道,分别为为AIN2~AIN6。其一个通道AIN7,但在官方手册中我没找到有对其描述的,感兴趣的朋友可以去察看芯片的英文手册进行研究,也许会找到和我不一样的结果。

在ADC头文件中,将ADC1所有的ADC1_CHANNEL(ADC通道)都进行枚举,以方便调用。

 1 /* Enum ----------------------------------------------------------------------*/
 2 
 3 enum ADC1_CHANNEL
 4 {                                        //bit  8  7  6  5  4  3  2  1
 5   
 6     ADC1_CHANNEL2 = 0x01,                //     0  0  0  0  0  0  0  1
 7     ADC1_CHANNEL3 = 0x02,                //     0  0  0  0  0  0  1  0
 8     ADC1_CHANNEL4 = 0x04,                //     0  0  0  0  0  1  0  0
 9     ADC1_CHANNEL5 = 0x08,                //     0  0  0  0  1  0  0  0
10     ADC1_CHANNEL6 = 0x10                 //     0  0  0  1  0  0  0  0
11         
12 };  

在ADC.C文件中,分为了多个函数,降低他们的耦合性,也方便理解。

首先是ADC中引角的初始化,将你所选通道的引角进行初始化,没有选到的就不进行初始化。

 1 /*******************************************************************************
 2 * Function Name  : MX_ADC_GPIO_Init
 3 * Description    : ADC GPIO Init
 4 * Input          : ADC1_CHANNEL
5 * Output : None 6 * Return : None 7 ********************************************************************************/ 8 9 void MX_ADC_GPIO_Init(uint8_t ADC1_CHANNEL) 10 { 11 switch(ADC1_CHANNEL) 12 { 13 case ADC1_CHANNEL2: GPIO_Init(ADC_Opt_GPIOC_Port,ADC_channe2_Pin,GPIO_MODE_IN_PU_NO_IT);break; 14 case ADC1_CHANNEL3: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe3_Pin,GPIO_MODE_IN_PU_NO_IT);break; 15 case ADC1_CHANNEL4: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe4_Pin,GPIO_MODE_IN_PU_NO_IT);break; 16 case ADC1_CHANNEL5: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe5_Pin,GPIO_MODE_IN_PU_NO_IT);break; 17 case ADC1_CHANNEL6: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe6_Pin,GPIO_MODE_IN_PU_NO_IT);break; 18 } 19 20 }

 

然后是ADC1的选择通道初始化:ADC连续读取,所选的通道,二分频,外部转换触发,外部触发器不开启,数据右对齐,施密特触发,不开启。(注意:STMS8003中的串口使用了PD5和PD6,与ADC1中通道5、通道6发生冲突,故不可使用。如需使用,请将串口的TX\RX引角更改换为其它的引角。

 1 /*******************************************************************************
 2 * Function Name  : MX_ADC1_CHANNEL_Init
 3 * Description    : ADC CHANNEL Init
 4 * Input          : ADC1_CHANNEL
 5 * Output         : None
 6 * Return         : None
 7 ********************************************************************************/
 8 
 9 void MX_ADC1_CHANNEL_Init(uint8_t ADC1_CHANNEL)
10 {
11   switch(ADC1_CHANNEL)
12   {
13     case ADC1_CHANNEL2: 
14     {
15        ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_2, 
16        ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 
17        ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL2, DISABLE);break;
18     }
19     case ADC1_CHANNEL3:
20     {
21        ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_3, 
22        ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 
23        ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL3, DISABLE);break;
24     }
25     case ADC1_CHANNEL4:
26     {
27        ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_4, 
28        ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 
29        ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL4, DISABLE);break;
30     } 
31     case ADC1_CHANNEL5:
32     {
33        ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_5, 
34        ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 
35        ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL5, DISABLE);break;
36     }
37     case ADC1_CHANNEL6:
38     {
39        ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_6, 
40        ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 
41        ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL6, DISABLE);break;
42     }
43   } 
44 }

 

这里就是将所有的ADC初始化进行一个统一的一个归类。

 1 /*******************************************************************************
 2 * Function Name  : MX_ADC1_Init
 3 * Description    : ADC Init
 4 * Input          : ADC1_CHANNEL
 5 * Output         : None
 6 * Return         : None
 7 ********************************************************************************/
 8 void MX_ADC1_Init(uint8_t ADC1_CHANNEL)
 9 {  
10   //初始化GPIO
11   MX_ADC_GPIO_Init(ADC1_CHANNEL);
12   
13   //初始化ADC1所有寄存器
14   ADC1_DeInit();
15   
16   //配置ADC1寄存器中的参数
17   MX_ADC1_CHANNEL_Init(ADC1_CHANNEL);
18   
19   //使能ADC1
20   ADC1_Cmd(ENABLE);
21   
22   //ADC1转换开始
23   ADC1_StartConversion();
24 }

 

最后就是数据获取,可以选择直接获取数据,也可以获取十次数据后取平均数。

注意:

ADC获取的值是AD值,需要将其进行代入公式中才能得到电压值。

Vin = (ADC * Vref) / 1024

VCC很明显可以使用万用表先测出来,1024是因为STM8S这款的AD是10位精度。

这里测试的VCC是3.35V,VCC另外一个意思就是单片机的供给电源。

 1 /*******************************************************************************
 2 * Function Name  : MX_ADC1_Get_Data
 3 * Description    : get VCC data
 4 * Input          : None
 5 * Output         : None
 6 * Return         : fVCC
 7 ********************************************************************************/
 8 float MX_ADC1_Get_Data(void)
 9 {
10   int iADC1_Value;
11   float fVCC;
12   
13   //读取转换结果
14   iADC1_Value = ADC1_GetConversionValue();
15   fVCC = (iADC1_Value * 3.350)/1024;
16   return fVCC;
17   
18 }
19 
20 
21 /*******************************************************************************
22 * Function Name  : MX_ADC1_Get_Average_Data
23 * Description    : Get VCC ten times average data. 
24 * Input          : None
25 * Output         : None
26 * Return         : fAverage_VCC
27 ********************************************************************************/
28 float MX_ADC1_Get_Average_Data(void)
29 {
30   int i;
31   float fAverage_VCC = 0.0;
32   
33   for(i=0;i<10;i++)
34   {
35    fAverage_VCC += MX_ADC1_Get_Data();
36   }
37   fAverage_VCC /= 10;
38   
39   return fAverage_VCC;
40   
41 }

将上面需要用到的函数在主函数中调用打印即可。

 

测试结果:

我用的调试仪器是可调式电源,可通过旋钮控制电压的输出大小。

当没有输出电压时,打印的值为0V.

基于STM8的ADC读取 随笔 第4张

当可调式电源输出的电压值为3.3V,串口助手上打印的也是3.3V。

基于STM8的ADC读取 随笔 第5张基于STM8的ADC读取 随笔 第6张

 

当可调式电源输出的电压值为24V,串口助手上打印的也是24V。

注意:请不要将24V电源直接通入单片机中,我是自己设置了一条电路进行测试的。ADC的最大输入电压是3.3V,为了安全起见,请不要超过该值。

注意:请不要将24V电源直接通入单片机中,我是自己设置了一条电路进行测试的。ADC的最大输入电压是3.3V,为了安全起见,请不要超过该值。

注意:请不要将24V电源直接通入单片机中,我是自己设置了一条电路进行测试的。ADC的最大输入电压是3.3V,为了安全起见,请不要超过该值。

基于STM8的ADC读取 随笔 第7张基于STM8的ADC读取 随笔 第8张

 

基于STM8的ADC读取说明到此结束,感谢大家观看。

 

作 者:浩宇99✌
出 处: https://www.cnblogs.com/zhenghaoyu/p/10672864.html
版权声明:本文原创发表于 博客园,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄