标题:
关于单片机串口通讯内容在1602液晶上显示的问题
[打印本页]
作者:
code_404
时间:
2018-11-22 21:18
标题:
关于单片机串口通讯内容在1602液晶上显示的问题
自己写了一段将单片机串口控制led灯亮灭,然后在LCD显示灯状态的程序。现有一下问题,向各位坛友请教:1.1602查忙程序,在下面程序130行中,只要我加入了带忙检测的清屏语句,LCD就不显示,但我串口调试助手还是能接收到返回值(例如ok_1)。而且在我显示字符串函数中(72行)加入忙检测,LCD也不能正常显示字符。(本人对查忙函数存在意义还是不怎么明白,只知道需要查忙来确定LCD是否在写入数据,防止数据丢失)
2.在我字符串定义中(13-15行),如果我在后面加上感叹号(如“uchar code error[]="error!";"),则我在串口助手中发送02之后,1602正常显示,串口助手正常收到返回值ok_2,但无法之后再次发送数据,就像串口中断没有再次打开一样,无论我在串口助手中发送什么,LCD以及串口助手都得不到返回值。但是,如果我缩短数组长度(如“uchar code error[]="er!";"),则程序正常运行(据我测试,两个字母加一个感叹号是上限了,像off!就已经出现跟error!一样的问题)。
希望有大神能给我解答,感激不尽。
单片机代码:
#include <reg52.h>
#include <stdio.h>
#define uint unsigned int
#define uchar unsigned char
#define PORT P2
sbit RS=P3^5; //寄存器选择位
sbit RW=P3^6; //读写选择位
sbit EN=P3^7; //使能位
sbit LED=P3^4;
uchar code led_on[]="on";
uchar code led_off[]="off";
uchar code error[]="error";
uchar a,flag_uart,flag_led;
void delay_us(uchar n) //微秒级别的延时
{
while(n--);
}
void delay_ms(uint x) //延时1ms
{
uint i,j;
for(i=x;i>0;i--)
for(j=114;j>0;j--);
}
void lcd_write_command(uchar command) //写命令函数
{
RS=0;
RW=0;
PORT=command;
EN=1;
delay_us(5);
EN=0;
}
void lcd_write_data(uchar dat) //写数据函数
{
RS=1;
RW=0;
PORT=dat;
EN=1;
delay_us(5);
EN=0;
}
void lcd_check_busy() //查忙函数
{
RS=0;
RW=1;
PORT=0xFF; //51IO口拉高,准备读状态
EN=1;
while(PORT & 0x01);
EN=0;
}
void lcd_write_command_busy(uchar command) //带查忙的写命令函数
{
lcd_check_busy();
RS=0;
RW=0;
PORT=command;
EN=1;
delay_us(5);
EN=0;
}
void lcd_write_str(uchar x,uchar y,uchar *p) //显示字符串函数
{
if(x==0)
lcd_write_command_busy(0x80+y); //x=0 第一行显示
else
lcd_write_command_busy(0xC0+y); //x=1 第二行显示
while(*p)
{
lcd_write_data(*p); //显示字符串
p++;
}
}
void lcd_init()
{
delay_ms(15);
lcd_write_command(0x38);
delay_ms(5);
lcd_write_command(0x38);
delay_ms(5);
lcd_write_command(0x38);
lcd_write_command_busy(0x38);
lcd_write_command_busy(0x0C); //开显示,关光标,光标不显示
lcd_write_command_busy(0x01); //清屏
lcd_write_command_busy(0x06); //地址指针+1,光标右移
}
void uart_init()
{
TMOD = 0x20;
TH1 = 0xfd;
TL1 = 0xfd;
TR1 = 1;
SCON = 0x50;
EA = 1;
ES = 1;
}
void main()
{
uchar *p;
p="Light:";
lcd_init();
uart_init();
while(1)
{
lcd_write_str(0,0,p);
if(flag_uart==1)
{
flag_uart=0;
ES=0;
TI=1;
switch(flag_led)
{
case 0:
LED=0;
//lcd_write_command_busy(0x01); //清屏
lcd_write_str(0,0,p);
lcd_write_str(1,5,led_off);
printf("ok_0\n");
break;
case 1:
LED=1;
//lcd_write_command_busy(0x01); //清屏
lcd_write_str(0,0,p);
lcd_write_str(1,5,led_on);
printf("ok_1\n");
break;
case 2:
lcd_write_str(1,5,error);
printf("ok_2\n");
break;
}
while(!TI);
TI=0;
ES=1;
}
}
}
void ser() interrupt 4
{
RI=0;
a=SBUF;
flag_uart=1;
if (a==0)
flag_led=0;
else if(a==1)
flag_led=1;
else
flag_led=2;
}
复制代码
作者:
phang
时间:
2018-11-23 09:44
main里的第一个 TI =1;干嘛用的??你置一的话,是会进入中断服务函数的? 你的中断服务函数里只对RI操作。。。
那想象下,中断-------flag_uart = 1;------main------检测flag_uart =1 后 flag_uart = 0; 然后 TI =1-------中断----------flag_uart =1 .............死循环吧???
好好调下。
作者:
code_404
时间:
2018-11-23 16:11
phang 发表于 2018-11-23 09:44
main里的第一个 TI =1;干嘛用的??你置一的话,是会进入中断服务函数的? 你的中断服务函数里只对RI操作。 ...
谢谢回答,我已经调试好了,是清屏指令之后需要一定的延迟来给1602的反应时间。TI=1并没有多大意义,进中断时由RI控制的吧,
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1