Led方阵和串口通信COM
Author:Luis
Time:2022—04-05
Version:v1.0
功能
Led88点阵2的双色控制、亮度控制、串口通信控制 1、S11 全亮;S15 全暗;S19 一个暗一个亮; S10 增加亮度;S14 减少亮度;S18 展示字; 2、串口通信,点亮灯和第几行第几列的灯。
环境
Keil和Protues联动调试仿真。
代码
Keil
#include <regx51.h>
// 按键
#define KEY P3
#define key_state_0 0 //判断按键是否按下
#define key_state_1 1 //判断按键是否抖动
#define key_state_2 2 //判断按键是否弹起
unsigned char key_flag = 0; // 按键标志位
// led显示
unsigned int wei[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; //扫描8位
unsigned int duan[8] = {0x00, 0x08, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00};
unsigned int hex_oct1[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
unsigned int hex_oct2[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
// 延时n毫秒
void delay_ms(unsigned int n)
{
unsigned int i = 0, j = 0;
for (i = 0; i < n; i++)
for (j = 0; j < 123; j++)
;
}
// 读取按键
char read_key(void)
{
static char key_state = 0;
unsigned char key_return, key_press;
unsigned char key1, key2;
KEY = 0xf0;
key1 = KEY & 0xf0;
KEY = 0x0f;
key2 = KEY & 0x0f;
key_press = key1 | key2;
switch (key_state)
{
case key_state_0:
if (key_press != 0xff)
key_state = key_state_1;
break;
case key_state_1:
if (key_press != 0xff)
{
if (key_press == 0xbe)
key_return = 1; // s11
if (key_press == 0xde)
key_return = 2; // s15
if (key_press == 0xee)
key_return = 3; // s19
if (key_press == 0xbd)
key_return = 4; // s10
if (key_press == 0xdd)
key_return = 5; // s14
if (key_press == 0xed)
key_return = 6; // s18
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press == 0xff)
{
key_state = key_state_0;
}
break;
}
return key_return;
}
// 引脚初始化和定时器初始化
void init()
{
// 使能三个锁存器
P2 = 0x07;
P0 = 0x00;
TMOD |= 0x01;
TH0 = 0x50; //计数起点为56320 ==10ms溢出一次
TL0 = 0xFB;
TR0 = 1;
EA = 1; //启动中断系统
EX0 = 0; //-->IE0
ET0 = 1; //-->TF0 控制位置1,表明当TF0置1时,中断系统将介入
EX1 = 0; //-->IE1
ET1 = 0; //-->TF1
ES = 0; //-->RI,TI
}
void led_init()
{
P2 = 0x07;
P0 = 0x00;
}
// 串口通讯初始化
void Serial_comInit()
{
SCON = 0x50; //配置SM0/1,并允许接收
PCON = 0x00;
TMOD = 0x20; // 设置定时器1 为方式2
TH1 = 0xfd; //装入初值 对应波特率9600
TL1 = 0xfd;
TR1 = 1; //启动定时器1
EA = 1; // 打开总中断开关
ES = 1; // 打开串口中断开关
}
// 主程序
void main()
{
unsigned char temp = 0; // 按键
unsigned char led_change = 0; // led的哪个亮
unsigned char led_light_flag = 0; // 是否调节
unsigned int led_light = 50; // 亮度
unsigned int i = 0, j = 0;
// 初始化
init();
led_init();
Serial_comInit();
P1 = 0x00;
// 主循环
while (1)
{
if (key_flag == 1)
{
key_flag = 0;
temp = read_key();
if (temp != 0xff)
{
// 功能选择
switch (temp)
{
// S11
case 1:
led_light_flag = 0;
P2 = 0x06;
P0 = 0xFF;
break;
// S15
case 2:
led_light_flag = 0;
P2 = 0x06;
P0 = 0x00;
break;
// S19
case 3:
led_light_flag = 0;
if (led_change == 0)
{
led_change = 1;
// 黄灯亮 蓝灯灭
P2 = 0x02;
P0 = 0xFF;
P2 = 0x04;
P0 = 0x00;
}
else if (led_change == 1)
{
led_change = 0;
// 黄灯灭 蓝灯亮
P2 = 0x02;
P0 = 0x00;
P2 = 0x04;
P0 = 0xFF;
}
break;
// S10
case 4:
P2 = 0x02;
P0 = 0xff;
led_light_flag = 1;
led_light += 5;
if (led_light >= 50)
led_light = 50;
break;
// S14
case 5:
P2 = 0x02;
P0 = 0xff;
led_light_flag = 1;
led_light -= 5;
if (led_light <= 0)
led_light = 0;
break;
// S18
case 6:
// 展示字
for (i = 0; i < 100; i++)
{
for (j = 0; j < 8; j++)
{
P2 = 0x01;
P0 = wei[j];
P2 = 0x02;
P0 = duan[j];
delay_ms(40);
}
}
break;
}
}
}
// 亮度 PWM
if (led_light_flag == 1)
{
P2 = 0x04;
P0 = 0xFF;
delay_ms(led_light);
P2 = 0x04;
P0 = 0x00;
delay_ms(50 - led_light);
}
// P2 = 0x01;
// P0 = 0x00;
// P2 = 0x02;
// P0 = 0x08;
// delay_ms(1000);
}
}
// 定时器
void TF0_isr() interrupt 1 // 10ms 进入一次
{
static unsigned char key_time = 0;
TH0 = 0x50; // 清0
TL0 = 0xFB;
if (key_time += 100)
{
key_time = 0;
key_flag = 1;
}
}
// 串口通讯
void chuankou() interrupt 4
{
unsigned char number;
unsigned char number_l, number_h;
RI = 0;
number = SBUF;
switch (number)
{
// 点亮LED
case 0x5a:
P1 = 0xFF;
break;
// 关闭LED
case 0xa5:
P1 = 0x00;
break;
// 11-88,点亮第几行第几列的灯
default:
number_l = number & 0x0f;
number_h = (number & 0xf0) >> 4; // 高4位和低4位
led_init();
P2 = 0x02;
P0 = hex_oct1[number_l - 1];
P2 = 0x01;
P0 = hex_oct2[number_h - 1];
break;
}
SBUF = number; //将接收到的数据放入到发送寄存器
while (!TI)
; //等待发送数据完成
TI = 0; //清除发送完成标志位
}
Proteus
主板AT89C52
存器74HC573
按键
Led方阵
串口通信COMPIM
注意点
1、串口通信RXD和TXD不能接反,MAX
2、Led的mode style设置为digital,要接电阻,不然Led灯不亮
3、为了页面整洁,Wire Label Mode(LBL)设置元件的Label
4、Proteus调试Keil的代码,双击主板,调整Program File。
5、读取数据8位的高位和低位: number_l = number & 0x0f; number_h = (number & 0xf0) >> 4; // 高4位和低4位
未解决的问题
1、单独测试Led方阵和串口通信都可以,但是,结合起来,led会变暗,猜测是interrupt 1和interrupt 4产生了冲突。
2、本人写的代码S19的功能是点击一下,换一个灯亮,黄灯和蓝灯交错亮,但是调试的结果是不需要手动点击,就交错亮。
3、串口(Proteus的COM3)只能读取PC机的COM4的数据,但是COM3不能传输数据到COM4中,尝试加了MAX232模块,但是出现黄色电平且无法运行成功。(黄色电平:逻辑冲突。。等原因)
如果有大佬在评论区,望能指出代码orProteus图的问题,谢谢!!!
|