nios ii 之 LCD 1602

来源:互联网 发布:hp打印机端口设置 编辑:程序博客网 时间:2024/05/01 13:45

大家好!这是本人第一篇博文,写得不好,还请多多指教。

初学nios,发现它多少有点和51单片机不一样。自己也摸爬打滚,连碰带撞,走了不少弯路,所以希望可以分享自己的经验,让初学者少走些弯路,也作为交流手段,望前辈们指教。

LCD 1602是一款较常见的液晶显示屏,可以显示16*2个字符(不能显示汉字)。网上为单片机写的程序较多,为FPGA写的少。在此我提供自己写的基于nios ii的程序,所用的板子是DE0 Nano板,采用用IO口模拟时序。

一、硬件设计

1602有5v的和3.3v的,我的DE0 Nano板IO口是3.3v的。我手上有5v的1602,本来一直很担心3.3v的IO口驱动不了1602,还怕把自己的板子烧了。经过多次尝试,我发现这是可以实现的。因为担心烧坏引脚我在LCD_RS,LCD_RW,LCD_E,LCD_DB0-7和3.3Vio口之间串了一个100欧姆的电阻。电阻的大小并不是固定的,几百差不多,因为电阻不够,其实有部分电阻我是用50欧姆的。

在sopc中加入各个模块,其中要注意加入的8位宽的LCD_DATA是bidir类型的。

二、软件设计

1.时序约束

1602的时序并不复杂,直接用网上的单片机程序改编也可以,但要注意,不难是会出问题的。因为单片机的指令周期大都在us级,1602的时序约束是ns级的,所以大部分单片机程序都不需要太多延时。但对于FPGA这种高速器件,这些时序参数要格外注意。我之前一直没有成功就是因为没有注意到这一点。像对于DE0 Nano板tSP1就需要延时,否者不能满足,而单片机程序很多都不需要。tPW,tC也要去延时,其他的时间都可以直接满足了。


2.初始化

1602LCD的一般初始化(复位)过程

延时15mS

写指令38H(不检测忙信号)

延时5mS

写指令38H(不检测忙信号)

延时5mS

写指令38H(不检测忙信号)

以后每次写指令、读/写数据操作均需要检测忙信号

写指令38H:显示模式设置

写指令08H:显示关闭

写指令01H:显示清屏

写指令06H:显示光标移动设置

写指令0CH:显示开及光标设置

初始化函数:

void InitLcd(){//clear the LCD_EIOWR_ALTERA_AVALON_PIO_DATA(LCD_E_BASE, 0x00);usleep(150000);//write third time 0x38 to LCD 1602,do not check busy,third time to ensure initial succeedLcdWrite(0x38,CMD);usleep(5000);LcdWrite(0x38,CMD);usleep(5000);LcdWrite(0x38,CMD);usleep(5000);//write 0x38 once more,set display mode(16*2,5*7,8bit)LcdWriteCmd(0x38);//close screenLcdWriteCmd(0x08);//clear screenLcdWriteCmd(0x01);//set cursor mode(N=1)LcdWriteCmd(0x06);//open the screenLcdWriteCmd(0x0c);}
3、写函数
void LcdWrite(alt_u8 data,alt_u8 RS){//set LCD_DATA on write stateIOWR_ALTERA_AVALON_PIO_DIRECTION(LCD_DATA_BASE, 0xff);//set 1 to LCD_RS for writing data,0 for writing commandIOWR_ALTERA_AVALON_PIO_DATA(LCD_RS_BASE, RS);//set 0 to LCD_RW for writing patternIOWR_ALTERA_AVALON_PIO_DATA(LCD_RW_BASE, WRITE);//write dataIOWR_ALTERA_AVALON_PIO_DATA(LCD_DATA_BASE, data);//set LCD_Eusleep(1);IOWR_ALTERA_AVALON_PIO_DATA(LCD_E_BASE, 0x01);//clear LCD_Eusleep(3);IOWR_ALTERA_AVALON_PIO_DATA(LCD_E_BASE, 0x00);}
4、读函数
alt_u8 LcdRead(alt_u8 RS){alt_u8 read_data;//set LCD_DATA on read stateIOWR_ALTERA_AVALON_PIO_DIRECTION(LCD_DATA_BASE, 0x00);//set 1 to LCD_RS for reading data,0 for reading commandIOWR_ALTERA_AVALON_PIO_DATA(LCD_RS_BASE, RS);//set 1 to LCD_RW for reading patternIOWR_ALTERA_AVALON_PIO_DATA(LCD_RW_BASE, READ);//set LCD_Eusleep(1);IOWR_ALTERA_AVALON_PIO_DATA(LCD_E_BASE, 0x01);//read datausleep(1);read_data = IORD_ALTERA_AVALON_PIO_DATA(LCD_DATA_BASE);//clear LCD_Eusleep(2);IOWR_ALTERA_AVALON_PIO_DATA(LCD_E_BASE, 0x00);return read_data;}
5、写命令
void LcdCheckBusy(){while(LcdRead(CMD) & 0x80);}void LcdWriteCmd(alt_u8 command){LcdCheckBusy();LcdWrite(command,CMD);}
6、写数据
void LcdWriteData(alt_u8 data){LcdCheckBusy();LcdWrite(data,DATA);}
7、显示函数

void LocateXY(alt_u8 x,alt_u8 y){x &= 0x0f;//ensure the x between 0 and 31y &= 0x01;//ensure that the y is 1 or 0if(y){LcdCheckBusy();LcdWriteCmd(x | 0x40 | 0x80);}else{LcdCheckBusy();LcdWriteCmd(x | 0x80);}}void PutChar(char value,alt_u8 x,alt_u8 y){LocateXY(x,y);LcdWriteData(value);}alt_u8 PutStr(char *value,alt_u8 x,alt_u8 y){alt_u8 len = 0,i;while(value[len] > 31) len ++;for(i = 0;i < len;i ++){PutChar(value[i],x ++,y);if(x == 16)//Cyclic display{x = 0;y ^= 0x01;}}return len;//return the length of the string}
8、头文件

#ifndef LCD_1602_SOLUTION_H_#define LCD_1602_SOLUTION_H_#define DATA 1#define CMD  0#define READ1#define WRITE0#include<system.h>#include<altera_avalon_pio_regs.h>#include<alt_types.h>#include<unistd.h>//check if the LCD 1602 is in busyvoid LcdCheckBusy();//set the beginning coordinate of the wordvoid LocateXY(alt_u8 x,alt_u8 y);//LCD writing function,the argument RS decide a data or a command to be writtenvoid LcdWrite(alt_u8 data,alt_u8 RS);//LCD reading function,the argument RS decide a data or a command to be readalt_u8 LcdRead(alt_u8 RS);//write a command to LCD 1602void LcdWriteCmd(alt_u8 command);//write a byte of data to LCD 1602void LcdWriteData(alt_u8 data);//read a command from LCD 1602alt_u8 LcdReadCmd();//read a data from LCD 1602alt_u8 LcdReadData();/*use the following function to initial the LCD 1602 and print words *///initial the LCD 1602void InitLcd();//print a charvoid PutChar(char value,alt_u8 x,alt_u8 y);//print a stringalt_u8 PutStr(char *value,alt_u8 x,alt_u8 y);//clear screenvoid LcdClearScreen();#endif /* LCD_1602_SOLUTION_H_ */
9、主函数

#include"lcd_1602_solution.h"int main(){InitLcd();
PutStr("hello",0,1);PutChar('a',0,0);while(1);return 0;}
因为整个工程太大,不可能在这里都说好,所以我把整个做好的工程放在我的CSDN资源里,大家可以免费下载 http://download.csdn.net/detail/ming1006/4036416
点击打开链接