今天是第一个综合的代码,用到了LED、数码管、串口、定时器等模块
用到的程序主要有延时、初始化、流水灯、573的选择、单个数码管显示数据、时间显示、定时器的初始化和中断函数、串口初始化和中断函数、串口数据解析函数、独立按键
代码如下:
#include "reg52.h"
void Delay(); //普通延时函数
void DelaySMG(); //数码管延时函数
void SelectHC573(); //寄存器选择
void DisplaySMG_Bit(); //数码管显示指定数据
void DisplayTime()(); //时间显示
void InitTimer0(); //定时器初始化
void InitUart(); //串口初始化
void SendByte(); //单字节发送数据
void ExecuteCommand(); //数据解析函数
void ScanKeys(); //按键扫描
void check_LED(); //LED灯测试
void check_SMG(): //数码管测试
void InitSystem(); //系统初始化,关闭无关设备
sfr AUXR = 0x8e; //定义辅助寄存器
sbit S5 = P3^2; //定义按键S5引脚
sbit S4 = P3^3; //定义按键S4引脚
unsigned char count = 0; //定义50ms定时中断累计变量
unsigned char t_h = 0; //定义运行时间的时变量
unsigned char t_m = 0; //定义运行时间的分变量
unsigned char t_s = 0; //定义运行时间的秒变量
unsigned char command = 0; //定义串口命令字接收变量
unsigned char stat_led = 0xff; //定义LED灯当前开关状态
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//共阳数码管的段码编码表
/*==================普通的延时函数======================*/
void Delay(unsigned int t)
{
while(t--);
while(t--);
}
/*================数码管专用延时函数====================*/
void DelaySMG(unsigned int t)
{
while(t--);
}
/*=================锁存器选择函数======================*/
void SelectHC573(unsigned channel)
{
switch(channel)
{
case 4:P2 = (P2 & 0x1f) | 0x80; //Y4输出0,选择LED控制
break;
case 5:P2 = (P2 & 0x1f) | 0xa0; //Y5输出0,选择蜂鸣器和继电器控制
break;
case 6:P2 = (P2 & 0x1f) | 0xc0; //Y6输出0,选择数码管位选
break;
case 7:P2 = (P2 & 0x1f) | 0xe0; //Y7输出0,选择数码管段码
break;
case 0:P2 = (P2 & 0x1f) | 0x00; //所有锁存器不选择
break;
}
}
/*=================单个数码管显示函数====================*/
void DisplaySMG_Bit(unsigned char value, unsigned char pos)
{
P0 = 0xff; //消隐
SelectHC573(6);
P0 = 0x01 << pos; //数码管的段位
SelectHC573(7);
P0 = value; //数码管显示内容
}
/*===============系统运行时间显示函数===================*/
void DisplayTime()
{
DisplaySMG_Bit(SMG_NoDot[t_s%10],7); //秒个位
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_s/10],6); //秒十位
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],5); //分隔符
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m%10],4); //分个位
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m/10],3); //分十位
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],2); //分隔符
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_h%10],1); //时个位
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_h/10],0); //时十位
DelaySMG(500);
}
/*================定时器T0初始化函数====================*/
void InitTimer0()
{
TMOD = 0x21; //必须注意,T0和T1的工作模式一起赋值
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
ET0 = 1; //使能定时器T0
EA = 1; //使能总中断
TR0 = 1; //启动定时器T0
}
/*===============定时器T0中断服务函数===================*/
void ServiceTimer0() interrupt 1
{
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
count++;
if(count == 20)
{
count = 0;
t_s++;
}
if(t_s == 60)
{
t_s = 0;
t_m++;
if(t_m == 60)
{
t_m = 0;
t_h++;
}
}
}
/*=================串口初始化函数========================*/
void InitUart()
{
TMOD = 0x21; //必须注意,T0和T1的工作模式一起赋值
TH1 = 0xfd; //设置9600波特率的参数
TL1 = 0xfd;
TR1 = 1; //启动定时器T1
SCON = 0x50; //8位UART模式,允许接收
AUXR = 0x00; //辅助寄存器设置(89C82系列不需要)
ES = 1; //使能串口中断
EA = 1; //使能总中断
}
/*=================串口中断服务函数====================*/
void ServiceUart() interrupt 4
{
if(RI == 1)
{
command = SBUF; //将接收到的数据保存到command变量
RI = 0; //将接收完成标志RI清0
}
}
/*=================串口发送单字节函数====================*/
void SendByte(unsigned char dat)
{
SBUF = dat; //将数据放进SBUF缓冲器
while(TI == 0);
TI = 0;
}
/*===============上位机命令解析执行函数==================*/
void ExecuteCommand()
{
if(command != 0x00) //接收到一个上位机命令
{
switch(command & 0xf0) //将命令类型取出来
{
case 0xa0: //远程灯光控制命令
SelectHC573(4);
stat_led = (stat_led | 0x0f) & (~command | 0xf0);
//0x0f用二进制表示为00001111 0xf0用二进制表示为11110000,这种方式可以保证只改
变前四位而不影响后四位。遇到这种情况的写法:先让受控制的位为0,写出来十六进制;再让不受控制位
为0,写出来十六进制;先让变量本身和第一个数取反;再让给的命令和第二个数取反;最后相与
P0 = stat_led;
SelectHC573(0);
command = 0x00; //清零
break;
case 0xb0: //读取现场系统运行时间命令
SendByte((t_h / 10 << 4) | (t_h % 10));//BCD码所以要移4位
SendByte((t_m / 10 << 4) | (t_m % 10));
SendByte((t_s / 10 << 4) | (t_s % 10));
command = 0x00;
break;
}
}
}
/*=================独立按键扫描函数====================*/
void ScanKeys()
{
if(S5 == 0) //发现按键S5信号
{
DisplayTime(); //去抖动处理
if(S5 == 0) //确认按键S5信号
{
while(S5 == 0) //等待按键S5松开
{
DisplayTime();
}
SelectHC573(4);
stat_led = (stat_led | 0x40) & (~stat_led | 0xbf);
P0 = stat_led; //执行现场灯光控制
SelectHC573(0);
}
}
if(S4 == 0) //发现按键S4信号
{
DisplayTime(); //去抖动处理
if(S4 == 0) //确认按键S4信号
{
while(S4 == 0) //等待按键S4松开
{
DisplayTime();
}
SelectHC573(4);
stat_led = (stat_led | 0x80) & (~stat_led | 0x7f);
P0 = stat_led; //执行现场灯光控制
SelectHC573(0);
}
}
}
/*=================工厂灯光检测函数====================*/
void CheckLED()
{
char i;
SelectHC573(4);
for(i = 0; i < 9; i++)
{
stat_led = 0xfe << i; //逐个点亮LED灯
P0 = stat_led;
Delay(60000);
}
for(i = 0; i < 9; i++)
{
stat_led = ~(0xfe << i); //逐个熄灭LED灯
P0 = stat_led;
Delay(60000);
}
SelectHC573(0);
}
/*================时间显示模块检测函数==================*/
void CheckSMG()
{
unsigned char i;
SelectHC573(7);
P0 = 0x00;
for(i = 0; i < 9; i++)
{
SelectHC573(6);
P0 = ~(0xfe << i); //逐个点亮数码管
Delay(60000);
}
for(i = 0; i < 9; i++)
{
SelectHC573(6);
P0 = 0xfe << i; //逐个熄灭数码管
Delay(60000);
}
SelectHC573(0);
}
/*==================系统初始化函数======================*/
void InitSystem()
{
SelectHC573(5);
P0 = 0x00;
SelectHC573(4);
P0 = stat_led;
SelectHC573(0);
}
/*======================主函数===========================*/
void main()
{
InitSystem();
CheckLED();
CheckSMG();
InitTimer0();
InitUart();
while(1)
{
ExecuteCommand();
DisplayTime();
ScanKeys();
}
}
代码不是原创,是我综合几个博客整理的
想先看几个综合代码找找感觉,然后自己写几个省赛的题目,51就先放放了