中断及定时器实现时钟功能

中断及定时器实现24时 时钟,程序如下:

#include <reg52.h>

 

#define PORTLEN P0

 

sbit bit_select = P2^0;

sbit seg_select = P2^1;

 

unsigned char src[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

unsigned char qrc[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

unsigned char second1[8];

unsigned char shi = 0;

unsigned char fen = 0;

unsigned char miao = 0;

 

void timer0_init(void)

{

  EA = 1;  //打开总中断

  TMOD |= 0x01; //设置工作方式

  TH0 = (65536 - 20000) / 256;

  TL0 = (65536 - 20000) % 256;  //设置定时器初值,1ms产生一次中断

  ET0 = 1;   //打开定时器中断

  TR0 = 1;   //打开定时器,开始每隔1ms1

} //打开计时器开始加1,当TH0 =0xff,TL0=0xff时,TF0(单片机内部定时器的溢出标志位,一般无需手动置位)01,触发中断,并重新置0.

然后向cpu请求中断,cpu响应的话就跳转到中断函数,即void timer0_isr() interrupt 1

 

void timer1_init(void)

{

  EA = 1;

  TMOD |= 0x10;

  TH1 = (65536 - 1000) / 256;

  TL1 = (65536 - 1000) % 256;

  ET1 = 1;

  TR1 = 1;

}

 

void main()

{

      timer0_init();

  timer1_init();

  while(1);

}

//while(1)相当于死循环,这边有个注意点,两个timerwhile里外的区别,后文中具体讲解。

 

void display()

{

    static unsigned char i = 0;

  PORTLEN = 0x0;   //消重影

  seg_select = 1;

  seg_select = 0;

  PORTLEN = 0xff;

  bit_select = 1;

  bit_select = 0;

  PORTLEN = second1[i];

  seg_select = 1;

  seg_select = 0;

  PORTLEN = qrc[i];

  bit_select = 1;

  bit_select = 0;

  

  i++;

  if(8 == i)

{

  i = 0;

}

}

 

void timer0_isr() interrupt 1        

{

  static unsigned char i = 0;

    TH0 = (65536 - 20000) / 256;

    TL0 = (65536 - 20000) % 256;   //设置定时器初值,每隔20ms产生一次中断

  i++;

  if(50 == i)

{

  i = 0;

        miao++;

  if(60 == miao)

{   

  miao = 0;

  fen++;

  if(60 == fen)

{

  fen = 0;

  shi++;

  if(24 == shi)

{

  shi = 0;

}

}

}

    }

second1[0] = src[shi / 10];

second1[1] = src[shi % 10];

second1[2] = 0x40;

second1[3] = src[fen / 10];

second1[4] = src[fen % 10];

second1[5] = 0x40;

second1[6] = src[miao / 10];

second1[7] = src[miao % 10];

}

 

void timer1_isr() interrupt 3

{

    TH1 = (65536 - 1000) / 256;

  TL1 = (65536 - 1000) % 256;

  display();

}

 //interrupt   x跟在interrupt   后面的x值是中断号,就是说这个函数对应第几个中断端口,在510   外部中断0 ;  1   定时器0 ;2   外部中断1 ;3   定时器1 ;4   串行中断

实际上编译的时候就是把你这个函数的入口地址方到这个对应中断的跳转地址

————————————————————————————————

接下来来讲讲while了,用AB分别代替timer0_init  time1_init 两个函数,A+,B+表示两个中断服务程序。

A,B执行完继续执行A,但要注意的是,A,B的执行 只是在执行的最后打开了定时器,可以近乎当作A结束开始定时器累加,然后同理B,但是B一结束又到AATHTL重新给值导致一直在中断,并未进入中断服务函数,这里要修改的话,就需要加入一个自己的delay延时函数,给他时间进入中断服务程序,但是这样意义也不是多大不如第二种

②第二种的话,则是,A,B,执行完,就一直在while里,等到A,B发出中断响应,按照优先级进入中断服务程序,等中断服务程序按其内中断结束,返回while里,(在中断服务程序里已再次给初值,定时器开启后不自动关)B一直在刷新display,A则是给temp数组给值。

上图右侧 看作执行时间是错误的,忘了改了,中断服务程序里的1ms和20ms只是再次赋初值

如有错误理解,还请留言

 

 

  • 9
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
51单片机可以通过定时器来控制数码管时钟的显示。以下是实现的步骤: 1. 首先需要设置定时器的工作模式和计数器初值。这里可以选择定时器的模式为计数模式,计数器的初值为65535-50000,即每隔500ms中断一次。 2. 在定时器中断服务函数中,需要对数码管进行扫描和显示。具体实现可以通过循环扫描8个数码管,以共阳极数码管为例,先将所有数码管的位选信号置低,然后将当前要显示的数字通过段选信号输出到数码管上,最后将对应的位选信号置高,使其显示出来。 3. 在主函数中,需要开启定时器并启用中断,以便定时器中断服务函数能够正常运行。 下面是一个简单的代码示例: ```c #include <reg51.h> // 数码管显示的数字 unsigned char disp[8] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07}; // 定时器中断服务函数 void timer_isr() interrupt 1 { static unsigned char digit = 0; // 当前显示的数码管 P2 = 0xff; // 关闭所有数码管的位选 // 显示当前数码管的数字 P0 = disp[digit]; // 选中当前数码管 P2 = ~(1 << digit); // 切换到下一个数码管 digit++; if (digit >= 8) digit = 0; } void main() { TMOD = 0x01; // 定时器0工作在模式1(16位计数器)下 TH0 = 0xd8; // 定时器初值为65535-50000 TL0 = 0xf0; ET0 = 1; // 开启定时器0中断 EA = 1; // 开启总中断 TR0 = 1; // 启动定时器0 while (1) { // 主循环中不需要做什么,定时器中断服务函数会定时扫描和显示数码管 } } ``` 需要注意的是,以上代码仅供参考,具体实现可能需要根据实际情况进行调整和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值