前几天在网上淘了一块TFT2.4寸屏,驱动芯片是的ILI9341,带转接板SPI通信方式,店家提供代码例程,发现不论怎样调试屏就是不显示,被搞矇了,用逻辑分析仪测试通信时序和规格书对比,规格书要求CS时间为40ns为写入时间,读取时间为40ns,共80ns,而单片机输出为80us,是单片机速度不够快还是代码问题?
#include <STC8H.H>
#include <intrins.h>
#define uint8_t unsigned char
#define uint16_t unsigned int
#define uint32_t unsigned long
//SDO引脚可以不连接
// 引脚定义 (根据实际电路连接修改)
#define LCD_CS P10
#define LCD_DC P11
#define LCD_SCL P12
#define LCD_SDO P13 // 主机输出
#define LCD_SDI P14 // 主机输入
#define reset P16
// 颜色定义 (RGB565)
#define WHITE 0xFFFF
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
#define BLUE 0x001F
// 延时函数 (1个_nop_约42ns @24MHz)
void delay_ns(uint8_t ns)
{
while(ns--) _nop_();
}
void Delay1ms(void) //@24.000MHz
{
unsigned char data i, j;
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
void delay_ms(unsigned int ms)
{
while(ms--)
{
Delay1ms();
}
}
// SPI初始化
void SPI_Init(void) {
LCD_CS = 1; // 片选无效
LCD_DC = 1; // 默认数据模式
LCD_SCL = 0; // 时钟低电平
// 配置IO模式 (P1.0-P1.4推挽输出)
P1M1 = 0x00; // 清除低5位
P1M0 = 0xFF; // P1.0-P1.6推挽输出
}
// SPI写命令
void LCD_Write_Cmd(uint8_t cmd)
{
uint8_t i;
LCD_CS = 0; // 片选有效
LCD_DC = 0; // 命令模式
// delay_ns(1); // >10ns (tas)
// 发送8位命令
for( i= 0; i < 8; i++)
{
LCD_SCL = 0;
LCD_SDO = (cmd & 0x80) ? 1 : 0;
cmd <<= 1;
// delay_ns(1); // >30ns (tds)
LCD_SCL = 1;
// delay_ns(1); // >40ns (twrh)
}
LCD_SCL = 0;
LCD_CS = 1; // 片选释放
}
// SPI写数据
void LCD_Write_Data(uint8_t dat)
{
uint8_t i;
LCD_CS = 0; // 片选有效
LCD_DC = 1; // 数据模式
// delay_ns(1); // >10ns (tas)
// 发送8位数据
for(i = 0; i < 8; i++) {
LCD_SCL = 0;
LCD_SDO = (dat & 0x80) ? 1 : 0;
dat <<= 1;
// delay_ns(1); // >30ns (tds)
LCD_SCL = 1;
// delay_ns(1); // >40ns (twrh)
}
LCD_SCL = 0;
LCD_CS = 1; // 片选释放
}
// SPI读数据
/*uint8_t LCD_Read_Data(void)
{
uint8_t dat = 0;
uint8_t i;
// 配置SDI为输入
P1M1 |= (1 << 4); // P1.4高阻输入
P1M0 &= ~(1 << 4);
LCD_CS = 0; // 片选有效
LCD_DC = 1; // 数据模式
delay_ns(1); // >10ns (tas)
// 读取8位数据
for( i = 0; i < 8; i++)
{
LCD_SCL = 0;
delay_ns(2); // >60ns (ttdl)
LCD_SCL = 1;
dat <<= 1;
if(LCD_SDI) dat |= 1;
delay_ns(2); // >60ns (trdh)
}
LCD_SCL = 0;
LCD_CS = 1; // 片选释放
// 恢复SDO为输出模式
P1M1 &= ~(1 << 4);
P1M0 |= (1 << 4);
return dat;
}*/
// ILI9341初始化
void ILI9341_Init(void) {
// 硬件复位
LCD_CS = 1;
reset=0;
delay_ms(50);
reset=1;
delay_ms(100);
// 这里可以添加硬件复位逻辑,如果板子有RESET引脚
// 软件初始化序列
LCD_Write_Cmd(0xCF); // Power Control B
LCD_Write_Data(0x00);
LCD_Write_Data(0xC1);
LCD_Write_Data(0x30);
LCD_Write_Cmd(0xED); // Power on sequence control
LCD_Write_Data(0x64);
LCD_Write_Data(0x03);
LCD_Write_Data(0x12);
LCD_Write_Data(0x81);
// ... 省略部分初始化命令,完整初始化序列请参考ILI9341数据手册
LCD_Write_Cmd(0x36); // Memory Access Control
LCD_Write_Data(0x48); // RGB顺序设置
LCD_Write_Cmd(0x3A); // Pixel Format
LCD_Write_Data(0x55); // 16位像素
LCD_Write_Cmd(0x11); // Sleep Out
delay_ms(120);
LCD_Write_Cmd(0x29); // Display On
}
// 设置显示区域
void LCD_SetWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
LCD_Write_Cmd(0x2A); // 列地址设置
LCD_Write_Data(x1 >> 8);
LCD_Write_Data(x1 & 0xFF);
LCD_Write_Data(x2 >> 8);
LCD_Write_Data(x2 & 0xFF);
LCD_Write_Cmd(0x2B); // 行地址设置
LCD_Write_Data(y1 >> 8);
LCD_Write_Data(y1 & 0xFF);
LCD_Write_Data(y2 >> 8);
LCD_Write_Data(y2 & 0xFF);
LCD_Write_Cmd(0x2C); // 写入GRAM
}
// 刷屏函数 (填充整个屏幕)
void LCD_FillScreen(uint16_t color)
{
uint32_t i;
LCD_SetWindow(0, 0, 239, 319); // ILI9341通常为240x320
for( i = 0; i < 240*320; i++) {
LCD_Write_Data(color >> 8); // 高字节
LCD_Write_Data(color & 0xFF); // 低字节
}
}
// 主函数示例
void main() {
SPI_Init(); // 初始化SPI
ILI9341_Init(); // 初始化LCD
while(1) {
LCD_FillScreen(RED);
delay_ms(500);
LCD_FillScreen(GREEN);
delay_ms(500);
LCD_FillScreen(BLUE);
delay_ms(500);
LCD_FillScreen(WHITE);
delay_ms(500);
LCD_FillScreen(BLACK);
delay_ms(500);
}
}
|