zoukankan      html  css  js  c++  java
  • 基于STM8的ADC读取---STM8-第四章

    1. 综诉

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

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

     

    2. 关于STM8S103手册的ADC简介

     

    由官方的全英手册可知。

    ----------------------------------------------------------------------------------------------------------------------------------

    STM8中ADC1和ADC2主要功能如下:

    • 10位分辨率
    • 单词和连续的转换模式
    • 可编程的(转换频率的)预分频,fMASTER 可以被分频 2到18
    • 可选择ADC专用外部中断(ADC_ETR)或者定时器触发信号(TRGO)来作为外部触发信号
    • 模拟放大(对于具有VREF引角的型号)
    • 转换结束时可产生中断
    • 灵活的数据对齐方式
    • ADC输入电压范围:VSSA≤VIN≤VDDA

    ----------------------------------------------------------------------------------------------------------------------------------

    ADC1具有以下拓展功能:

    • 带缓冲的连续转换模式
    • 单次和连续转换的扫描模式
    • 具有上限和下限门槛的模拟看门狗
    • 模拟看门狗时间发生可产生中断

    ----------------------------------------------------------------------------------------------------------------------------------

    3. 例程

    3.1 编译环境

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

     

    3.2 主芯片

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

     

    3.3 库文件的添加

      我们的工程可以在IAR的例程中复制,操作过程:打开STM8S_StdPeriph_Lib(这是一个官方的库文件,下载IAR STM8包的时候就携带,里面有库文件和相对应的例程),将Libraries文件复制到你工程所在的文件下,并将有关于ADC的库文件添加到你的工程列表当中。添加完成后,有可能你会看到一些C文件会有红色的小点报错,这是因为你选的芯片上没有该功能,你需要将其删掉才能不报错。如图。

     

    添加成功后,我们需要将头文件添加进来,头文件的路径存放在 Libraries->STM8S_StdPeriph_Driver->inc中,如图。 

     

     

    3.4 代码编写

      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发生冲突,故不可使用。如需使用,请将串口的TXRX引角更改换为其它的引角。

     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 }

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

    4. 实验结果

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

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

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

     

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

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

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

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

    5. 结尾

    对STM8的ADC的说明和引用到这里结束,感谢各位看官的点击。

    如果觉得有所收获请点下推荐,若认为该博客中存在错误的说明或者对博客中某方面有疑问请留言。

    作 者:浩宇99✌
    出 处:https://www.cnblogs.com/zhenghaoyu/p/10672864.html
    版权声明:本文原创发表于 博客园,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
  • 相关阅读:
    解决:Server IPC version 9 cannot communicate with client version 4
    解决Exception: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z
    hadoop解决windows下:Failed to set permissions of path: mp .staging to 0700
    find命令的使用
    linux解决端口冲突问题
    linux中实用的小工具lrzsz
    nginx常用命令
    编写测试用例的方法
    selenium之web自动化模拟操作(窗口,鼠标,键盘,js)
    什么是面向连接服务?什么是无连接服务?它们的区别是什么?
  • 原文地址:https://www.cnblogs.com/zhenghaoyu/p/10672864.html
Copyright © 2011-2022 走看看