Led方阵和串口通信COM

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图的问题,谢谢!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值