司败的man 2024-05-22 01:01 采纳率: 66.7%
浏览 73

51单片机串口通信lcd显示?

我利用普中 51 开发版和 lcd 1602 想完成通过虚拟助手发送数据 lcd 屏幕显示的功能,并且收到新的数据后,先清屏再显示新的,我的代码改过几次,有时显示不了,有时显示的最后出现四条横杠一样的东西,有的时候只能显示传输的前两个数字,有没有哥们能指点以下问题所在
以下是我的代码

#include "reg52.h"
#include "lcd1602.h"

#define DATA_LCD_SIZE 32 // 增加数组大小以存储更多数据
u8 data_lcd[DATA_LCD_SIZE] = {0}; // 初始化数组
volatile u8 data_received = 0; // 接收到的数据
volatile u8 data_index = 0; // 数组索引
volatile u8 new_data_flag = 0; // 新数据标志

/*******************************************************************************
* 函 数 名       : uart_init
* 函数功能       : 串口通信中断配置函数
* 输    入       : baud:波特率对应的TH、TL装载值
* 输    出        : 无
*******************************************************************************/
void uart_init(u8 baud)
{
    TMOD |= 0X20;  // 设置计数器工作方式2
    SCON = 0X50;   // 设置为工作方式1
    PCON = 0X80;   // 波特率加倍
    TH1 = baud;    // 计数器初始值设置
    TL1 = baud;
    ES = 1;        // 打开接收中断
    EA = 1;        // 打开总中断
    TR1 = 1;       // 打开计数器
}

/*******************************************************************************
* 函 数 名       : main
* 函数功能       : 主函数
* 输    入       : 无
* 输    出        : 无
*******************************************************************************/
void main()
{
    uart_init(0XFA); // 波特率为9600
    lcd1602_init();  // 初始化LCD1602

    while(1)
    {
        if(new_data_flag) // 如果有新数据标志
        {
            lcd1602_clear(); // 清除LCD
            data_lcd[data_index] = '\0'; // 在字符串末尾添加空字符
            lcd1602_show_string(0, 0, data_lcd); // 显示数据
            new_data_flag = 0; // 清除新数据标志
        }
    }
}

void uart() interrupt 4 // 串口通信中断函数
{
    u8 rec_data;

    RI = 0; // 清除接收中断标志位
    rec_data = SBUF; // 读取接收到的数据

    if(data_index < (DATA_LCD_SIZE - 1)) // 如果数组未满
    {
        data_lcd[data_index] = rec_data; // 存储接收到的数据
        data_index++; // 移动到下一个位置
        new_data_flag = 1; // 设置新数据标志
    }
    else
    {
        // 数组已满,这里可以添加处理逻辑,例如滚动显示或清空数组
        data_index = 0; // 重置索引
        new_data_flag = 1; // 设置新数据标志
    }
}


显示函数是这样定义的
lcd1602_show_string(u8 x, u8 y,u8 *ptr)
x:第几排
y:0为第一行,1为第二行

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2024-05-22 01:01
    关注

    上午好☀️☀️☀️️
    本答案参考ChatGPT-3.5

    根据问题分析,可能存在以下问题:

    1. 数据存储区域 (data_lcd) 是否足够存储所有数据。

    2. 数据存储索引 (data_index) 是否超出存储区域 (data_lcd) 界限。

    3. 数据显示函数 (lcd1602_show_string) 参数传递或调用方式是否正确。

    4. LCD 显示时是否清屏并传入正确的字符串参数。

    解决方案:

    1. 可以增加数据存储区的大小,确保所有数据都能被保存,例如将数据存储区域大小(DATA_LCD_SIZE)从32增加到64。

    2. 在存储数据时,需要判断数据存储索引是否超出存储区限制,如果超出,则需要进行数据处理,例如清空数组 (data_lcd) 或者滚动显示等。

    3. 在调用数据显示函数 (lcd1602_show_string) 时需要传入正确的参数,确保在 LCD1602 上正确显示数据。

    4. 在显示前需要清屏并传入正确的字符串参数,例如调用函数 lcd1602_clear() 清屏,调用函数 lcd1602_show_string() 传入数据数组 (data_lcd)

    修改后的正确代码:

    #include "reg52.h"
    #include "lcd1602.h"
    
    #define DATA_LCD_SIZE 64 // 增加数组大小以存储更多数据
    
    u8 data_lcd[DATA_LCD_SIZE] = {0}; // 初始化数组
    volatile u8 data_received = 0; // 接收到的数据
    volatile u8 data_index = 0; // 数组索引
    volatile u8 new_data_flag = 0; // 新数据标志
    
    /*******************************************************************************
    
    * 函 数 名 : uart_init
    
    * 函数功能 : 串口通信中断配置函数
    
    * 输 入 : baud:波特率对应的TH、TL装载值
    
    * 输 出 : 无
    
    *******************************************************************************/
    
    void uart_init(u8 baud) {
    
    TMOD |= 0X20; // 设置计数器工作方式2
    
    SCON = 0X50; // 设置为工作方式1
    
    PCON = 0X80; // 波特率加倍
    
    TH1 = baud; // 计数器初始值设置
    
    TL1 = baud;
    
    ES = 1; // 打开接收中断
    
    EA = 1; // 打开总中断
    
    TR1 = 1; // 打开计数器
    
    }
    
    /*******************************************************************************
    
    * 函 数 名 : main
    
    * 函数功能 : 主函数
    
    * 输 入 : 无
    
    * 输 出 : 无
    
    *******************************************************************************/
    
    void main() {
    
    uart_init(0XFA); // 波特率为9600
    
    lcd1602_init(); // 初始化LCD1602
    
    while(1) {
    
    if(new_data_flag) // 如果有新数据标志
    
    {
    
    lcd1602_clear(); // 清除LCD
    
    data_lcd[data_index] = '\0'; // 在字符串末尾添加空字符
    
    lcd1602_show_string(0, 0, data_lcd); // 显示数据
    
    new_data_flag = 0; // 清除新数据标志
    
    }
    
    }
    
    }
    
    void uart() interrupt 4 // 串口通信中断函数
    
    {
    
    u8 rec_data;
    
    RI = 0; // 清除接收中断标志位
    
    rec_data = SBUF; // 读取接收到的数据
    
    if(data_index < (DATA_LCD_SIZE - 1)) // 如果数组未满
    
    {
    
    data_lcd[data_index] = rec_data; // 存储接收到的数据
    
    data_index++; // 移动到下一个位置
    
    new_data_flag = 1; // 设置新数据标志
    
    }
    
    else {
    
    // 数组已满,这里可以添加处理逻辑,例如滚动显示或清空数组
    
    data_index = 0; // 重置索引
    
    new_data_flag = 1; // 设置新数据标志
    
    }
    
    }
    
    

    其中,lcd1602_show_string 函数的调用方式应该为:

    
    lcd1602_show_string(0, 0, data_lcd);
    
    

    其中,第一个参数表示行数,第二个参数表示列数,第三个参数表示传入的数据数组。

    另外需要注意,在 LCD 显示时需要先清屏,可以通过调用函数 lcd1602_clear() 进行清屏,然后再传入正确的数据数组进行显示。

    
    lcd1602_clear(); // 清除LCD
    
    lcd1602_show_string(0, 0, data_lcd); // 显示数据
    
    
    评论

报告相同问题?

问题事件

  • 创建了问题 5月22日