这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 高校专区» 坤创E-Geek/天科大新电社» 07. 单片机定时计数器的使用

共12条 1/2 1 2 跳转至

07. 单片机定时计数器的使用

高工
2019-01-25 21:45:33 打赏

很开心,大家能够继续跟上进度,进行单片机定时计数器的学习。单片机的定时计数器,是学习单片机一个非常重要的点,正确的使用定时计数器,能够减轻单片机CPU的负担,可以增强程序的实时性。例如我们之前所用的ms级别的延时函数,是通过两个for循环的嵌套,使程序不断的在原地进行“等待”,这样一来,单片机的CPU就会在延时的同时,被100%占用,导致当延时函数执行时,单片机无法做其他的任何事情。显然,这对单片机CPU的资源是一个极大的浪费,特别是程序中有较长的延时需求时,更是如此。而定时计数器的出现,则能够很好的解决了这一问题。

当然,从蓝桥杯竞赛的角度来说,定时计数器的使用也是一个较重要的编程技能,聪明的使用定时计数器,能够让你的程序更加灵活,也更容易设计、编写和维护

本节针对定时计数器,设计了两个练习题,题目要求如下:

题1、在数码管上显示字符8,利用定时器定时每1秒左移动一位

题2、数码管初始显示0,利用定时器定时每1秒数值加1

下面仍照惯例给出两个题目的代码,并在文末给出所有代码压缩包的下载链接,请大家自行下载哈~当然,本系列中所有的代码,均在相对应的开发板上验证通过,大家可以放心下载~

-----------------------蓝桥板代码---------------------

蓝桥板题1代码:

/********************************************************************* 1、在数码管上显示字符8,利用定时器定时每1秒左移动一位 **********************************************************************/ #include #include #define uchar unsigned char #define uint unsigned int uchar code smgwei[]={0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80,0x01}; uint tt; uchar a=8; void init(); //蓝桥杯板初始化程序 void keyScan();//键盘扫描 void delayms(uint z);//ms级延时函数 void timer0Init(void); //5毫秒@11.0592MHz void display(uchar j ); //数码管显示函数 /**********************主函数********************************/ /*void main() { init(); timer0Init(); while(1) { EA=1; //开总中断 ET0=1; //开定时计数器中断 if(tt>=200) { tt=0;a--; if(a==0)a=8; } display(a); } } void delayms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=845;y>0;y--); } void init() { P2=0xa0; P0=0x00; //关闭继电器蜂鸣器 P2=0x80; P0=0xff; //关闭led灯 P2=0xc0; P0=0xff; //选择所有数码管 P2=0xff; P0=0xff; //关闭所有数码管 } void timer0Init(void) //5毫秒@11.0592MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x00; //设置定时初值 TH0 = 0x28; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 } void timer0()interrupt 1 { tt++; } void display(uchar j ) { P2=0xc0; P0=smgwei[j]; //位选 P2=0xff; P0=0x80; //段选 delayms(5); }

蓝桥板题2代码:

/*************************************************************** 2、数码管初始显示0,利用定时器定时每1秒数值加1 ****************************************************************/ #include #include"intrins.h" #define uchar unsigned char #define uint unsigned int uchar code smgtab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF}; uchar yi,er,san,si,wu,liu,qi,ba; uint num; uchar tt; void init();//蓝桥杯板初始化程序 void delayms(uint z);//ms级延时函数 void timer0Init(void); //5毫秒@11.0592MHz void displayOne(uchar yi,uchar er);//第一 二个数码管显示函数 void displayTwo(uchar san,uchar si);//第三 四个数码管显示函数 void displayThree(uchar wu,uchar liu);//第五 六个数码管显示函数 void displayFour(uchar qi,uchar ba);//第七 八个数码管显示函数 /****************************主函数**********************************/ void main() { init(); timer0Init(); //5毫秒@11.0592MHz while(1) { yi=11; er=11;san=11;si=11;wu=11;liu=num/100; qi=num/10%10;ba=num%10; if(tt>=200){tt=0;num=num+1;} else if(num>999){num=0;} displayOne(yi,er); displayTwo(san,si); displayThree(wu,liu); displayFour(qi,ba); } } void timer0Init(void) //5毫秒@11.0592MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x00; //设置定时初值 TH0 = 0x28; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 EA=1; ET0=1; } void timer0()interrupt 1 { tt++; } void delayms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=845;y>0;y--); } void init() { P2=0xa0; P0=0x00; //关闭继电器蜂鸣器 P2=0x80; P0=0xff; //关闭led灯 P2=0xc0; P0=0xff; //选择所有数码管 P2=0xff; P0=0xff; //关闭所有数码管 } void displayOne(uchar yi,uchar er) { P2=0xc0; P0=0x01; //选通第一个数码管 P2=0xff; P0=smgtab[yi];//位选 delayms(1); P2=0xc0; P0=0x02; //选通第二个数码管 P2=0xff; P0=smgtab[er];//位选 delayms(1); } void displayTwo(uchar san,uchar si) { P2=0xc0; P0=0x04; //选通第三个数码管 P2=0xff; P0=smgtab[san];//位选 delayms(1); P2=0xc0; P0=0x08; //选通第四个数码管 P2=0xff; P0=smgtab[si];//位选 delayms(1); } void displayThree(uchar wu,uchar liu) { P2=0xc0; P0=0x10; //选通第五个数码管 P2=0xff; P0=smgtab[wu];//位选 delayms(1); P2=0xc0; P0=0x20; //选通第六个数码管 P2=0xff; P0=smgtab[liu];//位选 delayms(1); } void displayFour(uchar qi,uchar ba) { P2=0xc0; P0=0x40; //选通第七个数码管 P2=0xff; P0=smgtab[qi];//位选 delayms(1); P2=0xc0; P0=0x80; //选通第八个数码管 P2=0xff; P0=smgtab[ba];//位选 delayms(1); }

-----------------------小红板代码----------------------

小红板题1代码:

/************************************************** 1、在数码管上显示字符8,利用定时器定时每1秒左移动一位 **************************************************/ #include"reg52.h" #define uchar unsigned char #define uint unsigned int sbit P_HC595_SER = P2^7; //pin 14 SER data input sbit P_HC595_RCLK = P2^5; //pin 12 RCLk store (latch) clock sbit P_HC595_SRCLK = P2^6; //pin 11 SRCLK Shift data clock uchar code smgwei[]={0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F,0XFE}; uchar i=8; uint tt; void smg_Init(); //数码管初始化程序 void delayms(uint z);//ms级延时函数 void display(uchar j);//数码管显示函数 void timer0Init(void);//50毫秒@11.0592MHz void Send_595(unsigned char dat); /**************主函数************************/ /*void main() { smg_Init(); timer0Init(); while(1) { EA=1; ET0=1; if(tt>=20) { tt=0;i--; if(i==0)i=8; } display(i); } } void delayms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void SMG_Init() { Send_595(0x00); //同时选择8个数码管 Send_595(0x00); //让8个数码管同时显示消隐字符 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 } void Send_595(unsigned char dat) //发送一个字节 { unsigned char i; for(i=0; i<8; i++) { if(dat & 0x80) //判断dat的最高位是否为1 P_HC595_SER = 1; //最高位如果为1,则令P2.7 = 1 else P_HC595_SER = 0; //最高位如果为0,则令P2.7 = 0 P_HC595_SRCLK = 0; P_HC595_SRCLK = 1; P_HC595_SRCLK = 0; //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端 dat = dat << 1; //将dat左移一位,取次高位 } } void timer0Init(void) //50毫秒@11.0592MHz { TR0 = 1;//启动T0 TMOD = 0x01;//T0为定时器,工作模式1 16位计数器 TH0 = 0x4b; TL0 = 0xfc;//0x4bfc 定时50ms } void timer0()interrupt 1 { tt++; } void display(uchar j ) { Send_595( smgwei[j]); Send_595(0x7f); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(5); }

小红板题2代码:

/******************************************** 2、数码管初始显示0,利用定时器定时每1秒数值加1。 ********************************************/ #include"reg52.h" #define uchar unsigned char #define uint unsigned int sbit P_HC595_SER = P2^7; //pin 14 SER data input sbit P_HC595_RCLK = P2^5; //pin 12 RCLk store (latch) clock sbit P_HC595_SRCLK = P2^6; //pin 11 SRCLK Shift data clock sbit s5=P3^0; sbit s10=P3^1; sbit s15=P3^2; sbit s20=P3^3; uchar code smgtab[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X00}; uint tt; uint num; uchar yi,er,san,si,wu,liu,qi,ba; void smg_Init();//数码管初始化程序 void delayms(uint z);//ms级延时函数 void timer0Init(void); //50毫秒@11.0592MHz void Send_595(unsigned char dat); void displayOne(uchar yi,uchar er);//第一 二个数码管显示函数 void displayTwo(uchar san,uchar si);//第三 四个数码管显示函数 void displayThree(uchar wu,uchar liu);//第五 六个数码管显示函数 void displayFour(uchar qi,uchar ba); //第七 八个数码管显示函数 /*******************主函数************************************/ void main() { smg_Init(); timer0Init(); //50毫秒@11.0592MHz while(1) { yi=11;er=11;san=11;si=11;wu=11;liu=num/100;qi=num/10%10;ba=num%10; EA=1; ET0=1; if(tt>=20){tt=0;num=num+1;} else if(num>999){num=0;} //uint形最大计数值为65536 displayOne(yi,er); displayTwo(san,si); displayThree(wu,liu); displayFour(qi,ba); } } void delayms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void timer0Init(void) //50毫秒@11.0592MHz { TR0 = 1;//启动T0 TMOD = 0x01;//T0为定时器,工作模式1 16位计数器 TH0 = 0x4b; TL0 = 0xfc;//0x4bfc 定时50ms } void timer0()interrupt 1 { tt++; } void smg_Init() { Send_595(0x00); //同时选择8个数码管 Send_595(0x00); //让8个数码管同时显示消隐字符 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 } void Send_595(unsigned char dat) //发送一个字节 { unsigned char i; for(i=0; i<8; i++) { if(dat & 0x80) //判断dat的最高位是否为1 P_HC595_SER = 1; //最高位如果为1,则令P2.7 = 1 else P_HC595_SER = 0; //最高位如果为0,则令P2.7 = 0 P_HC595_SRCLK = 0; P_HC595_SRCLK = 1; P_HC595_SRCLK = 0; //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端 dat = dat << 1; //将dat左移一位,取次高位 } } void displayOne(uchar yi,uchar er) { Send_595(0xfe); //选通第一个数码管 Send_595(smgtab[yi]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xfd); //选通第二个数码管 Send_595(smgtab[er]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void displayTwo(uchar san,uchar si) { Send_595(0xfb); //选通第三个数码管 Send_595(smgtab[san]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xf7); //选通第四个数码管 Send_595(smgtab[si]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void displayThree(uchar wu,uchar liu) { Send_595(0xef); //选通第五个数码管 Send_595(smgtab[wu]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xdf); //选通第六个数码管 Send_595(smgtab[liu]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void displayFour(uchar qi,uchar ba) { Send_595(0xbf); //选通第七个数码管 Send_595(smgtab[qi]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0x7f); //选通第八个数码管 Send_595(smgtab[ba]);//段选 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); }

----------------所有代码打包下载链接------------------

07单片机定时计数器的使用_全部代码打包.zip

大家可以继续提前接着往下进行08.DS18B20温度传感器进行数据采集和使用的题目练习~如对代码有任何问题,请在下方回帖留言呀。

曾子在文末曰:“每篇文章末尾都有鸡汤,好烦啊。今天就什么都不曰了,正儿八经一回吧,明天再接着曰。”





关键词: 定时 计数器 使用 定时器

菜鸟
2019-01-25 22:11:34 打赏
2楼

感谢分享,51的资源缺陷往往考验着使用者,有的时候不得不考虑CPU运算时间的问题啊,力挺楼主!


高工
2019-01-26 09:43:10 打赏
3楼

代码的注释真的很详细,写的真是负责任,支持楼主!!!!!


菜鸟
2019-01-26 15:17:50 打赏
4楼

赞一个·


菜鸟
2019-01-26 18:27:13 打赏
5楼
感谢楼主分享

助工
2019-01-27 18:45:19 打赏
6楼
哇,膜拜楼主,解答了我好久的困惑,手动比心,哈哈哈

菜鸟
2019-01-27 18:52:52 打赏
7楼

对于备战的我来说太需要了,感谢老师


菜鸟
2019-01-31 14:04:45 打赏
8楼

定时器也是蓝桥杯比赛中的必考点 也是非常重要的


院士
2019-02-13 08:31:42 打赏
9楼

学习单片机定时计数器l啦!


工程师
2019-02-27 18:04:02 打赏
10楼
void timer0Init(void);这里括号里的void是什么意思?

共12条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]