找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1526|回复: 0
收起左侧

新手小白编写的51单片机可调时钟和原理图

[复制链接]
ID:1026584 发表于 2022-5-14 21:29 | 显示全部楼层 |阅读模式
电路原理图如下:
51hei.png 51hei.png
  1. #include <reg52.h>
  2. #define uchar unsigned char       //为宏定义,把unsigned char用uchar表示,方便书写
  3. #define uint unsigned int         //为宏定义,把unsigned int用uint表示,方便书写

  4. void display();                   //显示函数声明
  5. uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};   //0~9,-共阴极段码表数码管段选编码
  6. char hour =23, min =59, sec=55;   //定义全局变量时分秒并赋值

  7. sbit addr_A=P2^0;                 //定义addr_A为P2口的第一位
  8. sbit addr_B=P2^1;                 //定义addr_B为P2口的第二位
  9. sbit addr_C=P2^2;                 //定义addr_C为P2口的第三位

  10. sbit P10 = P1^0;                  //定义P10为P1口的第一位
  11. sbit P11 = P1^1;                  //定义P11为P1口的第二位
  12. sbit P12 = P1^2;                  //定义P12为P1口的第三位
  13. sbit P13 = P1^3;                  //定义P13为P1口的第四位

  14. uchar mode = 0;                   //0, 1, 2, 3分别表示正常计时、调时、调分、调秒模式
  15. uchar flash = 0xff;               //定义全局变量flash并赋值

  16. void delay(uint i) {              //延时函数的声明
  17.         while(i--);
  18. }

  19. void initT0() {                   //初始化定时器函数声明
  20.         TMOD = 0x01;                    //计数器工作在方式一,16位计数器
  21.         TH0 = (65536-50000)/256;        //给定时器0装初值,12MHZ晶振定时时间为50ms
  22.         TL0 = (65536-50000)%256;
  23.         EA =1;                          //开总中断
  24.         ET0 =1;                         //开定时器0分开关
  25.         TR0 =1;                         //启动定时器
  26. }

  27. void keyScan() {                  //键盘扫描函数
  28.           static bit oldState = 1;      //定义静态局部变量,保存按键的旧状态,1表示按键弹起,0表示按键已按下
  29.           if(!(P10&P11&P12&P13)) {      //判断是否可能有键按下
  30.                         delay(1000);                //延时消抖
  31.                         if(!(P10&P11&P12&P13)) {    //再次确认当前是否有键按下,且之前没有键按下
  32.                                 if(oldState) {        
  33.                                         oldState = 0;           //将旧键状态更新为已按下
  34.                                         if(!P10) {              //判断按键P10是否按下
  35.                                                 mode++;               //按下,mode模式加一
  36.                                                 if(mode>3) mode = 0;  //判断mode模式是否超出边界,超出清零
  37.                                         }
  38.                                         else if(!P11)           //判断按键P11是否按下
  39.                                                 switch(mode) {        //多分支选择语句
  40.                                                         case 1:hour++;if(hour>23) hour = 0;break;     //1模式下,小时加一;判断小时是否超出边界,超出清零;退出switch语句
  41.                                                         case 2:min++;if(min>59) min = 0;break;        //2模式下,分钟加一;判断分钟是否超出边界,超出清零;退出switch语句
  42.                                                         case 3:sec++;if(sec>59) sec = 0;break;        //3模式下,秒加一;判断秒是否超出边界,超出清零;退出switch语句
  43.                                                 }
  44.                                         else if(!P12){          //判断按键P12是否按下
  45.                                                 switch(mode) {
  46.                                                         case 1:hour--;if(hour<0) hour = 23;break;     //1模式下,小时减一;判断小时是否小于零,小于零给小时赋值23;退出switch语句
  47.                                                         case 2:min--;if(min<0) min = 59;break;        //2模式下,分钟减一;判断分钟是否小于零,小于零给分钟赋值59;退出switch语句
  48.                                                         case 3:sec--;if(sec<0) sec = 59;break;        //3模式下,秒减一;判断秒是否小于零,小于零给秒赋值59;退出switch语句
  49.                                                 }
  50.                                         //else   //关闭闹钟
  51.                                         }
  52.                         }
  53.                 }
  54.         }
  55.         else if(!oldState) oldState = 1;   //检测按键是否弹起
  56. }

  57. void main() {                     //主函数
  58.         initT0();                       //定时函数
  59.         while(1){                       //死循环
  60.                 keyScan();                    //键盘扫描函数
  61.                 display();                    //显示函数
  62.         }
  63. }

  64. void INT_T0() interrupt 1         //中断服务程序,其中1是定时器0入口序号
  65. {
  66.         static uchar counter = 0, counter_1=0;      //定义静态局部变量
  67.         TR0 = 0;                        //关闭定时器
  68.         TH0 = (65536-50000)/256;        //给定时器0装初值,12MHZ晶振定时时间为50ms
  69.         TL0 = (65536-50000)%256;
  70.         TR0 = 1;                        //启动定时器
  71.         counter++;                      //counter加一
  72.         counter_1++;                    //counter_1加一
  73.         if(counter_1==10) {             //counter_1经过0.5秒
  74.                  counter_1 = 0;               //counter_1清零
  75.                  flash = ~flash;              //全局变量flash按位取反
  76.         }
  77.         if(counter==20) {               //counter经过1秒
  78.                 counter = 0;                  //counter清零
  79.         if(mode==0) sec++;              //判断模式mode是否在0模式,是,秒加一
  80.         }
  81.         if(sec>=60) {                   //判断秒是否大于等于60
  82.                 sec = 0;                      //秒清零
  83.                 min++;                        //分加一
  84.         }
  85.         if(min>=60) {                   //判断分钟是否大于等于60
  86.                 min = 0;                      //分清零
  87.                 hour++;                       //小时加一
  88.         }
  89.         if(hour>=24) {                  //判断小时是否大于等于24
  90.                 hour = 0;                     //给小时赋0
  91.         }
  92. }

  93. void display() {                  //显示函数
  94.         uchar LED[8], i;                //定义数组LED,局部变量i
  95.         LED[0] = hour/10;               //给数组的第一位赋值,为小时数值十位上的数
  96.         LED[1] = hour%10;               //给数组的第二位赋值,为小时数值个位上的数
  97.         LED[2] = 10;                    //给数组的第三位赋值10
  98.         LED[3] = min/10;                //给数组的第四位赋值,为分钟数值十位上的数
  99.         LED[4] = min%10;                //给数组的第五位赋值,为分钟数值个位上的数
  100.         LED[5] = 10;                    //给数组的第六位赋值10
  101.         LED[6] = sec/10;                //给数组的第七位赋值,为秒钟数值十位上的数
  102.         LED[7] = sec%10;                //给数组的第八位赋值,为秒钟数值个位上的数
  103.        
  104.         for(i=0;i<8;i++) {              //FOR循环,数码管的位选
  105.                 addr_C = i/4;                 //最高位
  106.                 addr_B = i/2%2;               //第二位
  107.                 addr_A = i%2;                 //最低位
  108.                 if(i==(mode-1)*3 || i==(mode-1)*3+1) P0=table[LED[i]] & flash;
  109.                                               //mode  0  1  2  3        当模式mode和i满足关系
  110.                                               //i   01   34    67       i == (mode-1)*3时
  111.                                               //i == (mode-1)*3         数码管闪烁
  112.                 else P0 = table[LED[i]];      //不满足上述关系时,输出数码管的段选编码
  113.                 delay(200);                   //数码管延时
  114.                 P0 = 0X00;                    //数码管消隐
  115.         }
  116. }
  117.        
复制代码


评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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