天天看點

nios ii 之 使用自帶LCD 16207驅動1602的問題

上次成功用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本來就是一個低電平嗎?如果是這樣,那這個方法應該是行不通的啊!或者是因為其他原因導緻的?我會繼續測試,希望有經驗的大蝦們可以指點指點啊!