今天学的东西挺多的,包括:自己设计的小应用,矩阵键盘,矩阵键盘密码锁,控制按键led流水灯,定时器时钟
(那个视频真的煎熬,连续两个1小时的简直要命,那个时钟也是听的似懂非懂....)
小应用
这个是朋友问我能不能用51单片机实现类似红绿灯的效果,我大体做了一下,到周末回顾的时候还会进行填充(每周末会先复习前面的知识,包括之前没有弄懂的地方,如果时间不够就不学新知识了,也会利用已经学过的知识尝试创建小的应用,巩固学过的知识)
#include <REGX52.H>
#include "Delay.h"
#include "Nixie.h"
//设置红绿灯的等待时间为45s,由于设备限制仅
//实现红灯部分
void main()
{
while(1)
{
unsigned int time=45;
P2_7=0;
while(time>=10)
{
int a,b;
a=time/10;
b=time%10;
Nixie(1, 0xFF);
Nixie(2, 0xFF);
Nixie(1,a);
Nixie(2,b);
time--;
Delay(1000);
}
while(time>=0)
{
Nixie(2,time);
time--;
if(time<=5)
{
P2_7=1;
Delay(500);
P2_7=0;
Delay(500);
}
}
}
}
没搞明白为什么数码管没有达到红绿灯那种常亮的效果,一直在闪....
矩阵键盘
矩阵键盘由于内部电路的设计是先列后行进行设置。
先对p1初始化,设置为0表示选中当前列,若是当前列的某一行的按键被按下,就显示这个数字。
在同一时刻只能选中一个按钮
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在子函数,松手瞬间,返回按键键码
没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF;
P1_3=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
P1=0xFF;
P1_2=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
P1=0xFF;
P1_1=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
P1=0xFF;
P1_0=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber;
}
矩阵键盘
这个是实现键盘对应键位显示对应的数字
如果不加if判断,会一直显示00,但实际上是显示了被按下的按键的数字的,只是在循环体里面进行的比较快,被刷新成了0,肉眼就看不出来了
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"MatrixKey");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
LCD_ShowNum(2,1,KeyNum,2);
}
}
}
矩阵键盘密码锁
这应该算是一个小项目了吧。
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Password,Count;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Password:");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10)//如果s1-s10按键按下,输入密码
{
if(Count<4)//如果输入次数小于4
{
Password*=10;//密码左移一位
Password+=KeyNum%10;//获取一位密码
Count++;//计次加一
}
LCD_ShowNum(2,1,Password,4);//更新显示
}
if(KeyNum==11)//如果s11按键按下,确认
{
if(Password==2345)//如果密码等于正确密码
{
LCD_ShowString(1,14,"OK ");
Password=0;//密码清零
Count=0;//计次清零
LCD_ShowNum(2,1,Password,4);//更新显示
}
else
{
LCD_ShowString(1,14,"ERR");
Password=0;//密码清零
Count=0;//计次清零
LCD_ShowNum(2,1,Password,4);//更新显示
}
}
if(KeyNum==12)//如果s12按键按下,回退(优化直接删除)
{
Password/=10;
Count--;
LCD_ShowNum(2,1,Password,4);//更新显示
}
}
}
}
时钟
时钟的内部实现还是比较复杂的,这个可能看视频听的比较迷糊,自己私下可以看使用手册的原理图帮助理解。
这个TMOD设值的方法挺巧的
计数器65535溢出,1次是一微妙,所以设置的初值是64535,使它每次清零是一毫秒
计数器一共八位,TH0是高位TL0是地位
#include <REGX52.H>
/**
* @brief 定时器0初始化
* @param
* @retval
*/
void Timer0Init()
{
//TMOD=0x01;//0000 0001
TMOD &= 0xF0;//把TMOD的低四位清零,高四位保持不变
TMOD |= 0x01;//把TMOD的最低为置一,高四位保持不变
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
PT0=0;
}
/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
}
}
*/
控制按键led流水灯
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>
unsigned char KeyNum,LEDMode;
void main()
{
P2=0x0FE;
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;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
if(LEDMode==0)
P2=_crol_(P2,1);
if(LEDMode==1)
P2=_cror_(P2,1);
}
}
定时器时钟
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"
unsigned char Sec=55,Min=59,Hour=23;
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;
TL0 = 0x18; //设置定时初值
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;
}
}
}
}
江协老师讲的东西都很细致,很明白,虽然时间很长,但是有着弹幕先辈的陪伴还是能坚持下来的