很开心,大家能够继续跟上进度,进行单片机定时计数器的学习。单片机的定时计数器,是学习单片机一个非常重要的点,正确的使用定时计数器,能够减轻单片机CPU的负担,可以增强程序的实时性。例如我们之前所用的ms级别的延时函数,是通过两个for循环的嵌套,使程序不断的在原地进行“等待”,这样一来,单片机的CPU就会在延时的同时,被100%占用,导致当延时函数执行时,单片机无法做其他的任何事情。显然,这对单片机CPU的资源是一个极大的浪费,特别是程序中有较长的延时需求时,更是如此。而定时计数器的出现,则能够很好的解决了这一问题。
当然,从蓝桥杯竞赛的角度来说,定时计数器的使用也是一个较重要的编程技能,聪明的使用定时计数器,能够让你的程序更加灵活,也更容易设计、编写和维护。
本节针对定时计数器,设计了两个练习题,题目要求如下:
题1、在数码管上显示字符8,利用定时器定时每1秒左移动一位
题2、数码管初始显示0,利用定时器定时每1秒数值加1
下面仍照惯例给出两个题目的代码,并在文末给出所有代码压缩包的下载链接,请大家自行下载哈~当然,本系列中所有的代码,均在相对应的开发板上验证通过,大家可以放心下载~
-----------------------蓝桥板代码---------------------
蓝桥板题1代码:
/*********************************************************************
1、在数码管上显示字符8,利用定时器定时每1秒左移动一位
**********************************************************************/
#include<stc15f2k60s2.h>
#include<intrins.h>
#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<stc15f2k60s2.h>
#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);
}----------------所有代码打包下载链接------------------
大家可以继续提前接着往下进行 08. DS18B20温度传感器进行数据采集和使用的题目练习~如对代码有任何问题,请在下方回帖留言呀。
曾子在文末曰:“每篇文章末尾都有鸡汤,好烦啊。今天就什么都不曰了,正儿八经一回吧,明天再接着曰。”

我要赚赏金
