上次成功用FPGA的PIO口模拟時序成功操控1602,今天就又試了下用nios ii自帶的LCD 16207核驅動1602.網上關于這方面的程式大概有三種,我參考了它們都沒成功。其實有兩種方法給出代碼的作者都自己說沒有調試成功,其他說可以的大概隻是轉載,并沒有親身試驗吧。
這兩種方法都是直接用了LCD 1607核驅動1602,再用file檔案操作方式進行顯示,或設定STDOUT為lcd直接用printf函數顯示。事實上,這兩種方法都是行不通的,因為nios ii自帶的LCD 16207核并不能直接驅動1602,它的初始化函數并不适合1602,是以這兩種方法都不行。
第三種方法是用了LCD 16207核,但是自己寫初始化函數和其他驅動函數。這種方法我也覺得理論上可以成功,但是至今沒有成功。這裡我引用網上寫得較好的一個程式:
#include<system.h>
#include<altera_avalon_lcd_16207_regs.h>
#include<alt_types.h>
alt_u8 lcd_string1[] = "HB_XFU__ELC__LAB";
alt_u8 lcd_string2[] = "2009 xk";
void check_busy() //讀液晶的忙标志位并檢測
{
alt_u8 status;
do
{
status="IORD"_ALTERA_AVALON_LCD_16207_STATUS(LCD_BASE);
}while(status&0x80);
}
void lcd_init() //液晶1602初始化
{
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_BASE, 0x38); //功能設定
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_BASE, 0x01); //清屏
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_BASE, 0x06); //Y位址自動加1模式
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_BASE, 0x0c); //顯示開,不顯示光标
}
void lcd_prints(alt_u8 *string) //列印字元串
{
while(*string!='\0')
{
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_DATA(LCD_BASE, *string);
string++;
}
}
void select_xy(alt_u8 x,alt_u8 y) //選擇螢幕坐标,x=0為第1行,x=1為第2行
{ //y=0~15,分别對應第1列到第16列
check_busy();
if(x%2==0)
{
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_BASE, 0x80+y);
}
else
{
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_BASE, 0xc0+y);
}
}
int main (void) __attribute__ ((weak, alias ("alt_main"))); //将程式的入口改為alt_main(),可以使
//很多驅動不會加載,可以大大減小代碼長度
void alt_main()
{
lcd_init();
select_xy(0,0);
lcd_prints(lcd_string1);
select_xy(1,7);
lcd_prints(lcd_string2);
}
【本文來自】: IT線上(http://www.itolhome.cn)轉載請注明出處! 【原文位址】:http://www.itolhome.cn/thread-9322-1-1.html
上面的程式還有些地方修改後可以更好,在初始化是最好先延時15ms以上再寫三次不帶忙檢測的0x38指令,每次指令之間延時5ms,這是保證初始化成功,代碼如下:
void lcd_init() //液晶1602初始化
{
usleep(400000);
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x38);
usleep(5000);
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x38);
usleep(5000);
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x38);
usleep(5000);
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x38); //功能設定
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x08); //關屏
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x01); //清屏
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x06); //Y位址自動加1模式
check_busy();
IOWR_ALTERA_AVALON_LCD_16207_COMMAND(LCD_0_BASE, 0x0c); //顯示開,不顯示光标
}
以上方法照理應該可以,有作者确實也說親試成功,但自己調了半天也沒成功。我嘗試着在代碼間加延時,還采用了多次重複寫指令,寫資料的方法,發現偶爾可以出現些亂碼,有時可以出現我寫的字元,但坐标不對,其他坐标上出現了亂碼,不知道為什麼?後來我又用了邏輯分析儀signaltap檢測了下,發現LCD 16207核的接口LCD_E一直為低電平,我不知道是為什麼。難道自帶的LCD 16207核的LCD_E本來就是一個低電平嗎?如果是這樣,那這個方法應該是行不通的啊!或者是因為其他原因導緻的?我會繼續測試,希望有經驗的大蝦們可以指點指點啊!