历史上的今天
返回首页

历史上的今天

今天是:2025年12月07日(星期日)

正在发生

2022年12月07日 | 51单片机C语言程序100例分析(2)定时器+中断

2022-12-07 来源:zhihu

#include //包含 51 单片机寄存器定义的头文件

void main(void)

{

  TMOD=0x01;// 使用定时器 T0 的模式 1

  TH0=(65536-46083)/256; // 定时器 T0的高 8 位赋初值

  TL0=(65536-46083)%256; // 定时器 T0的低 8 位赋初值

  TR0=1; // 启动定时器 T0

  TF0=0; //清定时器溢出标志位

  P2=0xff;  

  while(1)// 无限循环等待查询  

  {  

    while(TF0==0);  

    TF0=0;  

    P2=~P2;//按位取反  

    TH0=(65536-46083)/256; // 定时器 T0 的高 8 位赋初值  

    TL0=(65536-46083)%256; // 定时器 T0 的低 8 位赋初值

  }

}


分析:新的寄存器出现了,它们分别是TMOD、TH0、TL0、TR0、TF0,只要掌握调用顺序就可以玩好定时器了。

实例 43 :用定时器 T1 查询方式控制单片机发出 1KHz 音频

#include // 包含 51 单片机寄存器定义的头文件

sbit sound=P3^7; 

void main(void)

  { 

    TMOD=0x10;// 使用定时器 T1 的模式 1

    TH1=(65536-921)/256; // 定时器 T1 的高 8 位赋初值

    TL1=(65536-921)%256; // 定时器 T1 的低 8 位赋初值

    TR1=1; 

    TF1=0; // 启动定时器 T1

    while(1)// 无限循环等待查询

    {

      while(TF1==0);

      TF1=0;

      sound=~sound; // 将 P3.7引脚输出电平取反

      TH1=(65536-921)/256; // 定时器 T0的高 8 位赋初值

      TL1=(65536-921)%256; // 定时器 T0的低 8 位赋初值

    }

  }  

实例 44:将计数器 T0 计数的结果送 P1 口 8 位 LED 显示

#include // 包含 51 单片机寄存器定义的头文件

sbit S=P3^4; // 将 S位定义为 P3.4引脚

void main(void)

{

  // EA=1; // 开总中断

  // 定时器 T0 中断允许  

  // ET0=1; 

  TMOD=0x02;// 使用定时器 T0 的模式 2

  TH0=256-156; // 定时器 T0的高 8 位赋初值

  TL0=256-156; // 定时器 T0 的高 8 位赋初值

  TR0=1; // 启动定时器 T0

  while(1)// 无限循环等待查询

  {

    while(TF0==0) // 如果未计满就等待

    {

      if(S==0) // 按键 S按下接地,电平为 0

      P1=TL0; //计数器 TL0加 1 后送 P1口显示

    }

    TF0=0; // 计数器溢出后,将 TF0清 0

  }

}  

分析:理论结合实例,效果很好吧。


实例 45:用定时器 T0 的中断控制 1 位 LED 闪烁

#include // 包含 51 单片机寄存器定义的头文件

sbit D1=P2^0; // 将 D1 位定义为 P2.0引脚

void main(void)

{

  EA=1;// 开总中断 

  ET0=1;// 定时器 T0 中断允许 

  TMOD=0x01;// 使用定时器 T0 的模式 1

  TH0=(65536-46083)/256; //定时器 T0 的高 8 位赋初值

  TL0=(65536-46083)%256; //定时器 T0的高 8 位赋初值

  TR0=1; // 启动定时器 T0

  while(1);

}

  

/**************************************************************

函数功能:定时器 T0 的中断服务程序

**************************************************************/

void Time0(void) interrupt 1 using 0 //寄存器

{

  D1=~D1; // 按位取反操作,将 P2.0引脚输出电平取反

  TH0=(65536-46083)/256; //定时器 T0 的高 8 位重新赋初值

  TL0=(65536-46083)%256; //定时器 T0的高 8 位重新赋初值

}  

实例 46:用定时器 T0 的中断实现长时间定时

#include // 包含 51 单片机寄存器定义的头文件

sbit D1=P2^0; // 将 D1 位定义为 P2.0引脚

unsigned char Countor; //设置全局变量,储存定时器 T0 中断次数

void main(void)

{

  EA=1; 

  ET0=1; 

  TMOD=0x01;

  TH0=(65536-46083)/256; //定时器 T0的高 8 位赋初值

  TL0=(65536-46083)%256; //定时器 T0的低 8 位赋初值

  TR0=1; // 启动定时器 T0

  Countor=0; // 从 0 开始累计中断次数

  while(1);

}

/**************************************************************

函数功能:定时器 T0 的中断服务程序

**************************************************************/

void Time0(void) interrupt 1 using 0

{

  Countor++; // 中断次数自加 1

  if(Countor==20) // 若累计满 20 次,即计时满 1s

  {

    D1=~D1; // 按位取反操作,将 P2.0引脚输出电平取反

    Countor=0; // 将 Countor 清 0,重新从 0 开始计数

  }

  TH0=(65536-46083)/256; //定时器 T0 的高 8 位重新赋初值

  TL0=(65536-46083)%256; //定时器 T0的高 8 位重新赋初值

}  

分析:这就是外存库,之前整理的中断和定时器没想到就是这里的片段。


实例 47:用定时器 T1 中断控制两个 LED 以不同周期闪烁

#include // 包含 51 单片机寄存器定义的头文件

sbit D1=P2^0; // 将 D1 位定义为 P2.0引脚

sbit D2=P2^1; // 将 D2 位定义为 P2.1引脚

unsigned char Countor1; //设置全局变量,储存定时器 T1 中断次数

unsigned char Countor2; //设置全局变量,储存定时器 T1 中断次数

void main(void)

{

  EA=1;// 开总中断 

  ET1=1; // 定时器 T1 中断允许

  TMOD=0x10; // 使用定时器 T1 的模式 1

  TH1=(65536-46083)/256; //定时器 T1 的高 8 位赋初值

  TL1=(65536-46083)%256; //定时器 T1的高 8 位赋初值

  TR1=1; // 启动定时器 T1  

  Countor1=0; // 从 0 开始累计中断次数

  Countor2=0; 

  while(1);

}

void Time1(void) interrupt 3 using 0

{

  Countor1++; //Countor1 自加 1

  Countor2++;//Countor2 自加 1

  if(Countor1==2) // 若累计满 2 次,即计时满 100ms

  {

    D1=~D1; // 按位取反操作,将 P2.0引脚输出电平取反

    Countor1=0; // 将 Countor1 清 0,重新从 0 开始计数

  }

  if(Countor2==8) // 若累计满 8 次,即计时满 400ms

  {

    D2=~D2; // 按位取反操作,将 P2.1引脚输出电平取反

    Countor2=0; // 将 Countor1 清 0,重新从 0 开始计数

  }

  TH1=(65536-46083)/256; //定时器 T1 的高 8 位重新赋初值

  TL1=(65536-46083)%256; //定时器 T1的高 8 位重新赋初值

}  

分析:慢慢欣赏吧,有问题欢迎评论。


实例 50-1 :输出 50 个矩形脉冲

#include // 包含 51 单片机寄存器定义的头文件

sbit u=P1^4; // 将 u 位定义为 P1.4

/*************************************************

函数功能:延时约 30ms (3*100*100=30 000μ s =30m

*************************************************/

void delay30ms(void)

{

  unsigned char m,n;

  for(m=0;m<100;m++)

  for(n=0;n<100;n++);

}

void main(void)

{

  unsigned char i;

  u=1; // 初始化输出高电平

  for(i=0;i<50;i++) //输出 50 个矩形脉冲

  {

    u=1;

    delay30ms();

    u=0;

    delay30ms(); 

  }

  while(1); 

}  

啦啦啦


实例 50-2:计数器 T0统计外部脉冲数

#include 

void main(void)

{

  TMOD=0x06; // TMOD=0000 0110B,使用计数器 T0 的模式 2

  EA=1; 

  ET0=0; // 不使用定时器 T0 的中断

  TR0=1;  // 启动 T0

  TH0=0; // 计数器 T0 高 8 位赋初值

  TL0=0;// 计数器 T0 低 8 位赋初值

  while(1) // 无限循环,不停地将 TL0计数结果送 P1口

  P1=TL0;

}

啊啊啊


实例 51-2 :定时器 T0 的模式 2 测量正脉冲宽度

#include // 包含 51 单片机寄存器定义的头文件

sbit ui=P3^2; // 将 ui 位定义为 P3.0( INT0)引脚,表示输入电压

void main(void)

{

  TMOD=0x0a; // TMOD=0000 1010B,使用定时器 T0 的模式 2, GATE置 1

  EA=1; // 开总中断

  ET0=0;// 不使用定时器 T0 的中断 

  TR0=1;// 启动 T0 

  TH0=0; // 计数器 T0 高 8 位赋初值

  TL0=0;  // 计数器 T0 低 8 位赋初值

  while(1)  // 无限循环,不停地将 TL0计数结果送 P1口

  {  

    while(ui==0)  //INT0 为低电平, T0 不能启动

    TL0=0; //INT0 为高电平,启动 T0 计时,所以将 TL0清 0

    while(ui==1) // 在 INT0 高电平期间,等待,计时

    P1=TL0; // 将计时结果送 P1口显示

  } 

}


哈哈哈


实例 53:用外中断 0 的中断方式进行数据采集

#include 

sbit S=P3^2;// 将 S位定义为 P3.2 

void main(void) // 包含 51 单片机寄存器定义的头文件

{

  EA=1; // 开放总中断

  EX0=1; // 允许使用外中断

  IT0=1; // 选择负跳变来触发外中断

  P1=0xff;

  while(1); 

}

void int0(void) interrupt 0 using 0 // 外中断 0 的中断编号为 0

{

  P1=~P1; // 每产生一次中断请求, P1取反一次。

}  

呐呐呐


实例 54-1 :输出负脉宽为 200 微秒的方波

#include // 包含 51 单片机寄存器定义的头文件

sbit u=P1^4;// 将u位定义为P1.4 

void main(void)

{

  TMOD=0x02; //TMOD=0000 0010B,使用定时器 T0 的模式 2

  EA=1;// 开总中断 

  ET0=1;// 定时器 T0 中断允许

  TH0=256-200; // 定时器 T0 的高 8 位赋初值

  TL0=256-200; // 定时器 T0 的高 8 位赋初值

  TR0=1; // 启动定时器 T0

  while(1);// 无限循环,等待中断

}

void Time0(void) interrupt 1 using 0 //"interrupt" 声明函数为中断服务函数

{

  u=~u; // 将 P1.4引脚输出电平取反,产生方波

}  

嗯嗯嗯


实例 54-2 :测量负脉冲宽度

#include // 包含 51 单片机寄存器定义的头文件

sbit u=P3^2;// 将 u 位定义为 P3.2 

void main(void)

{

  TMOD=0x02; //TMOD=0000 0010B,使用定时器 T0 的模式 2

  EA=1; // 开放总中断

  EX0=1; // 允许使用外中断

  IT0=1; // 选择负跳变来触发外中断

  ET0=1; // 允许定时器 T0 中断

  TH0=0; // 定时器 T0 赋初值 0

  TL0=0; // 定时器 T0 赋初值 0

  TR0=0; // 先关闭 T0

  while(1) ; // 无限循环, 不停检测输入负脉冲宽度

}

void int0(void) interrupt 0 using 0 // 外中断 0 的中断编号为 0

{

  TR0=1; // 外中断一到来,即启动 T0 计时

  TL0=0; // 从 0 开始计时

  while(u==0)// 低电平时,等待 T0 计时

  P1=TL0; //将结果送 P1口显示

  TR0=0; // 关闭 T0

}  

咯咯咯


实例 55:方式 0 控制流水灯循环点亮

#include // 包含 51 单片机寄存器定义的头文件

#include // 包含函数 _nop_()定义的头文件

unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};

// 流水灯控制码,该数组被定义为全局变量

sbit P17=P1^7;

/**************************************************************

函数功能:延时约 150ms

**************************************************************/

void delay(void)

{

  unsigned char m,n;

  for(m=0;m<200;m++)

  for(n=0;n<250;n++);

}

/**************************************************************

函数功能:发送一个字节的数据

**************************************************************/

void Send(unsigned char dat)

{

  P17=0;//P1.7 引脚输出清 0 信号,对 74LS164清 0  

  _nop_(); // 延时一个机器周期,保证清 0 完成

  P17=1; // 结束对 74LS164的清 0

  _nop_(); // 延时一个机器周期

  SBUF=dat; // 将数据写入发送缓冲器,启动发送

  while(TI==0); // 若没有发送完毕,等待

  TI=0;// 发送完毕, TI被置“ 1”,需将其清 0

}

/*******************************************

函数功能:主函数

******************************************/

void main(void)

{

  unsigned char i;

  SCON=0x00; //SCON=0000 0000B,使串行口工作于方式 0

  while(1)

  {

    for(i=0;i<8;i++)

    {

      Send(Tab[i]); // 发送数据

      delay(); // 延时

    }

  }

}  

略略略


打开串口调试程序,将波特率设置为9600,无奇偶校验晶振11.0592MHz,发送和接收使用的格式相同,如都使用字符型格式,在发送框输入hello, I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确,

include   

void main (void)

{

  SCON = 0x50; //SCON:模式 1,8-bit UART,使能接收V 

  TMOD = 0x20; /*TMOD: timer 1, mode 2,8-bit reload*/

  TH1 =0xFD;// TH1:重新加载值为9600波特

  TR1 = 1;// 启动定时器1

  EA = 1; //幵总中断

  ES = 1; //打开串口中断

  while (1); //主循环不做任何动作

}

void UART_SER (void) interrupt 4 //串行中断服务程序

{

  unsigned char Temp; //定义临吋变量 

  if(RI) //判断是接收中断产生

  {

    RI = 0;//标志位清零

    Temp = SBUF;//读入缓存区的值

    P1=Temp;//把值输出到P1口,用于观察

    SBUF = Temp;//把接收到的值再发回电脑端

  }

  if(TI) //如果是发送标志位,淸零

  TI = 0;

}

#include

void ConfigUART(unsigned int baud);

void main ()

{

   ConfigUART(9600);  //配置波特率为9600

   while(1)

   {

       while (!RI);     //等待接收完成

       RI = 0;          //清零接收中断标志位

       SBUF = SBUF + 1; //接收到的数据+1后,发送回去;

       //等号左边的SBUF实际上就是发送SBUF,因为对它的操作是“写”;

       //等号右边的是接收SBUF,因为对它的操作是“读”。

       while (!TI);     //等待发送完成

推荐阅读

史海拾趣

Alpha Industries公司的发展小趣事

在环保意识日益增强的今天,Alpha Industries积极响应绿色生产的号召。公司利用电子技术优化生产流程,减少能源消耗和废弃物排放。此外,Alpha Industries还推出了采用环保材料制成的军事服装系列,以实际行动践行绿色环保理念。这些举措不仅有助于提升公司的社会形象,也为公司的可持续发展奠定了坚实基础。

这些故事展示了Alpha Industries如何在电子技术的推动下,不断创新并适应市场变化,进而在相关领域取得显著发展。尽管这些故事并未直接涉及电子行业的核心业务,但它们却充分体现了Alpha Industries在技术创新和市场拓展方面的积极努力和取得的成果。

Avery Dennison公司的发展小趣事

1990年,Avery Adhesives与Dennison Manufacturing合并,成立了Avery Dennison公司。这一合并不仅增强了公司的实力,也为其全球扩张提供了有力支持。此后,Avery Dennison通过在欧洲建立工厂、收购其他公司等方式,不断拓展其业务版图。如今,公司的业务已经遍及50多个国家,成为全球领先的标签与包装材料解决方案提供商。

高创科技(gotrend)公司的发展小趣事

1990年,Avery Adhesives与Dennison Manufacturing合并,成立了Avery Dennison公司。这一合并不仅增强了公司的实力,也为其全球扩张提供了有力支持。此后,Avery Dennison通过在欧洲建立工厂、收购其他公司等方式,不断拓展其业务版图。如今,公司的业务已经遍及50多个国家,成为全球领先的标签与包装材料解决方案提供商。

FCI / Amphenol公司的发展小趣事

2005年,FCI迎来了新的发展机遇。贝恩资本,一家在全球近75个工业领域和技术公司有着丰富投资经验的私有投资基金,决定收购FCI。贝恩资本的加入为FCI提供了强大的财力和国际业务支持,使得FCI在连接器市场上更具竞争力。这一收购也标志着FCI正式迈入了一个新的发展阶段。

Amphenol公司的发展故事

Hengstler GmbH公司的发展小趣事

Amphenol公司成立于1932年,最初由Arthur J. Schmitt和Gordon K. Klapmeier共同创办,专注于电磁线缆的制造。然而,随着技术的进步和市场需求的变化,Amphenol公司逐渐将重心转向电缆连接器的制造。凭借高品质的产品和服务,Amphenol公司的电缆连接器在市场上获得了广泛的认可,并逐渐发展成为全球最大的电缆连接器制造商之一。

Crystal Clear Technology公司的发展小趣事

随着公司业务的不断扩张和盈利能力的提升,Crystal Clear Technology逐渐吸引了资本市场的关注。公司通过发行股票和债券等方式筹集资金,为公司的研发、生产和市场拓展提供了强有力的资金支持。资本市场的助力使得Crystal Clear Technology能够更快地实现规模扩张和产业升级,成为电子行业的一颗璀璨明星。

以上五个故事虽然是根据一般情况和行业趋势虚构的,但它们反映了一个电子企业在发展过程中可能遇到的挑战和机遇,以及如何通过技术创新、战略合作、国际化布局、环保理念和资本市场支持等方式实现快速成长。当然,每个企业的发展历程都是独特的,Crystal Clear Technology公司的发展故事也必然有其独特之处。

问答坊 | AI 解惑

常用的光电器件对比表(RoHS)

名    称 常用封 装外形 光谱(nm) 最大光电流 (10Lx)(μA) 特    点 缺  点 可应用性 光敏二极管 ?3,?5 850 0.05 有一定线性 光电流小,暗电流大 需要多级放大,应用电路复杂 光敏三极 ...…

查看全部问答>

2407AD转换模块几种触发源的应用

下载链接: http://www.hellodsp.com/bbs/viewthread.php?tid=7326…

查看全部问答>

超声波测距问题

本帖最后由 paulhyde 于 2014-9-15 09:10 编辑 最近买了个超声波测距模块,但发现程序与引脚对不上,调试的时候有错误,希望高手指点  …

查看全部问答>

【藏书阁】电子学计算手册

目录: 第一章 技术数学复习 第二章 直流电路分析 第三章 交流电路分析 第四章 R、L、C元件的选择 第五章 半导体器件的选择 第六章 音频放大器 第七章 调谐放大器 第八章 反馈 第九章 振荡器 第十章 电源 第十一章 电池的使用及特种元 ...…

查看全部问答>

三星2410上的USB驱动问题

我用的FFT-2410-V6.1的开发板,主板是三星的2410。开发板系统是Microsoft windows CE.NET版本是4.2。开发板有4个USBhost,插入键盘和鼠标都支持,但是插入我的U盘就不行了,出现“未能识别的USB设备,输入此USB设备的驱动程序名称-------”,有什么 ...…

查看全部问答>

pxa270休眠唤醒的怪问题。。

release版与debug版的区别在哪?把debug版本下的display驱动放到release下编译照样出样下列错误。。。 GP1 Irq PwrButtonIntrThread :go to sleep! SA2Video::PowerHandler++++++++++ DispDrvrPowerHandler----------bOff = 1 DispDrvrPowerHa ...…

查看全部问答>

cs8900a driver

最近在porting cs8900a driver, 从wince5.0 移到wince6.0中, 驱动编译成功,系统也能够检测到网卡,网络连接标示也有,可是与 pc 机就是ping 不通,不能连接到internet.硬件都没问题!希望那位大侠能够出手帮忙!!!…

查看全部问答>

信息产业部—硬件设计工程师培训火爆报名中!!!!!

目前全国的计算机硬件教育还处于起步阶段,由于实操环境和实验室的要求,大部分的培训机构和职业学校的硬件教育滞后于软件教育,导致学生技能水平低,不能满足就业的需求,同时对学生从事软件开发等高级职业造成了短腿的现象。    近 ...…

查看全部问答>

梦之旅同学松鼠1.0学习笔记(三)之矩阵键盘

  这几天事情比较多,所以就一直没有更新,呵呵,今天早上没课,把之前写好代码整理一下,顺便说下思路,发上来,供大家参考参考。   首先,本矩阵键盘硬件连接如下:       思路:   我的思路如下, ...…

查看全部问答>

师傅们 launchpad 那晶振怎么搞啊~为什么我弄不好呢~能给张照片吗?

初学者求照片~ 师傅们 launchpad 那晶振怎么搞啊~为什么我弄不好呢~能给张照片吗?…

查看全部问答>