找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机倒计时程序增加功能请教

[复制链接]
跳转到指定楼层
楼主
ID:301791 发表于 2018-11-11 08:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚接触单片机,现在实在没有独立写程序的能力,仅仅刚入门,所以只能在拿老师们的程序练习,现有问题请教各位老师:
下面这个程序,原来是999分钟倒计时,现在被我改成99分钟了,增加了暂停功能,暂停不影响继电器,继电器要在倒计时结束后才断电.
现在想添加两只led做指示,led1在计时开始的时候闪一下,(约0.5秒)led2在计时结束时闪一下(约0.5秒)或者在最后一分种的时候闪一下(约0.5秒)。请问老师们这该怎么改呢?先谢谢各位老师们了。
单片机源程序:
  1. //#include<reg52.h>
  2. #include<STC12C2052AD.h>          //库文件
  3. #include<intrins.h>
  4. #define uchar unsigned char //宏定义字符型变量
  5. #define uint  unsigned int //宏定义整型变量
  6. /*声明 SFR 相关 与 的 IAP*/
  7. sfr IAP_DATA = 0xE2;
  8. sfr IAP_ADDRH = 0xE3;
  9. sfr IAP_ADDRL = 0xE4;
  10. sfr IAP_CMD = 0xE5;
  11. sfr IAP_TRIG = 0xE6;
  12. sfr IAP_CONTR = 0xE7;

  13. /********************************************************************
  14.                              IO口定义
  15. ********************************************************************/
  16. uchar s1=0;
  17. bit  write=0;
  18. uint txian,dxian;
  19. uchar txian1,txian2;
  20. uchar dxian1,dxian2;
  21. uchar T0RH=0,T0RL=0;
  22. uint ms=0;
  23. uchar A1,A2;
  24. uchar B1,B2;
  25. uchar C1,C2;
  26. uchar D1,D2;
  27. bit bz1=0;
  28. bit bz2=0;
  29. sbit P10=P1^0;//数码管段
  30. sbit P11=P1^1;//数码管段
  31. sbit P12=P1^2;//数码管段
  32. sbit P13=P1^3;//数码管段
  33. sbit P14=P1^4;//数码管段
  34. sbit P15=P1^5;//数码管段
  35. sbit P16=P1^6;//数码管段
  36. sbit AIN1=P1^7;//信号输入
  37. sbit P30=P3^0;//按键输入
  38. sbit P31=P3^1;//按键输入
  39. sbit P32=P3^2;//数码管位
  40. sbit P33=P3^3;//数码管位
  41. sbit LED1=P3^4;//?
  42. sbit LED2=P3^5;//?
  43. sbit OUT1=P3^7;//继电器输出
  44. bit ts=1;     //
  45. bit yxbz=0;   //
  46. uint xianshi;
  47. /********************************************************************
  48.                             定义 ISP/IAP/EEPROM 命令
  49. *********************************************************************/
  50. #define CMD_IDLE 0
  51. #define CMD_READ 1
  52. #define CMD_PROGRAM 2
  53. #define CMD_ERASE 3
  54. #define ENABLE_IAP 0x83//SYSCLK<12MH
  55. #define IAP_ADDRESS 0x0000//存储地址

  56. /********************************************************************
  57. 禁用 ISP/IAP/EEPROM functionmake 单片机 在 一 安全 状态
  58. *********************************************************************/
  59. void IapIdle()
  60. {
  61.   IAP_CONTR = 0;    //
  62. IAP_CMD = 0;    //
  63. IAP_TRIG = 0;    //
  64. IAP_ADDRH = 0x80;  //
  65. IAP_ADDRL = 0;    //
  66. }
  67. /********************************************************************
  68.                              读数据
  69. *********************************************************************/
  70. uchar IapReadByte(uint addr)
  71. {
  72.    uchar dat;
  73.    IAP_CONTR = ENABLE_IAP;
  74.    IAP_CMD = CMD_READ;
  75.    IAP_ADDRL = addr;
  76.    IAP_ADDRH = addr >> 8;
  77.    IAP_TRIG = 0x46;
  78.    IAP_TRIG = 0xb9;
  79.    _nop_();
  80.    dat = IAP_DATA;
  81.    IapIdle();
  82.    return dat;
  83. }
  84. /********************************************************************
  85.                                写数据
  86. *********************************************************************/
  87. void IapProgramByte(uint addr, uchar dat)
  88. {
  89.    IAP_CONTR = ENABLE_IAP;
  90.    IAP_CMD = CMD_PROGRAM;
  91.    IAP_ADDRL = addr;
  92.    IAP_ADDRH = addr >> 8;
  93.    IAP_DATA = dat;
  94.    IAP_TRIG = 0x46;
  95.    IAP_TRIG = 0xb9;
  96.    _nop_();
  97.    IapIdle();
  98. }
  99. /********************************************************************
  100.                                擦除数据
  101. *********************************************************************/
  102. void IapEraseSector(uint addr)
  103. {
  104.    IAP_CONTR = ENABLE_IAP;
  105.    IAP_CMD = CMD_ERASE;
  106.    IAP_ADDRL = addr;
  107.    IAP_ADDRH = addr >> 8;
  108.    IAP_TRIG = 0x46;
  109.    IAP_TRIG = 0xb9;
  110.    _nop_();
  111.    IapIdle();
  112. }
  113. /********************************************************************
  114.                             初始定义
  115. *********************************************************************/
  116. code uchar seg7code[10]={0xfB,0x89,0xf5,0xdD,0x8F,0xdE,0xfE,0xc9,0xfF,0xdF}; //显示段码 数码管字跟
  117. /********************************************************************
  118.                             延时函数
  119. *********************************************************************/
  120. void delay(uchar t)
  121. {
  122.   uchar i,j;
  123.    for(i=0;i<t;i++)
  124.    {
  125.      for(j=130;j>0;j--);
  126.   { ;
  127.   }
  128.    }
  129. }
  130. /********************************************************************
  131.                             显示函数 接通时间
  132. *********************************************************************/        
  133. //void tong(uchar tdate) //显示函数
  134. void tong() //显示函数
  135. {
  136.     C1=txian%100/10;
  137.    C2=txian%10;
  138.    P32=1;P33=1;  
  139.     P1=seg7code[C1];
  140.    P32=0;P33=1;
  141.    delay(80);
  142.    P32=1;P33=1;  
  143.     P1=seg7code[C2];
  144.    P32=1;P33=0;
  145.    delay(80);

  146. }
  147.    
  148. void key()
  149. {
  150.    if(P30==0)
  151.    {
  152.    delay(80);
  153.    if(P30==0)
  154.    {
  155.    s1++;
  156.    if(s1>=4){s1=0;}
  157.    while(!P30);
  158.    }
  159. }}

  160. //定时器0初始化
  161. void t0_init(unsigned char ms0)    //ms0最大71
  162. {
  163. /***********************************************
  164. 一个机器周期=12*时钟周期。
  165. 11059200为时钟周期,一共为11059200/12=921600,就是每秒为921600Hz,
  166.     八位定时器 最大计时     0.2777778ms
  167. 十六位定时器最大计时   71.111111ms
  168. 11.0592MHz除12为921600Hz,就是一秒921600次机器周期,10ms=9216次机器周期。
  169.   65536-9216=56320(dc00)
  170.   TH0=0xdc,TL0=0x00
  171. ***********************************************/
  172.   long tmp;  //临时变量
  173.    tmp = 11059200 / 12;
  174.   tmp = (tmp * ms0) / 1000;
  175.   tmp = 65536 - tmp;
  176.   tmp = tmp + 3;
  177.   T0RH = (unsigned char)(tmp>>8);
  178.   T0RL = (unsigned char)tmp;        
  179.    TMOD &=0XF0;
  180.   TMOD |=0X01;  //方式一  一共四种方式   GATE0 C/T0  M0_1  M0_0  C/T0选择时钟计数还是外部计数  方式0是十三位定时器 ,方式1是十六位定时器,方式2是八位自动 方式4是两个八位
  181.   TH0=T0RH;
  182.   TL0=T0RL;
  183.   ET0=1;   //使能T0中断
  184.   EA=1;
  185.   TR0=1;
  186. }
  187. /********************************************************************
  188.                                主函数
  189. *********************************************************************/
  190. void main()
  191. {   
  192.   unsigned char flag=1,flag2=0;;
  193. txian1 = IapReadByte(0x01);  //读取0x01中的数据  并附给ca
  194. txian2 = IapReadByte(0x02);  //读取0x01中的数据  并附给ca
  195. t0_init(10);
  196. P1M0=0X00;P1M1=0X7f;
  197. txian=txian1*10+txian2;
  198. xianshi=txian;
  199. OUT1=1;
  200. //ts=0;bz1=1;ms=0;OUT1=0;
  201. while(1)
  202. {
  203.     key();
  204.    if((AIN1==0)&&(bz1==0)&&(ts==0)){delay(80);
  205.   if(AIN1==0){bz1=1;yxbz=!yxbz;}}
  206.    if((AIN1==0)&&(bz1==0)&&(ts==1)){delay(80);
  207.   if(AIN1==0){yxbz=1;ts=0;bz1=1;ms=0;OUT1=0;}}
  208.    if((AIN1==1)&&(bz1==1)){bz1=0;}
  209.     if(write==1)
  210.    {
  211.     TR0=0;                              
  212.      write=0;
  213.      IapEraseSector(0);
  214.      IapProgramByte(0x01,txian1);
  215.      IapProgramByte(0x02,txian2);
  216.     TR0=1;
  217.     xianshi=txian;
  218.   }
  219. }   
  220. }
  221. void t0(void) interrupt 1 using 0 //定时中断服务函数
  222. {
  223.    TH0=T0RH;
  224.    TL0=T0RL;
  225.       switch (s1){
  226.     case 0: tong();break;
  227.     case 1:ts=1;P1=seg7code[A1];P32=0;P33=1;if(P31==0){A1++;if(A1>9)A1=0;while(!P31);}break;
  228.      case 2:     P1=seg7code[A2];P32=1;P33=0;if(P31==0){A2++;if(A2>9)A2=0;while(!P31);}break;
  229.     case 3:     txian1=A1;txian2=A2;txian=txian1*10+txian2;write=1;break;
  230.     default: break;
  231.   }
  232. if(yxbz==1)
  233. {
  234. ms++;
  235. if(ms==4800)  //ms=80是1秒
  236. {
  237. ms=0;
  238. if(ts==0){txian--;if(txian<=0){bz1=0;OUT1=1;txian=txian1*10+txian2;ts=1;}}
  239. }
  240. }

  241. }
复制代码


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

使用道具 举报

沙发
ID:111634 发表于 2018-11-11 19:37 | 只看该作者
本帖最后由 zl2168 于 2018-11-11 21:13 编辑

实例93  99.9秒秒表  
Proteus仿真一下,确认有效。
实例95 99.9秒秒表.rar (38.86 KB, 下载次数: 6)

实例96  能预置初值的倒计时秒表
实例96 能设置初值的倒计时秒表.rar (40 KB, 下载次数: 8)

以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1内有常用的单片机应用100案例,用于仿真实验操作,书中电路和程序设计有详细说明,电路与程序真实可靠可信可行,程序语句条条有注解。若需99.99秒,硬件电路增加一位595。软件程序增加0.01s10ms计数器,并修改相应计数显示程序。
回复

使用道具 举报

板凳
ID:301791 发表于 2018-11-13 08:29 | 只看该作者
大神们提示一下也是好的,折腾了一晚上,只能折腾到开始计时亮,一分钟时间亮,计时完毕亮,就是还没弄成闪一下.
回复

使用道具 举报

地板
ID:213173 发表于 2018-11-13 15:54 | 只看该作者
声明两个全局位变量,分别用在计时开始和结束语句位置 置1
bit a=0,b=0;
void LED_Twinkle()//此函数放在主函数中调用
{
        static uint i=0,j=0;
        if(a==1)
        {       
                LED1=0;
                if(i++==10000)
                {
                        i=0;
                        a=0;
                        LED1=1;
                }
        }
        if(b==1)
        {       
                LED2=0;
                if(j++==10000)
                {
                        j=0;
                        b=0;
                        LED2=1;
                }
        }
}
回复

使用道具 举报

5#
ID:301791 发表于 2018-11-13 21:37 | 只看该作者
wulin 发表于 2018-11-13 15:54
声明两个全局位变量,分别用在计时开始和结束语句位置 置1
bit a=0,b=0;
void LED_Twinkle()//此函数放在 ...

谢谢老师指点.
回复

使用道具 举报

6#
ID:301791 发表于 2018-11-14 14:09 | 只看该作者

最后,还是用了自己的理解方式实现,这个程序还有小bug,但不影响玩。
刚好双十一图书对折,买了几本,估计这几天就能到了。
这个倒计时折腾了许久了,基本啃明白了,学习单片机就得死磕自己,慢慢来。
发这个帖子的时候一下没转过弯来。


IMG_8638.rar

608.8 KB, 下载次数: 5

回复

使用道具 举报

7#
ID:301791 发表于 2018-11-15 10:22 | 只看该作者
折腾了一上午,把数码管的管脚改了io口,小小修改了下程序。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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