新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > PC機與單片機在串口通訊

PC機與單片機在串口通訊

作者: 時間:2016-11-22 來源:網(wǎng)絡 收藏
剛調(diào)好LCD1602之后,又做了個PC串口與單片機的通信的程序,實現(xiàn)了基本的COM口的功能,從PC機上通過串口發(fā)出來的字符,可以在1602液晶上面顯示出來。
實現(xiàn)的基本功能是:
1,BACKSPACE功能,支持刪除鍵,但是僅限于本行;
2,ENTER功能,回車&換行功能,當一行輸入的時候按下ENTER鍵,即可切換并且清空新行;
3,ESC鍵功能,所有的顯示清除,光標清零;
4,單行循環(huán)顯示,擁有自動回車功能,當一行中的字符到末尾是自動清空本行,并且在本行的開頭顯示輸入的字符;
5,回顯字母A,表示接收的數(shù)據(jù)順利。

擬定增加的功能有:
1,陸續(xù)增加方向鍵(Up,Down,left,right),PageDown,PageUp,Insert,Home,End等按鍵;
2,增加歡迎和幫助功能;
3,增加顯示字符的自動篩選功能;
4,增加按鍵字符上傳到PC串口。

目前已知的bug:
1,只接受單字節(jié)的按鍵;
2,對于ESC功能,其它有0x1B的按鍵均能實現(xiàn)此功能,需要另加甄別;

源程序如下:
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的部分子程序并沒有采用新的代碼和函數(shù),而且在backspace的部分是采用的邏輯的辦法來實現(xiàn)的,所以感覺有點不太完美,好在處理的東西還不算太多,執(zhí)行的速度還是可以接受的。我在后來再深入發(fā)掘datasheet的時候才發(fā)現(xiàn),1602有指針AC增減的指令,寫入相關的命令就可以了:(


評論


技術專區(qū)

關閉