51单片机的计数器的工作原理
目录
51单片机的计数器的工作原理
如图所示,导入元器件并连线。
编写c程序并生成hex文件。
#include"reg52.h"
char duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned int num=0;
void initcounter(){
TMOD = 0x06; // 0000 0110
TH0=256-3; // 赋初值 计数3次
TL0=256-3; // 赋初值 计数3次
ET0 = 1; // 开启计时器0
EA = 1; // 打开总中断
TR0 = 1; // 开启计数器0
}
void display(){
P2=duan[num];
}
void main(){
initcounter();
while(1){
display();
}
}
void zhongduan() interrupt 1{ // 中断函数, 只要前面的计数器产生了中断,程序就会往这个函数里面走
num++;
if(num==10){
num=0;
}
}
最后导入proteus中,按 按键3次实线数码管加1的效果。
下面写一段计数器1触发的代码:
#include<reg52.h>
char duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
int num=0;
void init()
{
TMOD=0x60; //用计数器0的值: 0000 0110
TH1=256-3; // 用计数器0的值: TH0
TL1=256-3; // 用计数器0的值: TL0
ET1=1; // 用计数器0的值: ET0
TR1=1; // 用计数器0的值: TR0
EA=1;
}
void display()
{
P2=duan[num];
}
int main()
{
init();
while(1)
{
display();
}
}
void zhongduan()interrupt 3
{
num++;
if(num==10)
{
num=0;
}
}
用上面的程序把button接到P3.5/T1接口上也能实现按3次button数码管加1.
下面是最近看到的内容,感觉挺有用就记录下来吧!
为此写了一个小程序来验证学习到的知识是否正确。主要功能就是控制P0的第0口的小灯间隔1秒亮灭,来看程序,这是使用16位计时器0的例子:
#include<reg52.h>
sbit LED = P0^0;
unsigned int count = 0;
void InitTime()
{
TMOD = 0x01;
TH0 = 0xB4;
TL0 = 0x00;
TR0 = 1;
}
int main()
{
InitTime();
while(1)
{
if(1 == TF0)
{
TF0 = 0; // 将硬件置1的溢出标志位置0,重新计时
TH0 = 0xB4;
TL0 = 0x00;
count++;
if(40 == count)
{
count = 0;
LED = ~LED;
}
}
}
return 0;
}
下面是使用16位计时器1的例子
#include<reg52.h>
sbit LED = P0^0;
unsigned int count = 0;
void InitTime()
{
TMOD = 0x10; // 设置使用计时器1的工作模式1
TH1 = 0xB4;
TL1 = 0x00;
TR1 = 1;
}
int main()
{
InitTime();
while(1)
{
if(1 == TF1)
{
TF1 = 0; // 将硬件置1的溢出标志位置0,重新计时
TH1 = 0xB4;
TL1 = 0x00;
count++;
if(20 == count)
{
count = 0;
LED = ~LED;
}
}
}
return 0;
}
下面是使用16位计数器0和1,8位计数器0和1的例子,13位计数器只有计数1次能 成功,不知道原因。放开注释就能测试。
#include<reg52.h>
#define uc unsigned char
uc s[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uc num=0;
void init_count();
void display();
void main()
{
init_count();
while(1)
{
display();
}
}
void display()
{
P2=s[num];
}
//下面这是配置的16位计数器0的方法
//void init_count()
//{
// TMOD=0x05; //和定时器0的使用方法是一样的,只不过这里把C/T位置1了而已。
// TH0=(65536-3)/256;
// TL0=(65536-3)%256;
// TR0=1;
// ET0=1;
// EA=1;
//}
//void count_isr()interrupt 1
//{
// TH0=(65536-3)/256;
// TL0=(65536-3)%256;
// num++;
// if(num==10) num=0;
//}
// 下面这是配置的16位计数器1的方法
//void init_count()
//{
// TMOD=0x50; //和定时器0的使用方法是一样的,只不过这里把C/T位置1了而已。
// TH1=(65536-3)/256;
// TL1=(65536-3)%256;
// TR1=1;
// ET1=1;
// EA=1;
//}
//void count_isr()interrupt 3
//{
// TH1=(65536-3)/256;
// TL1=(65536-3)%256;
// num++;
// if(num==10) num=0;
//}
下面这个是配置的8位计数器0的方法
//void init_count()
//{
// TMOD=0x06; //和定时器0的使用方法是一样的,只不过这里把C/T位置1了而已。
// TH0=256-3; //这里赋值不用除是因为8位的数据可以放下,除是为了取高8位。
// TL0=256-3; //这里赋值不用取余是因为8位的数据可以放下,取余是为了取低8位。
// TR0=1;
// ET0=1;
// EA=1;
//}
//void count_isr()interrupt 1
//{ // 8位计数计时器能自动重载,所以不用赋初值
// num++;
// if(num==10) num=0;
//}
下面这个是配置的8位计数器1的方法
//void init_count()
//{
// TMOD=0x60; //和定时器0的使用方法是一样的,只不过这里把C/T位置1了而已。
// TH1=256-3; //这里赋值不用除是因为8位的数据可以放下,除是为了取高8位。
// TL1=256-3; //这里赋值不用取余是因为8位的数据可以放下,取余是为了取低8位。
// TR1=1;
// ET1=1;
// EA=1;
//}
//void count_isr()interrupt 3
//{ // 8位计数计时器能自动重载,所以不用赋初值
// num++;
// if(num==10) num=0;
//}