×
嵌入式 > 技术百科 > 详情

PC机与单片机在串口通讯

发布时间:2020-09-10 发布时间:
|
    刚调好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                      //PA5
#define RW                      //PA6
#define EN                      //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增减的指令,写入相关的命令就可以了:(



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
FPGA及CPLD应用领域不断拓展