标题: 51单片机入门经验分享6-利用STC单片机的ADC采集电压 [打印本页]

作者: dabing89    时间: 2018-10-13 09:10
标题: 51单片机入门经验分享6-利用STC单片机的ADC采集电压
利用STC单片机的ADC采集电压


在实际开发中,AD,DA用的相当多,这一节,我们写一个程序,将采集到的电压数值显示在数码管上,程序如下:
  1. /*******************************************************************************
  2. * 文件名: ADC转换器使用
  3. * 描  述: 电池电压
  4. * 功  能:中断方式 11.059200MHZ
  5. * 作  者:大核桃
  6. * 版本号:1.0.1(2017.05.23)
  7. *******************************************************************************/
  8. #include "stc15w.h"//头文件
  9. #include "intrins.h"


  10. /*******************************************************************************
  11. * 文件名: 重定义
  12. * 描  述:   
  13. * 功  能:
  14. * 作  者:大核桃
  15. * 版本号:1.0.1(2017.05.23)
  16. *******************************************************************************/
  17. typedef unsigned char uint8;
  18. typedef unsigned int  uint16;
  19. typedef unsigned long uint32;

  20. #define ADC_POWER   0x80            //ADC电源控制位
  21. #define ADC_FLAG    0x10            //ADC完成标志
  22. #define ADC_START   0x08            //ADC起始控制位
  23. #define ADC_SPEEDLL 0x00            //540个时钟

  24. /*******************************************************************************
  25. * 文件名:全局变量定义区域
  26. * 描  述:
  27. * 功  能:
  28. * 作  者:大核桃
  29. * 版本号:1.0.1(2015.03.03)
  30. *******************************************************************************/
  31. uint8 val,ch;
  32. uint16 temp;
  33. /*******************************************************************************
  34. * 文件名:共阳数码管真值表
  35. * 描  述:
  36. * 功  能:
  37. * 作  者:大核桃
  38. * 版本号:1.0.1(2015.03.03)
  39. *******************************************************************************/
  40. code uint8 LedChar[] = {
  41.         0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
  42.         0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xc1
  43. };

  44. /*******************************************************************************
  45. * 文件名:单独位定义
  46. * 描  述:   
  47. * 功  能:
  48. * 作  者:大核桃
  49. * 版本号:1.0.1(2017.05.23)
  50. *******************************************************************************/
  51. sbit LED0 = P1^0;//第1组LED
  52. sbit LED1 = P1^1;//第2组LED
  53. sbit LED2 = P1^2;//第3组LED                                 
  54. sbit LED3 = P1^3;//第4组LED
  55. sbit LED4 = P1^4;//第5组LED
  56. sbit LED5 = P3^2;//第6组LED
  57. sbit LED6 = P0^0;//第7组LED
  58. sbit LED7 = P0^1;//第8组LED

  59. sbit LEDS1 = P3^3;//数码管1
  60. sbit LEDS2 = P3^4;//数码管2
  61. sbit LEDS3 = P3^6;//数码管3
  62. sbit LEDS4 = P3^7;//数码管4

  63. /*******************************************************************************
  64. * 文件名:函数前置声明
  65. * 描  述:   
  66. * 功  能:
  67. * 作  者:大核桃
  68. * 版本号:1.0.1(2017.05.23)
  69. *******************************************************************************/
  70. void Mcu_Port_Init();
  71. void LedScan();
  72. void Delay500ms(); //24MHZ
  73. void Time0_Init();//定时器0
  74. void InitADC(void);

  75. /*******************************************************************************
  76. * 文件名
  77. * 描  述: 主函数  
  78. * 功  能:入口
  79. * 作  者:大核桃
  80. * 版本号:1.0.1(2017.05.23)
  81. *******************************************************************************/
  82. void main(void)
  83. {                                       
  84.         Mcu_Port_Init();//IO上电初始化
  85.         Time0_Init();
  86.         InitADC();
  87.         while(1);
  88. }

  89. /*******************************************************************************
  90. * 文件名:void LedScan()
  91. * 描  述: LED刷新
  92. * 功  能:
  93. * 作  者:大核桃
  94. * 版本号:1.0.1(2017.05.23)
  95. *******************************************************************************/
  96. void LedScan()
  97. {
  98.         static uint8 i = 0;

  99.         P2 = 0Xff;
  100.         switch(i)
  101.         {
  102.                 case 0: LEDS4 = 0;LEDS1 = 1;P2 = 0x7f & LedChar[16];i++;break;
  103.                 case 1: LEDS1 = 0;LEDS2 = 1;P2 = LedChar[val / 10 % 10];i++;break;
  104.                 case 2: LEDS2 = 0;LEDS3 = 1;P2 = LedChar[val % 10];i++;break;
  105.                 case 3: LEDS3 = 0;LEDS4 = 1;P2 = LedChar[17];i = 0;break;

  106.                 default:break;
  107.         }
  108. }

  109. /*******************************************************************************
  110. * 文件名:void InitADC(void)
  111. * 描  述: //初始化 AD 转换
  112. * 功  能:
  113. * 作  者:大核桃
  114. * 版本号:1.0.1(2015.03.03)
  115. *******************************************************************************/
  116. void InitADC(void)
  117. {
  118.         P1ASF = 0xE0; //设置 P1 口为模拟口
  119.         ADC_RES = 0; //清除结果寄存器
  120.         CLK_DIV |= 0x20; //ADRJ 为 1,ADC_RES 存放高两位结果,ADC_RESL 存放低 8 位结果
  121.     //ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START;
  122.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START;                    //ADC上电并延时
  123. }

  124. /*******************************************************************************
  125. * 文件名:void adc_isr() interrupt 5 using 1
  126. * 描  述: 中断服务程序
  127. * 功  能:
  128. * 作  者:大核桃
  129. * 版本号:1.0.1(2015.03.03)
  130. *******************************************************************************/
  131. void adc_isr() interrupt 5 using 1
  132. {
  133.         EADC = 1; //允许ADC转换中断
  134.         ET0 = 0;  //关闭定时器0中断

  135.         ADC_CONTR &= !ADC_FLAG; //清除ADC中断标志
  136.         temp = ADC_RES;
  137.         temp <<= 8;
  138.         temp |= ADC_RESL;

  139.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 5;
  140.         EADC = 0;//关闭ADC转换
  141.         ET0 = 1;  //打开定时器0中断        

  142. }

  143. /*******************************************************************************
  144. * 文件名:void VoltageCheckRefresh()
  145. * 描  述: 电压检测
  146. * 功  能:
  147. * 作  者:大核桃
  148. * 版本号:1.0.1(2015.03.03)
  149. *******************************************************************************/
  150. void VoltageCheckRefresh()
  151. {
  152.         val = (uint8)((temp)* 2 * 10 * 3.3 / 1023);                        
  153. }

  154. /*******************************************************************************
  155. * 文件名:void Time0_Init()
  156. * 描  述: 定时器0初始化
  157. * 功  能:10毫秒@11.0592MHz
  158. * 作  者:大核桃
  159. * 版本号:1.0.1(2017.05.23)
  160. *******************************************************************************/
  161. void Time0_Init(void)
  162. {
  163.         AUXR &= 0x7F;                //定时器时钟12T模式
  164.         TMOD &= 0xF0;                //设置定时器模式
  165.         TMOD |= 0X01;      //确保不干扰其他配置
  166.         TH0 = (65536 - 1000) / 256;                //设置定时初值
  167.         TL0 = (65536 - 1000) % 256;                //设置定时初值
  168.         ET0 = 1;
  169.         TR0 = 1;                //定时器0开始计时
  170.         EA = 1;               
  171. }
  172. /*******************************************************************************
  173. * 文件名:
  174. * 描  述: 中断函数
  175. * 功  能:1毫秒@11.0592MHz
  176. * 作  者:大核桃
  177. * 版本号:1.0.1(2017.05.23)
  178. *******************************************************************************/
  179. void ET0_IRQHandler() interrupt 1
  180. {
  181.         static uint8 tmr5ms = 0;

  182.         TH0 = (65536 - 1000) / 256;                //设置定时初值
  183.         TL0 = (65536 - 1000) % 256;                //设置定时初值

  184.         EADC = 0; //不允许ADC转换中断
  185.         tmr5ms++;
  186.         if(tmr5ms >= 5)
  187.         {
  188.                 tmr5ms = 0; //定时器5MS溢出一次
  189.                 VoltageCheckRefresh();
  190.         }

  191.         LedScan();
  192.         EADC = 1; //允许ADC转换中断
  193.                         
  194. }
  195. /*******************************************************************************
  196. * 文件名:void Mcu_Port_Init()
  197. * 描  述: io初始化
  198. * 功  能:
  199. * 作  者:大核桃
  200. * 版本号:1.0.1(2017.05.23)
  201. *******************************************************************************/
  202. void Mcu_Port_Init()
  203. {
  204.         IE = 0xa8;//允许AD转换
  205.         //将P0口低二位配置为推挽输出
  206.         //234567位配置位高阻输入
  207.         P0M1 = 0xFC;//1111 1100
  208.         P0M0 = 0X03;//0000 0011
  209.         //P0 = 0X01;//第6个
  210.         //P0 = 0X02;//第7个
  211.         //高3位配置高阻输入,用作模拟口
  212.         //其他配置推挽输出,驱动LED
  213.         P1M1 = 0xE0;//1110 0000
  214.         P1M0 = 0X1F;//0001 1111
  215.         //P2口配置准双向口
  216.         P2M1 = 0X00;
  217.         P2M0 = 0X00;
  218.         P2 = 0Xff; //上电为1111 1111

  219. //        //P54,P55口为推挽输出
  220.         P5M1 = 0X00;
  221.         P5M0 = 0X00;
  222.         P5 = 0xFF;

  223.         //P37,P36,3.2,P3.3 P3.4口为推挽输出
  224.         P3M1 = 0X00;
  225.         P3M0 = 0XFC;
  226.         P3 = 0X23; //0010 0111//第5个LED端口
  227.         
  228.         LED0 = 0;//第1组LED,如果使能请置为1
  229.         LED1 = 0;
  230.         LED2 = 0;
  231.         LED3 = 0;
  232.         LED4 = 0;
  233.         LED5 = 0;
  234.         LED6 = 0;
  235.         LED7 = 0;        
  236. }

  237. /*******************************************************************************
  238. * 文件名:void Delay500ms()                //@11.0592MHz
  239. * 描  述:Y5内核延时
  240. * 功  能:
  241. * 作  者:大核桃
  242. * 版本号:1.0.1(2017.05.23)
  243. *******************************************************************************/
  244. void Delay500ms()                //@11.0592MHz
  245. {
  246.         unsigned char i, j, k;

  247.         _nop_();
  248.         _nop_();
  249.         i = 22;
  250.         j = 3;
  251.         k = 227;
  252.         do
  253.         {
  254.                 do
  255.                 {
  256.                         while (--k);
  257.                 } while (--j);
  258.         } while (--i);
  259. }
复制代码


在数码管上显示的数值如下图所示,注意这是测试的锂电池的电压:
      

实际万用表测量的结果是4.01V,数码管显示的结果跟万用表的结果相差0.01V,我们用的ADC是10位的分辨率,参考电压是3.3V,那么一个LSB是3.3/1024 = 0.00322265625,那么0.01V,差不多3个LSB,考虑到我们的参考电压也是有少许误差存在的,所以这个结果还是比较合理的,如果使用独立的参考电压,误差应该会更小。



代码奉献上。
5.AD转换器的使用.rar (202.97 KB, 下载次数: 423)






作者: WOBENJUNZHU    时间: 2018-11-1 14:13
谢谢楼主的分享,看了你的程序,之前没弄懂的也搞清楚了
作者: topsjb    时间: 2018-11-10 22:26

谢谢楼主的分享,先下载学习。
作者: shidalin123    时间: 2018-11-12 10:07
学习一下,谢谢楼主
作者: jifengjianwu    时间: 2018-11-12 18:11
谢谢楼主,资料挺有用的,学习了。
作者: 1238    时间: 2018-12-1 16:59
谢谢楼主的分享,先下载备用。以后学习学习。
作者: 969168666    时间: 2018-12-5 09:31
谢谢分享,学习了
作者: friend114    时间: 2018-12-5 19:55
谢谢楼主的分享,先下载备用。以后学习学习。
作者: qsgang    时间: 2018-12-12 08:50
非常不错,感谢分享
作者: 时光倒影    时间: 2018-12-12 17:11
谢谢楼主分享
作者: 民盛    时间: 2018-12-26 15:11
这个太好了,正在学习。谢谢。
作者: 去远方    时间: 2018-12-26 17:15
感觉自己啥都不会啊

作者: jifengjianwu    时间: 2019-1-25 14:46
正好学习到这个内容,谢谢楼主。
作者: zhyuxn123    时间: 2019-2-22 14:45
学习一下,谢谢楼主
作者: 懒散专业户    时间: 2019-4-4 09:49
每天都有好东西学习,很不错,刚学习软件,受益匪浅
作者: michael2018    时间: 2019-4-8 16:05
楼主牛逼啦
作者: 太阳黑子1    时间: 2019-4-11 21:57
需要好好学习学习!!!
作者: songshengguo123    时间: 2019-6-2 18:37
谢谢,怎么感觉好复杂呢,不懂的原因吧。
作者: jpwu10    时间: 2019-6-11 06:57
谢谢,很好资料。
作者: sgly    时间: 2019-7-18 08:56
很厉害啊,正在学习
作者: 嘟嘟胖子    时间: 2019-7-18 17:15
谢谢楼主的分享,先学习下。
作者: 磨叽大王    时间: 2019-7-25 15:34
谢谢楼主分享,刚好准备做这个,学习一下
作者: qq1182560902    时间: 2019-10-12 02:33
有测试波形的方法吗?
作者: zql111000    时间: 2019-11-19 18:43
你好,你能写个完整的STC单片机内置ADC按键检测程序,用中断方式,谢谢
作者: Eliezer_Li    时间: 2019-12-25 23:48
本来一直不明白10位精度的低八位和高八位模拟量怎么合起来,res=ADC_RES*4+ADC_RESL;这种公式怎么理解
作者: walter189    时间: 2020-1-2 20:14
学习了,不错
作者: 奔儿霸    时间: 2020-3-27 23:31
你好,查询方式中获取值  GetADCResult(5) 中为什么要循环十次呢。
作者: 歌者    时间: 2020-4-17 09:32
很好的资料。学习了。谢谢楼主
作者: 编程小小白    时间: 2020-6-4 10:12
谢谢分享 正好要用到这些
作者: T礼物X    时间: 2020-9-15 15:01
遇到问题,谢谢楼主分享
作者: PCB_PCB    时间: 2020-9-20 17:08
楼主写的程序格式看上去很舒服,
作者: 山东小哥    时间: 2020-12-15 15:17
不错,正在学习
作者: wblqx    时间: 2021-2-12 08:30
正在学习STC芯片的AD,很好的资料。
作者: fefen0    时间: 2021-4-10 00:07
Eliezer_Li 发表于 2019-12-25 23:48
本来一直不明白10位精度的低八位和高八位模拟量怎么合起来,res=ADC_RES*4+ADC_RESL;这种公式怎么理解

谢谢楼主的分享,先下载备用。以后学习学习。

作者: zhth1979    时间: 2021-8-26 16:16
  谢谢楼主的分享,先下载学习。
作者: lileisgns    时间: 2022-5-17 17:48
好东西!可惜我还没有学到这里。
作者: wyl138    时间: 2022-10-31 18:38
虽然还看不懂,但我相信这个很有用,收藏先.
作者: hzm19640731    时间: 2023-4-15 17:58
谢谢楼主,资料挺有用!!!




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1