现象1:普通单芯铜线焊接的屏幕,能够正常读到ID,但是无法显示内容。
最近在做导师的项目,打板子前想先把一块2.4寸的TFT调好。之前屏幕已经试过能用,奈何今天用连接线外接时,能读到ID,但无法显示。
查了一下8080的时序,看了一下程序代码,基本确定是由于串扰造成的信号完整性问题,屏幕的并数据口电平转换比较快,很容易出现串扰问题,甚至用手指去触碰,都可能产生干扰。
因为项目问题,临时换方案不大可能,所以想着从时序上入手去降低刷新率。由于主控是STM32F103RCT6,所以没有FSMC,软件去模拟的,用的原子哥的LCD程序去修改显示驱动。
我的思路是,由于串扰的存在,只要预先改好DATAOUT并行口的电平,然后延时稳定后,再让屏幕来读取,这样就能把信息无误的传递过去。先看下发送的程序:
//写寄存器函数
//data:寄存器值
void LCD_WR_REG(u16 data)
{
LCD_RS_CLR;//写地址
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
// delay_us(100);
}
//写数据函数
//可以替代LCD_WR_DATAX宏,拿时间换空间.
//data:寄存器值
void LCD_WR_DATAX(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
我们看到,想要让数据稳定,那么可以在DATAOUT(data)后加入延时来处理,修改后是这样
//写寄存器函数
//data:寄存器值
void LCD_WR_REG(u16 data)
{
LCD_RS_CLR;//写地址
LCD_CS_CLR;
DATAOUT(data);
delay_us(1);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
// delay_us(100);
}
//写数据函数
//可以替代LCD_WR_DATAX宏,拿时间换空间.
//data:寄存器值
void LCD_WR_DATAX(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
delay_us(1);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
实测,延时1us就ok,如果不够,你可以先把显示加长点,再降到合适的时长。
刷新屏幕能显示了,把屏幕刷成蓝屏。
现象2:问题还没解决,能够刷新整块屏幕,但没法显示字体,而且,只要显示字体,刷新就会失效。
主函数大概是这样:
如果不注释LCD_ShowString,那么刷新屏幕也会失效。
造成这样的原因和上面一样,我们要减慢WR和CS的速度,不然会由于串扰,使数据接收和发送的使能失效,无法完成对应的功能,因此需等待并口电平转换完成。由于显示数字和刷屏用的函数不一样,这是通过画点来实现刷屏的,因此我们改对应函数的时延即可:
```c
//快速画点
//x,y:坐标
//color:颜色
void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color)
{
if(lcddev.id==0X9341||lcddev.id==0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF); //这里也要跳转过去加时延
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
}else if(lcddev.id==0X5510)
{
LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(x>>8);
LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(x&0XFF);
LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(y>>8);
LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(y&0XFF);
}else if(lcddev.id==0X1963)
{
if(lcddev.dir==0)x=lcddev.width-1-x;
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
}else if(lcddev.id==0X6804)
{
if(lcddev.dir==1)x=lcddev.width-1-x;//横屏时处理
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
}else
{
if(lcddev.dir==1)x=lcddev.width-1-x;//横屏其实就是调转x,y坐标
LCD_WriteReg(lcddev.setxcmd,x);
LCD_WriteReg(lcddev.setycmd,y);
}
LCD_RS_CLR;
LCD_CS_CLR;
DATAOUT(lcddev.wramcmd);//写指令
delay_us(1);//这里加时延
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
LCD_WR_DATA(color); //写数据
}
这样就能正常显示了,但是有一定的不稳定性,毕竟串扰极有可能由于长期运行,温度、空气等原因加剧,所以还是画板子吧,或者使用屏蔽线,做好防护。