51单片机实验 LED流水灯 定时器0方式1 中断实现
实验目的:
P1口接8个发光管,实现0.5秒依次闪烁,从上到下,再从下到上,
要求使用定时器0工作方式1,中断实现。
#include <at89x52.h>
code unsigned char out[14]={0x01,0x02,0x04,0x08,
0x10,0x20,0x40,0x80,
0x40,0x20,0x10,0x08,
0x04,0x02};
void Timer0_init(void)
{
TMOD &=~0x0f;
TMOD |=0x01;
TH0=(65536-50000)/256; //定时50毫秒
TL0=(65526-50000)%256;
ET0=1;
TR0=1;
}
void Timer0_ISR(void) interrupt 1
{
static unsigned char intcnt=0,idx=0;
TH0=(65536-50000)/256;
TL0=(65526-50000)%256;//重赋值
if(++intcnt == 10){//10次累计,50ms*10=0.5s
intcnt=0;
P1=out[idx++];
if(idx==14) idx=0;
}
}
void main(void)
{
Timer0_init();
EA=1;
//ET0=1;
while(1){
;
}
}
仿真结果:
从上到下,再从下到上依次闪烁
定义数组实现对整个P1口8个引脚进行控制,数组里的数为16进制,例如0x80为二进制的 1000 0000 ,即P1.7口为高电平,此时该引脚上的LED灯亮。
至于方式一的初值赋值,与上篇方式2赋值一般无二不再赘述,只是要注意方式1为16位计数器,特点是计数溢出后,计数器全为0,因此在循环定时或循环计数时就存在用指令反复装入初值的问题,有些影响定时精度。
总结:
对P1口引脚的电平控制有了新理解,初始是用很多if语句控制LED,代码冗余且效果不是很理想,常规上普遍采用移位控制,的确,由于自己一开始是在上一次实验的代码上修改,自己陷入井底思维了,只关注这一个一个引脚,没想过整个P1口,对整个口进行电平控制,采用数组遍历,十六进制赋值,代码简洁而高效 。
也可以采用左右移位控制,但是要注意溢出后重赋值,不然就没有灯会亮了。(溢出后为0000 0000,此时应对P1口视情况重赋值,例如0X01)