
AVR写LCD12864,在写页地址后读状态,一直为忙,那为懂AVR的帮我解决一下呢,用的是atmel studio 6.0 10
#define LCD_Page 0xB8 //起始页,共8页
#define LCD_Vertical 0x40 //起始例地址,共64例,共分为两块区域
#define LCD_ON 0x3f //液晶屏开
#define LCD_OFF 0x3E //液晶屏关
//定义接口寄存器
#define LCD_Data_Write PORTC //输出数据
#define LCD_Data_Flow DDRC //设置C口引脚方向,输出为写,输入为读
#define LCD_Data_Read PINC //读取状态口地址
#define LCD_Ctrl_Port PORTD
#define LCD_Ctrl_Flow DDRD
void LCD_Status()
{
INTU8 check;
Check_Busy:
LCD_Data_Flow=0x00;//设置为输入
LCD_Data_Write=0xff;//设置上拉电阻
LCD_Ctrl_Flow=0xff;//设置D口为输出
RW_1();
asm("nop");
RS_0();
asm("nop");
E_1();
asm("nop");
check=LCD_Data_Read;
E_0();
while(check&0x80) goto Check_Busy;
}
void LCD_Initialize()
{
Rest_1();
LCD_Write_Command(LCD_OFF);
LCD_Write_Command(LCD_ON);
}
void LCD_Write_Command(INTU8 m_com)
{
LCD_Status();//读取LCD液晶屏的状态
LCD_Data_Flow=0xff;//C口设置为输出
LCD_Data_Write=0xff;
LCD_Ctrl_Flow=0xff;//D口设置为输出
RW_0();
asm("nop");
RS_0();
asm("nop");
LCD_Data_Write=m_com;
_delay_us(20);
E_1();
asm("nop");
E_0();
}
void LCD_Write_Data(INTU8 m_data)
{
LCD_Status();
LCD_Data_Flow=0xff;//设置端口C为输出
LCD_Data_Write=0xff;//设置输出高电平
RW_0();
asm("nop");
RS_1();
asm("nop");
if(!Data_Display) LCD_Data_Write=m_data;
else LCD_Data_Write=~m_data;
_delay_us(20);
E_1();
asm("nop");
E_0();
}
void LCD_Clear()
{
INTU8 j,k;
CS1_1();
CS2_1();
LCD_Write_Command(LCD_Page+0);//写了这句后,读液晶状态一直为忙
LCD_Write_Command(LCD_Vertical+0);
for(j=0;j<8;j++)
{
LCD_Write_Command(LCD_Page+j);
for(k=0;k<64;k++)
{
LCD_Write_Command(LCD_Vertical+k);
LCD_Write_Data(0x00);
}
}
}
写开关屏命令后,读状态都是正常的,就是在写page和例时检测液晶屏状态,就一直是忙,程序检查了几遍都没发现问题,实在没法了, 展开
没能直接找出你程序的明显问题,但有几点可以考虑下:
void LCD_Status()中,仔细对照12864的说明书,看你口线的操作逻辑,是否完全符合说明书。你写开关屏命令正确,但也并不能保证逻辑就是正确的,Y? 因为你锁出去的数据是不同的,不仔细看你程序,理论上讲,对后续的程序的影响是不一样的。不同厂家的LCD操作,大同小异,但确实各有不同之处。
在AVR中,asm("nop");是可以用NOP();来代替的,后者比前者看起来舒服些。
你没说你的CPU连接LCD的排线的长度,此长度小于5cm时,考虑可以很少;>10cm时,需要考虑电容效应,信号会被延迟,你程序中NOP()的个数可能会不够,因为AVR的机器周期其实是可以小于us级的(看你的晶振速度了),一个NOP可能起不到作用,需要N个。
个人观点供参考,我用LCD时,根本就不去查询LCD是否繁忙,因为现在的LCD接收端口都是硬件锁存的,速度非常快,根本不会出现繁忙拥堵的情况。下面是我使用320240LCD的写命令和数据的函数,没查询,大量使用从来也不出问题:
void LcmWriteADataByte(uchar mydata) //写数据.
{
pinLcmA00();
LCM=mydata;
NOP();
pinLcmCS0();
pinLcmWR0();
NOP();
pinLcmWR1();
pinLcmCS1();
}void LcmWriteAControlByte(uchar mycommand) //写指令.
{
pinLcmA01();
LCM=mycommand;
pinLcmCS0();
pinLcmWR0();
NOP();
pinLcmWR1();
pinLcmCS1();
pinLcmA01();
}总结,不正常工作最可能的两个原因(不是全部原因):A逻辑不完全符合说明书;B延时不够,或某些地点漏做延时了。希望有所帮助。