前言
今天由于处理一些问题花了较长的时间,所以今天的博客更新比较晚,今天学习了51单片机的定时器功能,并依据这个功能做了两个小小项目,一个是独立按键控制流水灯的的方向,一个是简易的计时器,接下来那我们记录一下今天的学习内容吧。
定时器介绍以及基本知识
简介:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成作用:1.用于及时系统,可以实现软件及时,或者让程序每隔一段时间进行一项操作;2.替代长时间的Delay,提高CPU的运行效率和处理速度等等。其实也有大佬将定时器有很好的总结,下面我贴上链接
51单片机定时器-CSDN博客文章浏览阅读5.6k次,点赞25次,收藏112次。下面来介绍学习51单片机第一个也是最常用的片上外设——定时器。该硬件是集成在单片机内部的,与板上外设不同的是,它不会受到外界的干扰,只会听从cpu的命令。在小编看来,51单片机上的外设虽没有stm32的复杂,但配置起来要比stm32难,stm32配置片上外设只需要调用函数库输入指定的参数即可,相比于51单片机来的更方便,而51单片机则更底层些,需要从配置寄存器开始,设置初值等等一步一步地打通通道。*ps:学习基础外设部分一定一定要学会查资料!_51单片机定时器https://blog.csdn.net/weixin_69561921/article/details/130030119?spm=1001.2014.3001.5502这篇文章将其工作原理有很棒的总结,但是我得纠正一些东西:普中科技的板子的晶振是11.0592MHz,配置代码有错误,其代码会有一定误差,11.0592MHz的配置代码如下:
#include <REGX52.H>
void Timer0Init(void) //1毫秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
PT0=0;
}
/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;//保证在退出函数的时候不丢失其原本数值
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
P2_0=~P2_0;
}
}
*/
,注释里面是中断函数模板,T0count是时间,可以按需求修改,在if语句里面按需修改,其余代码可以由STC-ISP软件生成但是后面得配置通道。
独立按键控制流水灯
独立按键使用的是K1,每一次按下K1将会变换流水灯的流水方向,是实现思路是先判断是否按下K1然后再在中断函数中实现流水灯的流动,其可以有头文件intrins.h中的_crol_()和cror_()快速实现,一个是循环左移,一个是循环右移。判断K1的时候模块化了独立按键按下的代码,以下是实现代码:
main函数:
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <intrins.h>
unsigned char KeyNum, LEDMode;
void main()
{
P2 = 0xFE;
Timer0Init();
while (1)
{
KeyNum = Key();
if (KeyNum)
{
if (KeyNum == 1)
{
LEDMode++;
if (LEDMode >= 2)
{
LEDMode = 0;
}
}
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count; // 使用static的原因就是在函数退出后能够保存之前的值
TL0 = 0x66; // 设置定时初值
TH0 = 0xFC; // 设置定时初值
T0Count++;
if (T0Count >= 500)
{
T0Count = 0;
if (LEDMode == 0)
{
P2 = _crol_(P2, 1); // 循环左移
}
else if (LEDMode == 1)
{
P2 = _cror_(P2, 1); // 循环右移
}
}
}
独立按键的头文件以及c文件
#include <REGX52.H>
#include "Delay.h"
//获取独立按键建码 返回按键的按键
unsigned char Key()
{
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();
#endif
这个只要之前掌握的知识牢固,实现起来还是很容易的。
简易的计时器
其实现的是一个计秒的计时器,最大可以实现23:59:59,主要是通过定时器来实现的,其中的逻辑实现相对容易,用几个if判断后就可以实现,只需要特别注意一下LCD1602的显示即可其实现代码如下,其余头文件可以访问我之前写的博客
#include <REGX52.H>
#include "Timer0.h"
#include <intrins.h>
#include "LCD1602.h"
unsigned char Sec,Min,Hour;
void main()
{
LCD_Init();
Timer0Init();
LCD_ShowString(1,1,"Clock:");
LCD_ShowString(2,1," : : ");
while (1)
{
LCD_ShowNum(2,1,Hour,2);
LCD_ShowNum(2,4,Min,2);
LCD_ShowNum(2,7,Sec,2);
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count; // 使用static的原因就是在函数退出后能够保存之前的值
TL0 = 0x66; // 设置定时初值
TH0 = 0xFC; // 设置定时初值
T0Count++;
if (T0Count >= 1000)
{
T0Count = 0;
Sec++;
if(Sec>=60)
{
Sec=0;
Min++;
if(Min>=60)
{
Min=0;
Hour++;
if(Hour>=24)
{
Hour=0;
}
}
}
}
}
问题:
1.今天的知识感觉好理论,特别是在讲解定时器的理论知识的时候,感觉有点难,后面肯定还需要花时间去深度学习一下
2.今天花了好长一段时间去解决初始化LCD后再初始化定时器之后LCD1602显示出的问题,最终结果发现,造成这样的原因是在新键文件的时候选错了芯片。