上次成功用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本来就是一个低电平吗?如果是这样,那这个方法应该是行不通的啊!或者是因为其他原因导致的?我会继续测试,希望有经验的大虾们可以指点指点啊!