找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4742|回复: 41
打印 上一主题 下一主题
收起左侧

用RC充放电实现检测外部电压STC15F单片机Keil工程与代码

  [复制链接]
回帖奖励 10 黑币 回复本帖可获得 10 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
ID:971077 发表于 2021-10-19 09:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
对于没有ADC的MCU,而又要测量外部的一个电压时,使用RC充放电的方式是比较容易实现并且低成本的方法。
STC15F系列是1T的MCU,其IO口有OPEN-DRAIN模式,此模式可以很容易用一个IO口配合一个定时器实现RC充放电来测量外部未知电压。如果没有空余的定时器,也可以使用指令循环的方式实现。本例使用定时器。

本范例使用P3.2(INT0)来做RC测量
电路原理图如下:


单片机源程序如下:
  1. /*

  2. 功能描述: 使用STC15F系列C版本做的RC测量电压的例子.

  3. */

  4. #include "reg51.h"

  5. #define MAIN_Fosc                            22118400L              //定义主时钟

  6. #define              uchar              unsigned char
  7. #define uint              unsigned int

  8. sfr AUXR = 0x8e;    //Auxiliary register
  9. sfr P3M1  = 0xB1;              //P3M1.N,P3M0.N               =00--->Standard,              01--->push-pull
  10. sfr P3M0  = 0xB2;              //                                                                      =10--->pure input,              11--->open drain

  11. sbit              P_TXD1  = P3^1;              //定义模拟串口发送脚,打印信息用
  12. sbit    P_RC = P3^2;              //RC port
  13. uchar              SampleCnt;                            //发送结果的采样间隔计数
  14. uchar              LineCnt;                            //每行显示结果计数
  15. bit                            B_Over;                                          //超时标志
  16. bit                            B_ADC_OK;                            //检测完成标志
  17. uint              adc;                                          //RC做的ADC值

  18. void              RC_start(void);
  19. void              Tx1Send(uchar dat);
  20. void               InitTimer(void);
  21. void              delay_ms(unsigned char ms);

  22. ///////////////////////////////////////////////////////////

  23. void main(void)
  24. {

  25.               InitTimer();                            //初始化Timer

  26.     P3M1 |=  1 << 2;         //P3.2 config as Open-Drain
  27.               P3M0 |=  1 << 2;
  28.               P_RC = 0;               //Clear RC port to 0
  29. //    TMOD |= 0x00;           //T0 as 16 bits timer, auto reload

  30.     while (1)
  31.     {
  32.         delay_ms(5);   //放电时间
  33.                            
  34.                             B_ADC_OK = 0;                            //清除ADC结束标志
  35.                             B_Over = 0;                                          //清除超量程标志
  36.         RC_start();           //RC charge-decharge
  37.                             while(!B_ADC_OK && !B_Over)              ;              //等待ADC结束或超时
  38.                             if(B_ADC_OK)
  39.                             {
  40.                                           if(++SampleCnt >= 100)              //1秒钟发一个结果给串口
  41.                                           {
  42.                                                         SampleCnt = 0;
  43.                                                         Tx1Send(adc / 10000 + '0');           //send to PC from the UART
  44.                                                         Tx1Send(adc % 10000 / 1000 + '0');
  45.                                                         Tx1Send(adc % 1000 / 100 + '0');
  46.                                                         Tx1Send(adc % 100 / 10 + '0');
  47.                                                         Tx1Send(adc % 10 + '0');
  48.                                                         Tx1Send(' ');
  49.                                                         Tx1Send(' ');
  50.                                                         if(++LineCnt >= 10)                            //10个结果后换行
  51.                                                         {
  52.                                                                       LineCnt = 0;
  53.                                                                       Tx1Send(0x0d);   //send CR
  54.                                                                       Tx1Send(0x0a);
  55.                                                         }
  56.                                           }
  57.                             }
  58.     }
  59. }


  60. ///////////////////////////////////////////////////////////

  61. //============================================================
  62. // 函数: void  delay_ms(unsigned char ms)
  63. // 描述: 延时函数。
  64. // 参数: ms,要延时的ms数.
  65. // 返回: none.
  66. // 版本: VER1.0
  67. // 日期: 2010-12-15
  68. // 备注:
  69. //============================================================
  70. void  delay_ms(unsigned char ms)
  71. {
  72.      unsigned int i;
  73.               do
  74.               {
  75.                             i = MAIN_Fosc / 14000L;              //1T
  76.                             while(--i)              ;   //13T per loop
  77.      }while(--ms);
  78. }


  79. /**************** RC启动函数 ******************************/
  80. void   RC_start(void)
  81. {
  82.                         //使用Timer 0 计时
  83.     TH0 = 0;            //clear Timer 0
  84.     TL0 = 0;
  85.               B_Over = 0;                                          //Clear Over flag
  86.     P_RC = 1;           //RC charge
  87.     TR0 = 1;            //enable Timer 0
  88.               IE0 = 0;                                          //Clear INT0 flag
  89.               EX0 = 1;                            //INT0 Enable
  90.               IT0 = 0;                            //INT0 上升,下降沿中断            
  91. }

  92. /********************* INT0中断函数 *************************/
  93. void INT0_int (void) interrupt 0                            //
  94. {
  95.     if(INT0 && !B_Over)                            //上升沿中断,无超时
  96.               {
  97.                             TR0 = 0;            //deable Timer 0
  98.                             P_RC = 0;           //decharge
  99.                             adc = TH0;            //read the RC time
  100.                             adc = (adc << 8) + TL0;
  101.                             B_ADC_OK = 1;                            //标志ADC结束
  102.               }
  103. }


  104. /**************** Timer初始化函数 ******************************/
  105. void InitTimer(void)
  106. {
  107.               TMOD = 0;                            //for STC15Fxxx系列              Timer0 as 16bit reload timer.
  108.               TH0 = 0;
  109.               TL0 = 0;
  110.               ET0 = 1;                            //允许Timer0中断
  111.               TR0 = 0;
  112.               EA  = 1;                            //允许总中断
  113. }

  114. /********************** Timer0中断函数************************/
  115. void timer0 (void) interrupt 1
  116. {
  117.               TR0 = 0;              //超量程关闭
  118.               B_Over = 1;              //标志超量程
  119. }


  120. /********************** 模拟串口相关函数************************/

  121. void              BitTime(void)              //位时间函数
  122. {
  123.               uint i;
  124.               i = ((MAIN_Fosc / 100) * 104) / 130000L - 1;                            //根据主时钟来计算位时间
  125.               while(--i);
  126. }

  127. //模拟串口发送
  128. void              Tx1Send(uchar dat)                            //9600,N,8,1                            发送一个字节
  129. {
  130.               uchar              i;
  131.               EA = 0;
  132.               P_TXD1 = 0;
  133.               BitTime();
  134.               for(i=0; i<8; i++)
  135.               {
  136.                             if(dat & 1)                            P_TXD1 = 1;
  137.                             else                                          P_TXD1 = 0;
  138.                             dat >>= 1;
  139.                             BitTime();
  140.               }
  141.               P_TXD1 = 1;
  142.               EA = 1;
  143.               BitTime();
  144.               BitTime();
  145. }
复制代码

Keil代码hex文件下载:
STC15Fxx.rar (9.61 KB, 下载次数: 46)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏9 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:941265 发表于 2021-10-20 10:36 | 只看该作者
51黑有你更精彩,谢谢分享
回复

使用道具 举报

板凳
ID:313048 发表于 2021-10-20 14:10 | 只看该作者
还有这种操作,涨知识了
回复

使用道具 举报

地板
ID:32289 发表于 2021-10-20 21:22 | 只看该作者
精度如何?准确度呢?
回复

使用道具 举报

5#
ID:480510 发表于 2021-10-22 18:38 | 只看该作者
有时间我也试试
回复

使用道具 举报

6#
ID:4867 发表于 2021-10-25 18:07 | 只看该作者
检测充放电时间来判断电压,精度和电容、电阻、频率都有关系!要求不高的应用是可以应急用用!
回复

使用道具 举报

7#
ID:85865 发表于 2021-10-25 18:48 | 只看该作者
这种方式检测的电压准吗
回复

使用道具 举报

8#
ID:965189 发表于 2021-10-25 23:06 | 只看该作者
涨知识了,检测中断间隔时间。
回复

使用道具 举报

9#
ID:854138 发表于 2021-11-4 13:24 | 只看该作者
51黑有你更精彩,谢谢分享
回复

使用道具 举报

10#
ID:977934 发表于 2021-11-7 00:22 | 只看该作者

51黑有你更精彩,谢谢分享
回复

使用道具 举报

11#
ID:978845 发表于 2021-11-7 11:45 来自手机 | 只看该作者
51黑有你更精彩,谢谢分享
回复

使用道具 举报

12#
ID:976070 发表于 2021-11-7 17:12 | 只看该作者
可调电阻范围????????
回复

使用道具 举报

13#
ID:624769 发表于 2021-11-7 23:00 | 只看该作者
252622979 发表于 2021-10-25 18:48
这种方式检测的电压准吗

不准,要准的话,最起码要用比较器。 这个就是STC官网上面的范例,范例中也有说明,这个方法仅仅只是用于,连比较器都没有的单片机偏偏需要一个大约的电压值的权宜之计。
回复

使用道具 举报

14#
ID:305762 发表于 2021-11-8 08:17 | 只看该作者

51黑有你更精彩,谢谢分享!!!
回复

使用道具 举报

15#
ID:548757 发表于 2021-11-9 15:28 | 只看该作者
学习学习,借鉴一种分析方法!
回复

使用道具 举报

16#
ID:928284 发表于 2021-11-27 16:36 | 只看该作者
论坛里有你,才有更大的意义,我在学习中。
回复

使用道具 举报

17#
ID:985476 发表于 2021-11-27 23:11 | 只看该作者
真是大开眼界,非常有学习价值
回复

使用道具 举报

18#
ID:979106 发表于 2021-11-28 13:51 | 只看该作者

涨知识了,检测中断间隔时间。
回复

使用道具 举报

19#
ID:652804 发表于 2021-11-28 16:42 | 只看该作者
有时间我也试试
回复

使用道具 举报

20#
ID:986042 发表于 2021-12-6 16:50 | 只看该作者

好资料,51黑有你更精彩!
回复

使用道具 举报

21#
ID:137736 发表于 2021-12-6 21:27 | 只看该作者
原来网上有用89C2051比较强做的电压测量程序
回复

使用道具 举报

22#
ID:989283 发表于 2021-12-7 20:09 | 只看该作者


好资料,51黑有你更精彩!
回复

使用道具 举报

23#
ID:996104 发表于 2021-12-23 14:25 | 只看该作者


好资料,51黑有你更精彩!
回复

使用道具 举报

24#
ID:993969 发表于 2022-2-4 15:59 | 只看该作者

51黑有你更精彩,谢谢分享
回复

使用道具 举报

25#
ID:983641 发表于 2022-2-18 12:23 | 只看该作者
这种方法比较新颖,不知道精度和量程如何。
回复

使用道具 举报

26#
ID:974778 发表于 2022-2-18 14:07 | 只看该作者

51黑有你更精彩,谢谢分享
回复

使用道具 举报

27#
ID:1014986 发表于 2022-4-3 14:34 | 只看该作者
51黑有你更精彩,谢谢分享
回复

使用道具 举报

28#
ID:1017657 发表于 2022-4-11 21:41 | 只看该作者
这样测电压准吗
回复

使用道具 举报

29#
ID:1020136 发表于 2022-4-20 19:16 | 只看该作者
涨知识了,谢谢楼主
回复

使用道具 举报

30#
ID:973561 发表于 2022-5-16 10:34 | 只看该作者

涨知识了,谢谢楼主
回复

使用道具 举报

31#
ID:1028891 发表于 2022-5-23 16:44 | 只看该作者
51黑有你更精彩,谢谢分享
回复

使用道具 举报

32#
ID:297903 发表于 2022-5-24 09:45 | 只看该作者
學習了,謝謝!!
回复

使用道具 举报

33#
ID:1030839 发表于 2022-5-30 13:36 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

34#
ID:1031100 发表于 2022-5-30 22:33 | 只看该作者
太强啦
回复

使用道具 举报

35#
ID:1033422 发表于 2022-6-9 16:02 | 只看该作者
检测充放电时间来判断电压,精度和电容、电阻、频率都有关系!
回复

使用道具 举报

36#
ID:1034398 发表于 2022-6-14 11:34 | 只看该作者
好强,我直接学晕了
回复

使用道具 举报

37#
ID:1034398 发表于 2022-6-14 11:36 | 只看该作者
请问能教一下51单片机温度报警器怎么搞?
回复

使用道具 举报

38#
ID:334440 发表于 2022-6-14 21:15 | 只看该作者
精确度如何,有验证过的大师吗
回复

使用道具 举报

39#
ID:257564 发表于 2022-6-15 13:21 | 只看该作者
这种方法不错,挺实用的
回复

使用道具 举报

40#
ID:1043176 发表于 2022-9-14 09:18 | 只看该作者
  51黑有你更精彩,谢谢分享!!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表