定时/计数器应用——从P1.0输出周期为1s的方波,让发光二极管以1Hz闪烁

利用定时/计数器T0从P1.0输出周期为1s的方波,让发光二极管以1Hz闪烁,设晶振频率为12MHz。

2021-01-20,51单片机学习笔记

代码(精简注释):
/*********************************************************
利用定时/计数器T0从P1.0输出周期为1s的方波,
让发光二极管以1HZ闪烁,设晶振频率为12MHz
**********************************************************/
#include <reg52.h>
unsigned char num;
sbit LED1=P1^0;

void main()
{
    
    
	num=0;//初始化计数变量
	EA=1;//打开特殊功能寄存器IE内的总开关EA
	ET0=1;//打开特殊功能寄存器IE内的开关ET0
	TMOD=0X01;//0000 0001
	//低四位,GATE=0,C/T=0,M1M0=01;选用中断源T0,方式1,16位定时器
	TH0=(65536-50000)/256;//初始化,装填初值
	TL0=(65536-50000)%256;
	TR0=1;//启动定时器
	
	while(1)
	{
    
    
		if(num==20)
		{
    
    
			num=0;//中断函数每执行20次,初始化计数变量
			LED1=~LED1;//取反
		}
	}//中断函数每执行20次,led1取反一次,20*50ms=1s,即led1以1s的间隔交替点亮熄灭
}

//中断函数 中断源:"定时/计数器0(T0)",代号1
void time0() interrupt 1 
{
    
    
	TH0=(65536-50000)/256;//初始化,装填初值60(8进制)
	TL0=(65536-50000)%256;//初始化,装填初值176(8进制)
	num++;//计数变量自增
	
	/*方式1是对每一个机器周期进行计数,直到计满后,溢出,申请中断
	这里是从15536(=65536-50000)位置开始计数,逐次加1,直到65535位置即将溢出,再加1,回到0
	共50000次"加1",机器周期为1us时,每次加1耗时1us,全程耗时50ms*/
}
代码(详细注释):
/*********************************************************
利用定时/计数器T0从P1.0输出周期为1s的方波,
让发光二极管以1HZ闪烁,设晶振频率为12MHz
**********************************************************/

#include <reg52.h>
unsigned char num;
sbit LED1=P1^0;

void main()
{
    
    
	num=0;//初始化计数变量
	EA=1;//打开特殊功能寄存器IE内的总开关EA
	ET0=1;//打开特殊功能寄存器IE内的开关ET0
	TMOD=0X01;//0000 0001
	/*
	TMOD是定时/计数器的工作方式寄存器,
		确定工作方式和功能。低四位用于T/C0,高四位用于T/C1。
		自左向右:
		高四位:[GATE|C/T|M1|M0]低四位:[GATE|C/T|M1|M0]
	
	((这里选择T/C0,使用低四位,所以高四位设置0))‘0000 xxxx’
	
	
	GATE:门控位。
		GATE=0时,只要使TCON中的TR0或TR1为1,就可以启动定时/计数器(T/C)
		工作。(其中:TR0对应T/C0;TR1对应T/C1)
		GATA=1时,要满足两个条件,才能启动定时/计数器(T/C)工作:
		1.使TR0或TR1为1。
		2.同时外部中断引脚INT0/1也为高电平时。
		(INT0对应T/C0;INT1对应T/C1)
	
	((这里选择GATE=0,TR0=1))‘0000 0xxx’
	
	
	C/T:定时/计数模式选择位。
		C/T=0为定时模式;C/T=1为计数模式。
		
	((这里选择C/T=0,定时模式))‘0000 00xx’
	
	
	M1M0:工作方式设置位。
		定时/计数器有四种工作方式,由M1M0进行设置。
		M1M0=00,方式0,13位定时器/计数器
		M1M0=01,方式1,16位定时器/计数器
		M1M0=10,方式2,8位自动重装定时器/计数器
		M1M0=11,方式3,T0分成两个独立的8位定时器/计数器,T1此方式停止计数
	
	((这里选择M1M0=01,方式1))‘0000 0001’
	*/
	
	TH0=(65536-50000)/256;//初始化,装填初值,装填初值60(8进制)
	TL0=(65536-50000)%256;//初始化,装填初值,装填初值176(8进制)
	/*方式1(M1M0=01),定时器(C/T=0)模式
	方式1的计数位数是16位,由TL0作为低8位,TH0作为高8位,组成了16位加1计数器
	16位寄存器可以装填的范围是0~65535,共65536个数
		65535(10)=1111 1111 1111 1111(2)=FFFF(16)=177777(8)
	16位定时器0装初值的计算公式:
	假设要计的个数是n,
	TH0=(65536-n)/256;//高8位=差对256(2的8次方)求商
	TL0=(65536-n)%256;//低8位=差对256(2的8次方)求余
	*/
	TR0=1;//启动定时器
	/*TR0(TCON.4)T/C0运行控制位
	TR0置1时,T/C0开始工作;TR0置0时,T/C0停止工作.TR0由软件置1或清0.
	所以,用软件可控制定时/计数器的启动与停止.
	*/
	while(1)
	{
    
    
		if(num==20)
		{
    
    
			num=0;//中断函数每执行20次,初始化计数变量
			LED1=~LED1;//取反
		}
	}//中断函数每执行20次,led1取反一次,20*50ms=1s,即led1以1s的间隔交替点亮熄灭
}

//中断函数 中断源:"定时/计数器0(T0)",代号1
/*5个中断源的代号分别是:
外部中断0(INT0)-->0
定时/计数器0(T0)-->1
外部中断1(INT1)-->2
定时/计数器1(T1)-->3
串行口-->4
它们的优先级从上到下由高到低递减*/
void time0() interrupt 1 
{
    
    
	TH0=(65536-50000)/256;//初始化,装填初值60(8进制)
	TL0=(65536-50000)%256;//初始化,装填初值176(8进制)
	num++;//计数变量自增
	/*((这里要装填的个数为50000))
		((fosc=12MHz,震荡周期=1/12um,机器周期=1us))
		((50000*1us=50ms,单次执行延时50ms))
		振荡周期:为单片机提供振荡源的周期(是指振荡源的两个相邻同方向峰值之间的时间)
		机器周期:1个机器周期等于12个振荡周期
	
	方式1是对每一个机器周期进行计数,直到计满后,溢出,申请中断
	这里是从15536(=65536-50000)位置开始计数,逐次加1,直到65535位置即将溢出,再加1,回到0
	共50000次"加1",机器周期为1us时,每次加1耗时1us,全程耗时50ms
	*/
}

写在最后:
本文仅为个人学习笔记,诸多纰漏,欢迎斧正!

猜你喜欢

转载自blog.csdn.net/qq_46541463/article/details/112886579