数码之家

 找回密码
 立即注册
搜索
查看: 2183|回复: 27

[C51] 小白自学C51单片机编程,定时器分钟秒钟

[复制链接]
发表于 2023-12-20 11:30:25 | 显示全部楼层 |阅读模式
昨天写了一个0-9999的累加程序,受到不少网友的帮助,在此先说声谢谢,
今天写了一个用定时器实现分钟,秒钟的程序,
先上原理图
4位数码管的位控制和段接口如下,




uchar code table[]={}
这条语句内的16进制数转换成二进制就是下图这样的
1就表示二极管不亮,0就表示亮
8个二极管的亮与不亮就成了数字,




效果图



以下为代码,在昨天代码基础上修改来的

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

sbit a = P1^0;    //个位
sbit b = P1^1;    //十位
sbit c = P1^2;    //百位
sbit d = P1^3;    //千位

uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f};  //最后一个是小数点

uint time=0;  // 秒
uint fen=0;  // 分
uint xms;
uchar dingshi=0; //定时次数

void display(time);
void delay(xms);

void main ()
{
     TMOD=0X01;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    EA=1;
    ET0=1;               
    TR0=1;
    while(1)
    {
        display(time);
    }
}

void display(time)
{
      P0=table[time%10];
     a=0;
     delay(5);
     a=1;

     P0=table[time/10%10];
     b=0;
     delay(5);
     b=1;

      P0=table[fen%10];
     c=0;
     delay(5);
     c=1;

     P0=table[fen/10%10];
     d=0;
     delay(5);
     d=1;
   
     P0=table[10];  //显示一个点,
     d=0;
     delay(5);
     d=1;
}
void delay(xms)
{
     uchar i;
    while(xms--)
    {
         for(i=0;i<113;i++);
    }
}


void jishu ()interrupt 1
{   
    TH0=(65536-45872)/256;
    TL0=(65536-45872)%256;
   
     if(dingshi==20)  //如果定时了20次,也就是1秒钟就执行括号内程序
    {
         dingshi=0;  
        time++;   //秒加1
        if(time==60)
        {
             time=0;
            fen++;  //秒加了60分加1
            if(fen==60)
            {
                 fen=0;
            }
        }      
    }            
    dingshi++;  
}



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 2023-12-20 15:25:57 | 显示全部楼层
好奇,简单的线路图用什么软件画的。
回复 支持 反对

使用道具 举报

发表于 2023-12-21 08:46:51 | 显示全部楼层
好。。。

有一个小小建议,
**点不是独立的、结合对应的位
**减少使用delay(),相对更“准确”
**全局变量不必给函数传参数了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-21 09:59:20 | 显示全部楼层
devcang 发表于 2023-12-21 08:46
好。。。

有一个小小建议,

谢谢
也就是说uint time=0;  // 秒  直接写成uint time就可以了吗?默认是0吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-21 10:02:06 | 显示全部楼层
如果我要在这基础上加一个外部中断1,接口是P3.3  电路上P3.3接了一个按键,按下时,分钟加5分,程序上要怎样实现呢?
回复 支持 反对

使用道具 举报

发表于 2023-12-21 11:06:17 来自手机浏览器 | 显示全部楼层
我发现,无论是教材还是网上的例子程序,需要延时就delay(),需要显示就直接端口输出/控制显示芯片,需要按键就开中断,寄存器值、显示字符码直接使用立即数0x**……这些方式在用于生产目的的程序中几乎是不会使用的。我多次说过,再简单的程序也要按接口层加应用层设计,可能开始不能理解为什么要这么做,只要按这种思路修改程序就可以。
回复 支持 1 反对 0

使用道具 举报

发表于 2023-12-21 11:23:54 | 显示全部楼层
hellozwt 发表于 2023-12-21 09:59
谢谢
也就是说uint time=0;  // 秒  直接写成uint time就可以了吗?默认是0吗?

全局变量,不用再传递给函数,在函数内直接使用。
回复 支持 反对

使用道具 举报

发表于 2023-12-21 11:26:12 | 显示全部楼层
hellozwt 发表于 2023-12-21 10:02
如果我要在这基础上加一个外部中断1,接口是P3.3  电路上P3.3接了一个按键,按下时,分钟加5分,程序上要怎 ...

简单地,可以这样,
主函数开中断0,然后中断中如此:

void ex_int_0 ()interrupt 0
{   
            fen+=5;  //分加5
            if(fen>=60)
            {
                 fen=fen-60;
            }
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-21 14:03:39 | 显示全部楼层
mmxx2015 发表于 2023-12-21 11:06
我发现,无论是教材还是网上的例子程序,需要延时就delay(),需要显示就直接端口输出/控制显示芯片,需要按 ...

谢谢指导,不过对初学者来说,什么是接口层,什么是应用层,根本理解不了,能否有简单的示例,初学都对着示例就好理解了,谢谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-21 14:06:43 | 显示全部楼层
devcang 发表于 2023-12-21 11:26
简单地,可以这样,
主函数开中断0,然后中断中如此:

谢谢指导,
回复 支持 反对

使用道具 举报

发表于 2023-12-21 17:10:24 | 显示全部楼层
虽然程序能正常运行,通常在产品设计的时候不是这样设计的,首选数码管一般选用共阴数码管,共阴数码管和共阳数码管的成本是一样的,驱动电路不一样,大多数单片机的IO输出电流比较小,一般不超过15mA,灌电流则较大,一般都能达到50mA以上,所以共阴数码管可直接用IO驱动,还能省掉几个三极管和电阻。
程序上我只年了前面几行,虽说能运行,但是明显不规范。
  1. #define uchar unsigned char
  2. #define uint unsigned int
  3. 这里不应该使用宏定义,应该使用数据类型定义,如下
  4. typedef unsigned char uchar;
  5. typedef unsigend int uint;
  6. 通常会写成下面的方式
  7. typedef unsigned char uint8_t;
  8. typedef unsigned int   uint16_t;

  9. 下面是定义了数码管的几个位控制
  10. sbit a = P1^0;    //个位
  11. sbit b = P1^1;    //十位
  12. sbit c = P1^2;    //百位
  13. sbit d = P1^3;    //千位
  14. 一般这样写
  15. #define LED_COM_A P10
  16. #define LED_COM_B P11
  17. #define LED_COM_C P12
  18. #define LED_COM_D P13

  19. 定时器的初始化一般封装成一个函数,参数就是定时时间

  20. 数码管的扫描一般是放在定时中断函数中调用
复制代码


回复 支持 反对

使用道具 举报

发表于 2023-12-21 17:29:07 | 显示全部楼层
第一步就成功了,恭喜迈进单片机世界!
回复 支持 反对

使用道具 举报

发表于 2023-12-21 17:30:17 | 显示全部楼层
devcang 发表于 2023-12-21 11:26
简单地,可以这样,
主函数开中断0,然后中断中如此:

有可能按一下产生很多次中断
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-12-21 19:47:33 | 显示全部楼层
devcang 发表于 2023-12-21 08:46
好。。。

有一个小小建议,

我不知道让这个点亮一秒灭一秒要怎样写代码
回复 支持 反对

使用道具 举报

发表于 2023-12-21 20:10:51 来自手机浏览器 | 显示全部楼层
hellozwt 发表于 2023-12-21 19:47
我不知道让这个点亮一秒灭一秒要怎样写代码

把要显示的内容做成一个表就可以了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-22 08:15:23 | 显示全部楼层



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

发表于 2023-12-22 09:08:23 | 显示全部楼层
程序的点在的位,显示的在c位,不知道怎么做到的
显示点和数在同一位,数据或一下然后一起输出
回复 支持 反对

使用道具 举报

发表于 2023-12-22 09:15:07 | 显示全部楼层
视觉暂留时间0.1-0.4s,4位数字中断后每次更新一位,更新完就休眠或者做其他有意义的事,等待中断唤醒再次刷新,中断频率40Hz以上就显示的不错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-22 09:54:29 | 显示全部楼层
bg4rff 发表于 2023-12-22 09:15
视觉暂留时间0.1-0.4s,4位数字中断后每次更新一位,更新完就休眠或者做其他有意义的事,等待中断唤醒再次刷 ...

休眠 唤醒现在还不懂,现在还是看着教程慢慢理解的基础阶段,
回复 支持 反对

使用道具 举报

发表于 2023-12-22 10:09:22 | 显示全部楼层
bg4rff 发表于 2023-12-22 09:08
程序的点在的位,显示的在c位,不知道怎么做到的
显示点和数在同一位,数据或一下然后一起输出 ...

看7段数码管的各位定义未?   最高位就是小数点。
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-8 03:39 , Processed in 0.234001 second(s), 10 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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