PC机与单片机在串口通讯
时间:11-22
来源:互联网
点击:
刚调好LCD1602之后,又做了个PC串口与单片机的通信的程序,实现了基本的COM口的功能,从PC机上通过串口发出来的字符,可以在1602液晶上面显示出来。
实现的基本功能是:
1,BACKSPACE功能,支持删除键,但是仅限于本行;
2,ENTER功能,回车&换行功能,当一行输入的时候按下ENTER键,即可切换并且清空新行;
3,ESC键功能,所有的显示清除,光标清零;
4,单行循环显示,拥有自动回车功能,当一行中的字符到末尾是自动清空本行,并且在本行的开头显示输入的字符;
5,回显字母A,表示接收的数据顺利。
拟定增加的功能有:
1,陆续增加方向键(Up,Down,left,right),PageDown,PageUp,Insert,Home,End等按键;
2,增加欢迎和帮助功能;
3,增加显示字符的自动筛选功能;
4,增加按键字符上传到PC串口。
目前已知的bug:
1,只接受单字节的按键;
2,对于ESC功能,其它有0x1B的按键均能实现此功能,需要另加甄别;
源程序如下:
160的配置文件:
------------------------------------1602.h开始---------------------------------------------
#define uchar unsigned char
#define uint unsigned int
#define RS 5 //PA5
#define RW 6 //PA6
#define EN 7 //PA7
#define INDATA PIND //data port
#define OUTDATA PORTD //data port
/
uchar lcd_bz(void)
{
uchar result = 1;
PORTA &= ~(1 //RS = 0
PORTA |= (1 //RW = 1
DDRD = 0x00; //PORTD as input
PORTD = 0xff; //pull-up enable
PORTA |= (1 //EN = 1
_delay_ms(2);
if((INDATA & 0x80)==0x80)
result = 1;
else
result = 0;
PORTA &= ~(1 //EN = 0
DDRD = 0xff; //PORTD as output
return result;
}
/
void lcd_write(uchar cmd)
{
PORTA &= ~(1 //RS = 0
PORTA &= ~(1 //RW = 0
OUTDATA = cmd;
PORTA &= ~(1 //EN = 0
PORTA |= (1 //EN = 1
_delay_ms(1);
PORTA &= ~(1 //EN = 0
}
/
void lcd_write_cmd(uchar cmd)
{
while(!lcd_bz()) {;} //wait when busy?
PORTA &= ~(1 //RS = 0
PORTA &= ~(1 //RW = 0
OUTDATA = cmd;
PORTA &= ~(1 //EN = 0
//_delay_ms(1);
PORTA |= (1 //EN = 1
_delay_ms(2);
PORTA &= ~(1 //EN = 0
}
/
void lcd_write_data(uchar data)
{
while(!lcd_bz()) {;} //wait when busy?
PORTA |= (1 //RS = 1
PORTA &= ~(1 //RW = 0
OUTDATA = data;
PORTA &= ~(1 //EN = 0
PORTA |= (1 //EN = 1
_delay_ms(2);
PORTA &= ~(1 //EN = 0
}
//
void lcd_setxy(uchar x, uchar y)
{
if (x > 15)
x = 0;
switch (y)
{
case 1: lcd_write_cmd(x | 0xc0); break; //set line 2
default: //Set to line 1 when y > 2
case 0: lcd_write_cmd(x | 0x80); break; //set line 1
}
}
/
void lcd_init(void)
{
DDRA = 0xff;
DDRD = 0xff;
_delay_ms(10);
lcd_write(0x38);
lcd_write(0x38);
lcd_write(0x38);
_delay_ms(2);
lcd_write_cmd(0x38); //display mode setting
lcd_write_cmd(0x01); //display off,
lcd_write_cmd(0x08); //dispaly clean
lcd_write_cmd(0x06); //cursor increase add. by 1.
lcd_write_cmd(0x0e); //display on, cursor disappear
_delay_ms(1);
}
/
void lcd_clean(uchar lcd_line)
{
uchar lcd_pos;
lcd_setxy(0, lcd_line);
for(lcd_pos = 0; lcd_pos < 16; lcd_pos++)
{
lcd_setxy(lcd_pos, lcd_line);
lcd_write_data(0x20); //display mode setting
_delay_ms(1);
}
}
------------------------------------1602.h结束--------------------------------------------
串口设置的头文件
------------------------------------com.h开始--------------------------------------------
#define uchar unsigned char
#define uint unsigned int
#define FOSC 16000000 //CLOCK SPEED
#define BAUD 9600
/
case 0x0d:
{
line = ~(line|0xfe); //chang the other line
lcd_clean(line); //clean this line
lcd_setxy(0, line); //set position to 0
pre_pos = i;
i = 0; //reset postion i
break;
}
case 0x08:
{
if(i != 0) //disable BackSpace when i = 0
{
i--;
lcd_setxy(i, line); //backspace a position in current line
lcd_write_data(0x20); //clean current character, position add 1
lcd_setxy(i, line); //set the position back
}
break;
}
case 0x1b:
{
_delay_ms(10);
lcd_clean(0); //clean line 0
lcd_clean(1); //clean line 1
lcd_setxy(0, 0); //reset (0,0)
i = 0;
line = 0;
pre_pos = 0;
break;
}
default:
{
lcd_setxy(i&0x0f, line);
if(i > 15)
{
lcd_clean(line); //auto clean current line
lcd_setxy(0, line); //reset the position back to (0, $(line))
i = 0; //reset the position i
}
lcd_write_data(temp);
i++;
break;
}
}
USART_Status(1); //Enable COM
}
}
------------------------------------main.c结束--------------------------------------------
这个程序写在新的1602的驱动之前,所以有关1602的部分子程序并没有采用新的代码和函数,而且在backspace的部分是采用的逻辑的办法来实现的,所以感觉有点不太完美,好在处理的东西还不算太多,执行的速度还是可以接受的。我在后来再深入发掘datasheet的时候才发现,1602有指针AC增减的指令,写入相关的命令就可以了:(