找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机定时控制继电器带显示程序+Proteus仿真图

[复制链接]
跳转到指定楼层
楼主
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. //main.c
  2. -----------------------------------
  3. /*******************************************************************************
  4. *                 
  5. *                     
  6. --------------------------------------------------------------------------------
  7. * 实 验 名         : 动态数码管显示,定时器
  8. * 实验说明       :
  9. * 连接方式       :
  10. * 注    意         :
  11. *******************************************************************************/

  12. #include"STC15F2K.h"
  13. #include"epprom.h"
  14. //--定义使用的IO口--//
  15. #define u8 unsigned char
  16. #define u16 unsigned int
  17. sbit you1=P2^0;
  18. sbit you2=P2^1;
  19. sbit you3=P2^2;
  20. sbit you4=P2^3;
  21. sbit you23=P2^4;
  22. sbit kai=P2^5;
  23. sbit fen=P2^6;
  24. sbit shi=P2^7;
  25. sbit jidianqi=P3^7;
  26. //--定义全局变量--//
  27. u8 code DIG_PLACE[8] = {
  28. 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选控制   查表的方法控制
  29. u8 code DIG_CODE[18] = {
  30. 0x3f,0x06,0x5b,0x4f,0x66,
  31. 0x6d,0x7d,0x07,0x7f,0x6f,
  32. 0x77,0x7c,0x39,0x5e,0x79,
  33. 0x71,0x40,0x80};
  34. //0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F、- 的显示码
  35. u8 X1,X2,X3,X4,X5;
  36. u8 DisplayData[8];
  37. u16 DJS=0,fen60,shi6;
  38. bit kk=0;     //开关,1,倒计时进行,继电器闭合;0,输入时间,继电器断开
  39. u16 ff=10*60/*600秒*/,ss=60*60/*3600秒*/;  
  40. u16 count_djs=0;
  41. u16 countt=0;
  42. u8 KKKEY;
  43. //--声明全局函数--//
  44. void DigDisplay(); //动态显示函数
  45. void ConfigTimer0(u8 ms);
  46. void  key_sm();
  47. void anjian();

  48. /*******************************************************************************
  49. * 函 数 名         : XX,提供各个数码管的数值

  50. *******************************************************************************/
  51. void  XX()
  52. {

  53.    countt=DJS-count_djs;
  54. if(kk==0) {

  55.         X1=shi6/10;
  56.         X2=shi6%10;
  57.         X3=fen60/10;
  58.         X4=fen60%10;
  59.         X5=17;
  60.         }
  61. if(kk==1)
  62.   {
  63.   if(countt<=3600)
  64.   {
  65.          X1=countt/600%10;
  66.         X2=countt/60%10;
  67.         X3=countt/10%6 ;
  68.         X4=countt%10/*kk */ ;
  69.         X5=17;
  70.    }
  71.    if(countt>3600)
  72.    {
  73.         X1=countt/36000%10;
  74.         X2=countt/3600%10    ;
  75.         X3=countt%3600/600%6;
  76.         X4=countt%3600/60%10;
  77.    }
  78.    if(X1==0)
  79.        { X1=16;
  80.           if(X2==0)
  81.           {X2=16;
  82.           if(X3==0)X3=16;
  83.           }}
  84. }
  85. }
  86. /*******************************************************************************
  87. * 函 数 名         : 扫描按键,赋值。

  88. *******************************************************************************/
  89. void  key_sm()
  90. {
  91. anjian();
  92. if(KKKEY==1) {KKKEY=0;fen60=fen60+10;if(fen60>=60)fen60=0;}
  93. if(KKKEY==2) {KKKEY=0;shi6=shi6+1;if(shi6>6)shi6=0;}
  94. if(KKKEY==3) {KKKEY=0;kk=~kk;;}

  95. ////写入epprom
  96. if(KKKEY>0){
  97. shanchu(0x0000);
  98. xieru(0x0001,fen60)    ;
  99. xieru(0x0002,shi6)    ;  }
  100. DJS=(shi6*ss+fen60*60);  //单位是秒。

  101. }
  102. /*******************************************************************************
  103. * 函 数 名         : main
  104. * 函数功能           : 主函数
  105. * 输    入         : 无
  106. * 输    出         : 无
  107. *******************************************************************************/

  108. void main(void)
  109. {     
  110.     ConfigTimer0(5);
  111.     while(1)
  112.     {
  113.         key_sm();
  114.         
  115.            XX();
  116.         jidianqi=!kk;
  117.         DigDisplay();
  118.         if(countt<=0){kk=0;you23=0;     }
  119.     }               
  120. }

  121. /*******************************************************************************
  122. * 函 数 名         : DigDisplay
  123. * 函数功能           : 使用数码管显示
  124. * 输    入         : 无
  125. * 输    出         : 无
  126. *******************************************************************************/

  127. void DigDisplay()
  128. {
  129.     unsigned int j;
  130. //******************************
  131.     you1=0;
  132.     P1= DIG_CODE[X1];     //发送位选
  133.     j = 200;                         //扫描间隔时间设定
  134.     while(j--);   
  135.     P1 = 0x00;//消隐
  136.     you1=1;
  137. //******************************
  138.     you2=0;
  139.     P1= DIG_CODE[X2];     //发送位选
  140.     j = 200;                         //扫描间隔时间设定
  141.     while(j--);   
  142.     P1 = 0x00;//消隐
  143.     you2=2;
  144.     //******************************
  145.     you3=0;
  146.     P1= DIG_CODE[X3];     //发送位选
  147.     j = 200;                         //扫描间隔时间设定
  148.     while(j--);   
  149.     P1 = 0x00;//消隐
  150.     you3=3;
  151.     //******************************
  152.     you4=0;
  153.     P1 = DIG_CODE[X4];     //发送位选
  154.     j = 200;                         //扫描间隔时间设定
  155.     while(j--);   
  156.     P1 = 0x00;//消隐
  157.     you4=1;            
  158.             
  159.     }
  160. /* 配置并启动T0,ms-T0定时时间 */
  161. void ConfigTimer0(u8 ms)
  162. {
  163.     unsigned long tmp;  //临时变量
  164.    
  165.     tmp = 12000000 / 12;      //定时器计数频率
  166.     tmp = (tmp * ms) / 1000;  //计算所需的计数值
  167.     tmp = 65536 - tmp;        //计算定时器重载值
  168.     TMOD &= 0xF0;   //清零T0的控制位
  169.     TH0 = (u8)(tmp>>8);  //定时器重载值拆分为高低字节
  170.     TL0 = (u8)tmp;
  171.     ET0 = 1;        //使能T0中断
  172.     TR0 = 1;        //启动T0
  173.     EA=1;
  174. }
  175. //中断定义为5毫秒
  176. void InterruptTimer0() interrupt 1
  177. {   
  178.     static    u8 Di;
  179.          Di++;
  180.          if(kk==0){count_djs=0;you23=0;        }
  181.          if(Di==100) {you23=1;}      //秒显示赋值 0.5秒
  182.          if(Di==200 &&kk==1 ) {{you23=0;count_djs=count_djs+1;; }}
  183.          WDT_CONTR=0x37;       //看门狗刷新  8.4S         
  184.                  
  185. }
  186. /**/                 
  187. //按钮扫描     需在定时中断中调用
  188. void anjian()
  189. {
  190.     static u16 JiShu =0;
  191.     static u16 JiShu1=0;
  192.     static u16 JiShu2=0;
  193.     static u8 keybuf  = 0xff;
  194.     static u8 keybuf1 = 0xff;
  195.     static u8 keybuf2 = 0xff;
  196.     u8 nm=500;

  197.     keybuf = (keybuf <<1) |fen;
  198.     if(keybuf == 0x00)
  199.     { JiShu++; if(JiShu>=nm) {JiShu=0;KKKEY=1;} }

  200.     keybuf1 = (keybuf1 <<1) |shi;
  201.     if(keybuf1 == 0x00)
  202.     { JiShu1++; if(JiShu1>=nm) {JiShu1=0;KKKEY=2;} }

  203.     keybuf2 = (keybuf2 <<1) |kai;
  204.     if(keybuf2 == 0x00)
  205.     { JiShu2++; if(JiShu2>=nm) {JiShu2=0;KKKEY=3;} }}

  206. // epprom.c
  207. #include "epprom.h"
  208. void Delay(uchar n)
  209. {
  210. uint x;
  211. while (n--)
  212. {
  213. x = 0;
  214. while (++x);
  215. }
  216. }
  217. void guanbi()        //iap闲置
  218. {                              
  219. IAP_CONTR = 0; //Close IAP function      \关闭IAP功能
  220. IAP_CMD = 0; //Clear command to standby    \清除待命命令
  221. IAP_TRIG = 0; //Clear trigger register    \清除触发寄存器
  222. IAP_ADDRH = 0x80; //Data ptr point to non-EEPROM area \数据ptr指向非EEPROM区域
  223. IAP_ADDRL = 0; //Clear IAP address to prevent misuse \清除IAP地址以防止误用
  224. }
  225. uchar duqu(uint addr)
  226. {
  227. uchar dat; //Data buffer     \数据缓冲区
  228. IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time \打开IAP功能,设置等待时间
  229. IAP_CMD = CMD_READ; //Set ISP/IAP/EEPROM READ command \设置ISP/IAP/EEPROM读取命令
  230. IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low \将ISP/IAP/EEPROM地址设置为低位
  231. IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high  \将ISP/IAP/EEPROM地址设置为高
  232. IAP_TRIG = 0x5a; //Send trigger command1 (0x5a)     \发送触发器命令1(0x5a)
  233. IAP_TRIG = 0xa5; //Send trigger command2 (0xa5)      \发送触发器命令2(0xa5)
  234. _nop_(); //MCU will hold here until ISP/IAP/EEPROM \MCU将在此保持,直到ISP/IAP/EEPROM
  235. //operation complete \操作完成
  236. dat = IAP_DATA; //Read ISP/IAP/EEPROM data \读取ISP/IAP/EEPROM数据
  237. guanbi(); //Close ISP/IAP/EEPROM function \关闭ISP/IAP/EEPROM功能
  238. return dat; //Return Flash data    \返回闪存数据
  239. }
  240. void xieru(uint addr, uchar dat)
  241. {
  242. IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time \打开IAP功能,设置等待时间
  243. IAP_CMD = CMD_PROGRAM; //Set ISP/IAP/EEPROM PROGRAM command    \设置ISP/IAP/EEPROM程序命令
  244. IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low \将ISP/IAP/EEPROM地址设置为低位
  245. IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high \将ISP/IAP/EEPROM地址设置为高
  246. IAP_DATA = dat; //Write ISP/IAP/EEPROM data     \写入ISP/IAP/EEPROM数据
  247. IAP_TRIG = 0x5a; //Send trigger command1 (0x5a)     \发送触发器命令1(0x5a)
  248. IAP_TRIG = 0xa5; //Send trigger command2 (0xa5)     \发送触发器命令2(0xa5)
  249. _nop_(); //MCU will hold here until ISP/IAP/EEPROM \MCU将在此保持,直到ISP/IAP/EEPROM
  250. //operation complete  \操作完成
  251. guanbi();
  252. Delay(1);
  253. }
  254. void shanchu(uint addr)
  255. {
  256. IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time \打开IAP功能,设置等待时间
  257. IAP_CMD = CMD_ERASE; //Set ISP/IAP/EEPROM ERASE command    \设置ISP/IAP/EEPROM擦除命令
  258. IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low \将ISP/IAP/EEPROM地址设置为低位
  259. IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high \将ISP/IAP/EEPROM地址设置为高
  260. IAP_TRIG = 0x5a; //Send trigger command1 (0x5a)    \发送触发器命令1(0x5a)
  261. IAP_TRIG = 0xa5; //Send trigger command2 (0xa5)    \发送触发器命令2(0xa5)
  262. _nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete \MCU将在此保持,直到ISP/IAP/EEPROM操作完成
  263. //
  264. guanbi();
  265. }

  266. //epprom.h

  267. #ifndef __EPPROM1_H__
  268. #define __EPPROM1_H__
  269. //---包含头文件---//
  270. #include "STC15F2K.h"
  271. #include "intrins.h"
  272. //typedef unsigned char BYTE;
  273. //typedef unsigned int WORD;
  274. //---重定义关键词---//
  275. #ifndef uchar
  276. #define uchar unsigned char
  277. #endif

  278. #ifndef uint
  279. #define uint unsigned int
  280. #endif
  281. #endif
  282. #define CMD_IDLE 0 //Stand-By
  283. #define CMD_READ 1 //Byte-Read
  284. #define CMD_PROGRAM 2 //Byte-Program
  285. #define CMD_ERASE 3 //Sector-Erase
  286. #define ENABLE_IAP 0x82 //if SYSCLK<20MHz
  287. #define IAP_ADDRESS 0x0000
  288. void Delay(uchar n);
  289. void guanbi();
  290. uchar duqu(uint addr);
  291. void xieru(uint addr, uchar dat);
  292. void shanchu(uint addr);
复制代码

Keil代码与Proteus仿真下载:
定时器带显示20211206.7z (1.57 MB, 下载次数: 40)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:477512 发表于 2021-12-29 17:32 | 只看该作者
你这个电路没有DS3231,电路一旦停电,时间归零,还得从头开始!
回复

使用道具 举报

板凳
ID:705074 发表于 2021-12-29 23:51 | 只看该作者
wbwcf13e 发表于 2021-12-29 17:32
你这个电路没有DS3231,电路一旦停电,时间归零,还得从头开始!

这个电路是倒计时关闭电源插座,用时间中断计时,不用DS3231.
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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