单片机定时器与数码管静态显示

很多新手在单片机上走的第一步是点亮第一个led灯,实际上因为开发板的不同,所编写的代码也不同,关键是你要去了解你用的开发板的电路布局。对于电路方面的知识我这里也不详讲,我要做的是无论你用哪一种开发板我的文章都能帮助你。
p0 = 0xfe;
这句代码大家不陌生。
void main(){
unsigned char count = 0;
while(1){
p0 = ~(0x01 < =8){
count = 0;
}
}
}
以上就是实现流水灯的基本代码,这里没有电路供你分析,但是无论什么开发板,核心代码可以用以上代码实现。
我相信你能看到这里也是有点基础的,这里的延时函数delay,接下来要讲的是定时器,定时器就是可以替代延时函数的。
定时器
标准的51单片机内部有t0和t1两个定时器,实际上就是tcon特殊功能的寄存器来控制这两个定时器的。
除此之外,定时值存储寄存器有th和tl,给tl赋值后,tl会自动加1,加到255后th加1,有趣的th也可以提前赋值,但这只是定时器工作的一种模式,定时器有四种模式,这里我不祥讲,而且我们几乎用的模式就是这种,后面涉及到会详细讲解。这里只需要知道tcon(地址0x88)位分配,以后会经常用到。
还有一个tmoc就是定时器作用的模式,位分配如下图:
代码:
void main()
{ th0 = 0xb8; //给th0赋值,后面的0代表是给定时器t0的th赋值
tl0 = 0x00;
tr0 = 1;//启动t0定时器
if(tf0 == 1) //判断t0是否溢出,tf是个标志位
{ //重置
th0 = 0xb8;
tl0 = 0x00; } }
以上就是定时器,时间多少呢?
我们以晶振位11.0592为例,时钟周期是1/11059200,机器周期(1ms)12/11059200,如果我们定时20ms,那个要执行20*(12/110592)次,算出来是18432次,换成十六进制是b800,所以对th0赋值b8,对tl0赋值00;
数码管
#include
sbit addr0 = p1^0;
sbit addr1 = p1^1;
sbit addr2 = p1^2;
sbit addr3 = p1^3;
sbit enled = p1^4;
void main() {
addr2 = 1;
addr1 = 0;
addr0 = 1;
addr3 = 1;
enled = 0;
p0 = 0xf8;
while(1);}
上面代码是用位stc-51开发板写的,在最后一个数码管上显示数字7,数码管难度简单,只需要针对数码管等的排布编程即可。
下面我们用关键字code定义数码管所能够显示所有字符的数组,这里再结合定时器一起。
#include sbit addr0 = p1^0;sbit addr1 = p1^1;sbit addr2 = p1^2;sbit addr3 = p1^3;sbit enled = p1^4;
//数组
unsigned char code led[] =
{ 0xc0, 0xf9, 0xa4,
0xb0, 0x99, 0x92,
0x82, 0xf8, 0x80,
0x90, 0x88, 0x83,
0xc6, 0xa1, 0x86,0x8e};
void main() { unsigned char count = 0;
//记录t0中断次数
unsigned char secnt = 0;
//记录经过的秒数
addr2 = 1;
addr1 = 0;
addr0 = 0;
addr3 = 1;
enled = 0;
//设置t0模式
tmod = 0x01;
//为t0的th0,tl0初始化
th0 = 0xb8;
tl0 = 0x00;
//启动t0 tr0 = 1;
while(1){
if(tf0 ==1)
{ th0 = 0xb8;
tl0 = 0x00;
count++;
tf0 = 0; }
if(count >=50)
{ count = 0;
p0 = led[secnt];
secnt++;
if(secnt>=16)
{ secnt = 0; } } }}
这里代码比较紧凑,不过不影响。上面的代码我相信你也能懂,但是你能发现定时器在这里起到了一个定时中断的作用。
这里讲一下中断。
中断
下面是中断ie寄存器位分配图:
直接上代码:
#include
//数码管显示字符真值数组
unsigned char code ledchar[]=
{0xc0, 0xf9, 0xa4, 0xb0, 0x99,
0x92, 0x82, 0xf8, 0x80, 0x90,
0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e };
//数码管显示区数组
unsigned char ledbuff[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
sbit addr0 = p1^0;sbit addr1 = p1^1;sbit addr2 = p1^2;sbit addr3 = p1^3;sbit enled = p1^4;
unsigned char i = 0;
//动态扫描索引
unsigned int c = 0;
//记录中断次数
void main() {
unsigned long s = 0;
//记录秒数
//使能u3
addr3 = 1;
enled = 0;
//设置t0模式
tmod = 0x01;
//初始化th0,tl0
th0 = 0xfc; tl0 = 0x66;
//启动tr0
tr0 = 1;
//使能总中断
ea = 1;
//使能t0中断
et0 = 1;
//主循环
while(1) { //1s中断 if(c>=1000) { s++; c=0; //为数码管显示区赋值 ledbuff[0] = ledchar[s%10]; ledbuff[1] = ledchar[s/10%10]; ledbuff[2] = ledchar[s/100%10]; ledbuff[3] = ledchar[s/1000%10]; ledbuff[4] = ledchar[s/10000%10]; ledbuff[5] = ledchar[s/100000%10]; } }}
//定时器t0中断服务void interrupttimer0() interrupt 1{ //重新赋值 th0 = 0xfc; tl0 = 0x66; c++; //显示消隐 p0 = 0xfe; //完成数码管动态扫描 switch(i) { case 0: addr2 = 1;addr1 = 0; addr0 = 1; i++; p0 = ledbuff[0]; break;
case 1: addr2 = 1;addr1 = 0; addr0 = 0;i++; p0 = ledbuff[1]; break;
case 2: addr2 = 0;addr1 = 1; addr0 = 1;i++; p0 = ledbuff[2]; break;
case 3: addr2 = 0;addr1 = 1; addr0 = 0; i++; p0 = ledbuff[3]; break;
case 4: addr2 = 0; addr1 = 0; addr0 = 1;i++; p0 = ledbuff[4]; break;
case 5: addr2 = 0;addr1 = 0; addr0 = 0;i=0; p0 = ledbuff[5]; break; default:break;
}
}
这组代码能够按照我们计算好的时间为单位显示秒数。
我们能够提出中断核心代码
ea = 1//中断总开关
et0 = 1//确认使用t0定时器中断开关
tr0 = 1//肯定要启动t0定时器
void interrupttimer0() interrupt 1//定时器t0中断服务,中断代码写在这里面,至于interrupt 1是因为interrupt会去寻找地址' 1 ',而t0定时器中断的地址就是1,所以我们可以直接在此函数中写中断期间的代码。至于各种中断的地址我也不再这里多写了。值得一谈的是ip——中断优先级寄存器位分配
各级中断都差不多,中断发生的也很多,当同时有许多中断发生时,可以通过置上面的值为1升级成优先级中断。

中兴通讯5G+云网融合综合解决方案助力抗疫一线,推进应用在海外落地
【虹科应用】虹科DASYLab在齿轮箱测试台的测量和控制系统中的应用
基于TM320F2812数字信号处理器实现多组分气体分析平台的构建
请问如何去使用钳形接地电阻表?
魅族Flyme6:11.30全球首发!更加强悍,更加智能!得天独厚更懂你
单片机定时器与数码管静态显示
人工智能在深圳正式启幕 天数智获得“AI+芯片最佳未来成长奖”
沙地英国银行计划“沙特2030年愿景”将区块链用于政府服务和相关交易
常用的电平转换方案分享
导热结构胶点胶问题的解决方案
电网广域监测系统的特点优势及在电力系统中的应用分析
几种常用的嵌入式Linux GUI及其特点
瑞萨电子发布R8C/Lx系列8位微控制器
基于嵌入式低功耗芯片和PC104总线实现铁路道口报警系统的设计
电源滤波电容的容量越大就越好吗?
新转换器架构在50kHz都不用磁芯,不是50MHz
智能电网的发展方向和挑战
三星S8评测:进步最大的智能手机 售价超5千成本高达2117
日本家用美容仪多次获奖,斩获少女肌的美容仪哪家强?
将区块链引入医疗系统给患者带来极大便利