51计数器
以下是一个方波脉冲(波峰是1,高电位;波谷是0,低电位)
每来一个脉冲(波峰),计数器+1
程序的思路是:用延时函数令P10口反复改变电平状态,形成方波信号
准备工作:连接P10和P34引脚
计数器的配置
// 计数器0初始化
void counter0Init()
{
TR0 = 1; //启动计数器0
TMOD = 0x05; //计数器工作模式 M1=0;M0=1;
TH0 = 0;
TL0 = 0;
}
测试程序如下
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
sbit LED1 = P1^0;
uchar code table[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f} ; //code表示存在code区,数据不能被修改
void delay(unsigned int z)
{
unsigned int x, y;
for(x = z; x > 0; x--)
for(y = 114; y >0; y--);
}
void display(uchar i)
{
uchar bai, shi, ge;
bai = i / 100;
shi = i / 10 % 10;
ge = i % 10;
/*******************************************************/
P0 = 0xff; //清除断码
WE = 1; //打开位选
P0 = 0XFE; //1111 1110选择第一个数码管
WE = 0; //锁住位选数据
DU = 1; //打开段选
P0 = table[bai]; //显示百位
DU = 0; //锁住段选数据
delay(5);
/*******************************************************/
P0 = 0xff; //清除断码
WE = 1; //打开位选
P0 = 0XFD; //1111 1101选择第二个数码管
WE = 0; //锁住位选数据
DU = 1; //打开段选
P0 = table[shi]; //显示十位
DU = 0; //锁住段选数据
delay(5);
/*******************************************************/
P0 = 0xff; //清除断码
WE = 1; //打开位选
P0 = 0XFB; //1111 1011选择第三个数码管
WE = 0; //锁住位选数据
DU = 1; //打开段选
P0 = table[ge]; //显示个位
DU = 0; //锁住段选数据
delay(5);
}
// 计数器0初始化
void counter0Init()
{
TR0 = 1; //启动计数器0
TMOD = 0x05; //计数器工作模式 M1=0;M0=1;
TH0 = 0;
TL0 = 0;
}
void main()
{
delay(500);
LED1 = ~LED1;
display(TL0);
}
虽然已经能观察到现象,但是以上程序存在一个问题,使用delay函数会占用单片机运行资源,导致单片机没有办法“抽出时间”去处理数码管动态扫描。
程序改进
利用定时器1来产生脉冲方波
// 计数器0初始化
void counter0Init()
{
TR0 = 1; //启动计数器0
TMOD = 0x15; //计数器工作模式 M1=0;M0=1;
TH0 = 0;
TL0 = 0;
}
//定时器1初始化
void timer1Init()
{
TR1 = 1; //启动定时器1
TMOD = 0x15; //定时器1工作模式1,16位定时模式
TH1 = 0x4b;
TL1 = 0xfd; //定时50ms
}
void main()
{
uchar mSec; //毫秒
counter0Init(); //计数器0初始化
timer1Init(); //定时器1初始化
while(1)
{
if(TF1 == 1) //TF0==1即经过50ms
{
TF1 = 0; //软件清零溢出标志位
TH1 = 0x4b; //重放初值
TL1 = 0xfd;
mSec++; //50ms到
if(mSec == 10) //10个50ms到
{
mSec = 0;
LED1 = ~LED1; //产生方波脉冲
}
}
display(TL0);
}
}
网友评论