单片机定时器的 & 2.4g & 精准计时 & 串口通信
时间:2022-10-20 21:00:00
目录
- [电子定时闹钟程序](https://blog.csdn.net/weixin_46858768/article/details/115047895?spm=1001.2014.3001.5501)
- 任务一,点亮-熄灭LED灯
- 任务2显示静态数码管和动态数码管
-
- 1.上电后,数字管显示0 每次按下按钮。将数字添加到数字管中,直到 F ,然后循环
- 2.上电后,四个数字管显示0 数字管10进制显示每次按钮数字管数字加 ,加到9999,然后循环
- 任务三,精确计时器
-
- 2.按下按钮,开始计时,准确到10ms计算到60的显示s例如位显示,如1.25.8 表示1分25.8秒 以此类推,计算到26分钟30秒,显示为26分钟.30.毫秒进度不显示。计算一个小时 误差不大于2秒
- 任务4。串口通信
-
- 1.用电脑串口助手发送0xab,返回 0xac
- 2.两个单片机通信a单片机 按下按钮开始精准计时 按另一个按钮 a单片机停止计时,并将当前时间发送到B单片机 b单片机立即开始倒计时,0后使用LED灯亮
-
- 发送
- 接收
定时电子闹钟程序设计–》定时电子闹钟程序
任务一,点亮-熄灭LED灯
1.按下一个按钮 一个LED灯亮 按下另一个按钮进行更改LED灯灭
LED (Light Emitting Diode )发光二极管是半导体=一种极管, 将电能转化为光能。
LED和普通二极管一样,PN结构,具有单向导电性。只有当电源水平和LED正极相连,
电源负极与LED负极相连时,LED导通、发光;相反,LED不能导通,也不能发光。
了解LED如何工作 即书的12页开始
- 定义它的 P1 LED灯引脚 可以一起定义 :
LED = P1
也可以单独定义P1^0~P0^7
共八个灯 - 按钮 P3 引脚就是指 P3.4~P3^7 四个按钮分别对应
- 单片机用于实验低电平点亮的 也就是给 0 就可以点亮 如果给1 高电平时不亮
#include sbit led1 = P1^0; sbit k1 = P3^4;//按钮1 定义 k1 为按钮1 类推 sbit k2 = P3^5;//按钮2 sbit k3 = P3^6;//按钮3 sbit k4 = P3^7;//按钮4 void main() {
while(1){
led1 = 1; //开始灯灭 if(k1 == 0){
//按下k1 进入while 循环 灯亮 while(1){
led1 = 0; if(k2 == 0|| k3 == 0|| k4 == 0){
//按下 k-2-3-4 跳出while循环 灯灭 break;
}
}
}
}
}
##2.按下一个按钮,4个LED灯以1s间隔流水灯
- 定义一个按钮用来启动
- 因为单片机执行时的速度是人的肉眼所看不到的 所以要定义一个延时的工具(函数)来延时执行 可以保证可以看到效果
- 此处调用了内置的位移函数intrins.h
#include
#include
sbit k1 = P3^4;//按钮开始流水灯
void delay(int x)//延时1s函数
{
int i,j; //执行一段空语句来进行延时
for(i = x;i > 0;i--){
for(j = 112;j > 0;j--){
}
}
}
void main()
{
int i;
if(k1 == 0){
delay(2); //消抖
P1 = 0xfe;//只亮第一盏灯
for(i = 0;i < 4;i++){
delay(1000);//调用延时
P1 = _crol_(P1,1);//每次往左移动一位
}
}
}
任务二,静态数码管和动态数码管显示
1.上电后一个数码管显示0 每按一次按钮。数码管显示的数字加一,直到 F ,然后循环
LED 显示器静态显示简介
单片机系统中常用的显示器有发光二极管(Light Emitting Diode, LED)显示器、液晶(Liquid
Crystal Display, LCD)显示器、CRT显示器等。LED,LCD 显示器有2种显示结构,即段显示(7段、
了解LED的组成和其作用 即书上的47页
- 给每个数码管的 引脚定义再调用 分别是P2^4 -P2^7的引脚
- 数码管有一位和多位一体两类,它是由8个LED(a,b,c,d,e,f,g,dp)排列组成,任意一个LED叫作一个“段”。通过给a,b,c,d,e,f,g,dp各个脚加上不同的控制电压可以使不同的LED导通发亮,从而显示0~9各个数字和ABCDEF各个字母。
- 也可以定义一个 十六进制码来让单片机识别调用
#include
sbit k1 = P3^4;//定义按钮
sbit smg1 = P2^4; //四个LED灯的引脚
sbit smg2 = P2^5;
sbit smg3 = P2^6;
sbit smg4 = P2^7;
void delay(unsigned int s)//延时函数
{
unsigned int i,j;
for(i = s;i > 0;i--){
for(j = 112;j > 0;j--){
}
}
}
unsigned char code smgduan[16]= {
0x3f, 0x06, 0x5b, 0x4f,
0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c,
0x39, 0x5e, 0x79, 0x71}; //0~F 十六个十六进制码
void main()
{
int i = 0;
while(1){
if(k1 == 0)
{
while (k1 == 0 );
delay(5);//按钮消抖
i++; // 给数码管加一
}
delay(5);
P0 = smgduan[i];
smg1 = 0;//前面的三个LED等灭
smg2 = 0;
smg3 = 0;
smg4 = 1;//一个LED灯亮
delay(1);//延时才可以看到效果 不然肉眼看不清
if(i >= 15)//因是 16进制码 从0开始到了15 进一归0
{
i = 0;
}
}
}
2。上电后,四个数码管显示0 数码管一十进制显示每按一次按钮数码管数字加一 ,一直加到9999,然后循环
#include
sbit led1 = P2^4;//四个LED灯
sbit led2 = P2^5;
sbit led3 = P2^6;
sbit led4 = P2^7;
sbit k1 = P3^4;//按钮
sbit k2 = P3^5;
unsigned char code smg[16]= {
0x3f, 0x06, 0x5b, 0x4f,
0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c,
0x39, 0x5e, 0x79, 0x71}; //0~F??十六进制码
void delay(int x)//延时函数
{
int i,j;
for(i = x;i > 0;i--){
for(j = 11;j > 0;j--){
}
}
}
void main()
{
int i = 0,j = 0,k = 0,l = 0;
while(1){
P0 = smg[i];//个位LED
led4 = 1;
led3 = 0;
led2 = 0;
led1 = 0;
delay(1);
P0 = smg[j];//十位LED
led4 = 0;
led3 = 1;
led2 = 0;
led1 = 0;
delay(1);
P0 = smg[k];//百位LED
led4 = 0;
led3 = 0;
led2 = 1;
led1 = 0;
delay(1);
P0 = smg[l];//千位LED
led4 = 0;
led3 = 0;
led2 = 0;
led1 = 1;
delay(1);
delay(1);
if(k1 == 0){
while(k1 == 0);
delay(10);
i+=1;//每次加一
}
if(i >= 10) //i个位加到10 十位进位一 个位归0
{
i = 0;
j += 1;
}
if(j >= 10){
//j十位加到10 百位进位一 十位归0
j = 0;
k += 1;
}
if(k >= 10)//k百位加到10 千位进位一 百位归0
{
k = 0;
l += 1;
}
if(l >= 10)//l千位加到10 全归0
{
i = 0;
j = 0;
l = 0;
l = 0;
}
}
}
任务三,精准计时器
##1.按下按钮,开始计时,利用四个数码管显示。精确到10ms显示 ,计算到99秒后循环
EXO(E.0),外部中断0允许位。
ETO(IE.1),定时/计数器TO中断允许位。
EX1(IE2),外部中断0允许位。
ET1(IE.3),定时/计数器T1中断允许位。
ES(IE.4),串口中断允许位。
EA(IE.7), CPU中断允许(总允许)位。
了解单片机的中断系统和其IO分配引脚 即书上66页开始 下面表格时其中之一
控制寄存器TCON
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
功能 | TE1 | TR1 | TF0 | TR0 | … | … | … | … |
-
调用延时函数来进行计时的话 会消耗 cpu资源 从而执行起来会变慢,久了计时上也会出现延时不准确
-
所以需要调用中断系统,它不会消耗 cpu资源 从而达到精确计时
-
下面一个小案例
-
void Time() { TMOD = 0x01; //定时器选择工作方式 1 TH0 = 0x3c; //设置初始值 TL0 = 0x0b0; EA = 1; //打开总中断 ET0 = 1; //打开定时器 T0 中断 TR0 = 1;//启动定时器T0 }
#include
#define uc8 unsigned char
sbit k1 = P3^4;
sbit k2 = P3^5;
uc8 i,sh = 0,bh = 0,m = 0,sm = 0,k,j;
unsigned char code xianshi[]={
0x8f,0x4f,0x2f,0x1f};
//数码管各位的码表
unsigned char code meidian[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//数码管各位的码表(带上小点)
unsigned char code youdian[]={
0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
void delay(unsigned char jk)//延时函数
{
for(j=jk;j>0;j--)
for(k=112;k>0;k--);
}
void display1(uc8 wei,uc8 shu)//在任意一位显示任意的数字
{
wei=wei-1;
P2 |= 0xf0;//给P2.4-P2.7置1
if(wei == 2)
P0=youdian[shu];
else
P0=meidian[shu];
P2=P2&xianshi[wei];//给P2需要显示的那一位置1,其他置0
delay(3);
}
void display(unsigned char a,unsigned char b,unsigned char c,unsigned char d)
{
//一次显示4个数字,且每位显示数字可自定。
display1(4,a);
display1(3,b);
display1(2,c);
display1(1,d);
}
void start_timer()
{
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //打开定时器
}
void stop_timer()
{
ET0=0; //关定时器0中断
EA=0; //关总中断
TR0=0; //关闭定时器
}
void InitTimer0(void)//定时器的设定
{
TMOD = 0x01;
TH0 = 0x0Dd;
TL0 = 0x0F0;
}
void main()
{
InitTimer0();
while(1){
if(k1==0)//开始计时
{
delay(1);
if(k1==0)
{
start_timer();
}
}
if(k2 == 0){
//停止时间
delay(1);
stop_timer();
}
display(sm,m,bh,sh);
if(i == 1){
//个豪
sh++;
i = 0;
}
if(sh == 10){
//十豪
bh++;
sh = 0;
}
if(bh == 10){
//百豪
m++;
bh = 0;
}
if(m == 10){
sm++;
m = 0;
}
if(sm == 10){
//stop_timer();
sm = 0;
}
display(sm,m,bh,sh);//显示
}
}
void Timer0Interrupt(void) interrupt 1//定时器的中断
{
TH0 = 0x0Db;
TL0 = 0x0F0;
i++;
}
2.按下按钮,开始计时,精确到10ms显示,计算到60s后进位显示,例如1.25.8 表示1分25.8秒 以此类推,计算到26分钟30秒显示为26.30,此时毫秒进度不显示。计算一小时的时间 误差不大于2秒
- 用 if 来进行判断 到了条件就进一位显示
- 把开始计时和停止计时 分开封装
#include
#define uc8 unsigned char sbit k1 = P3^4;//两个k1 k2 按钮 sbit k2 = P3^5; sbit led1 = P2^4; sbit led2 = P2^5; sbit led3 = P2^6; sbit led4 = P2^7; uc8 i,sh = 0,bh = 0,m = 0,sm = 0,k,j,gf = 0,sf = 0,gs = 0,ss = 0,ph = 0;//全局定义 unsigned char code xianshi[]={ 0x8f,0x4f,0x2f,0x1f};//数码管各位的码表 unsigned char code meidian[]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管各位的码表(带上小点) unsigned char code youdian[]={ 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; void delay(unsigned char jk){ //延时函数 for(j=jk;j>0;j--) for(k=112;k>0;k--); } void display1(uc8 wei,uc8 shu)//在任意一位显示任意的数字 { wei=wei-1; P2 |= 0xf0;//给P2.4-P2.7置1 if(wei == 2) P0=youdian[shu]; else P0=meidian[shu]; P2=P2&xianshi[wei];//给P2需要显示的那一位置1,其他置0 delay(1); } void display(unsigned char a,unsigned char b,unsigned char c,unsigned char d){ //一次显示4个数字,且每位显示数字可自定。 display1(4,a); display1(3,b); display1(2,c); display1(1,d); } void start_timer(){ EA=