硬汉嵌入式论坛

 找回密码
 立即注册
查看: 187|回复: 2
收起左侧

[技术讨论] 8080时序驱动ST7789V屏幕,屏幕无法显示一直花屏

[复制链接]

1

主题

2

回帖

5

积分

新手上路

积分
5
发表于 2025-4-30 15:14:47 | 显示全部楼层 |阅读模式
本帖最后由 摇铃山药 于 2025-4-30 15:51 编辑

我这边使
[C] 纯文本查看 复制代码
#ifndef __ST7789V_LCD_H__
#define __ST7789V_LCD_H__

#ifdef __cplusplus
extern "C" {
#endif


#include "hal/hal_gpio.h"
#include "proj_config.h"
#include "hal/hal_clock.h"
#include "ln_test_common.h"

// 定义屏幕控制引脚
#define LCD_CS_PORT GPIOB_BASE
#define LCD_CS_PIN  GPIO_PIN_6
#define LCD_RS_PORT GPIOB_BASE
#define LCD_RS_PIN  GPIO_PIN_5
#define LCD_WR_PORT GPIOB_BASE
#define LCD_WR_PIN  GPIO_PIN_4
#define LCD_RD_PORT GPIOB_BASE
#define LCD_RD_PIN  GPIO_PIN_3
#define LCD_RESET_PORT GPIOB_BASE
#define LCD_RESET_PIN  GPIO_PIN_7

// 定义数据总线引脚
#define LCD_DATA_PORT GPIOA_BASE
#define LCD_D0_PIN GPIO_PIN_11
#define LCD_D1_PIN GPIO_PIN_10
#define LCD_D2_PIN GPIO_PIN_9
#define LCD_D3_PIN GPIO_PIN_8
#define LCD_D4_PIN GPIO_PIN_7
#define LCD_D5_PIN GPIO_PIN_6
#define LCD_D6_PIN GPIO_PIN_5
#define LCD_D7_PIN GPIO_PIN_0

// 定义延时函数
#define LCD_DELAY_MS(ms) ln_delay_ms(ms)
//#define LCD_DELAY_US(us) ln_delay_us(us)

// 宏定义写入高低电平
#define LCD_CS_LOW()   hal_gpio_pin_reset(LCD_CS_PORT,LCD_CS_PIN)
#define LCD_CS_HIGH()  hal_gpio_pin_set(LCD_CS_PORT,LCD_CS_PIN)
#define LCD_RS_LOW()   hal_gpio_pin_reset(LCD_RS_PORT,LCD_RS_PIN)
#define LCD_RS_HIGH()  hal_gpio_pin_set(LCD_RS_PORT,LCD_RS_PIN)
#define LCD_WR_LOW()   hal_gpio_pin_reset(GPIOB_BASE,LCD_WR_PIN)
#define LCD_WR_HIGH()  hal_gpio_pin_set(GPIOB_BASE,LCD_WR_PIN)
#define LCD_RESET_LOW() hal_gpio_pin_reset(LCD_RESET_PORT,LCD_RESET_PIN)
#define LCD_RESET_HIGH() hal_gpio_pin_set(LCD_RESET_PORT,LCD_RESET_PIN)

#define USE_HORIZONTAL 2  //设置横屏或者竖屏显示 01为竖屏 23为横屏

#define LCD_WIDTH 240
#define LCD_HEIGHT 320


/* R     G      B      */
/* 00000 000000 00000  */
//颜色定义
#define WHITE         	 0xFFFF
#define BLACK         	 0x0000	  
#define BLUE           	 0x001F  
#define BRED             0XF81F
#define GRED 			 0XFFE0
#define GBLUE			 0X07FF
#define RED           	 0xF800
#define MAGENTA       	 0xF81F
#define GREEN         	 0x07E0
#define CYAN          	 0x7FFF
#define YELLOW        	 0xFFE0
#define BROWN 			 0XBC40 
#define BRRED 			 0XFC07
#define GRAY  			 0X8430 
#define DARKBLUE      	 0X01CF
#define LIGHTBLUE      	 0X7D7C	
#define GRAYBLUE       	 0X5458 
#define LIGHTGREEN     	 0X841F 
#define LGRAY 			 0XC618 
#define LGRAYBLUE        0XA651 
#define LBBLUE           0X2B12 

//int ln_drv_spi_lcd_init(void);
//void ln_drv_spi_lcd_fill(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t *color);


void GPIO_Init_OUTPUT(uint32_t gpio_base, gpio_pin_t pin);	//设置某个引脚为推挽输出
void LCD_GPIO_Init();	//初始化GPIO函数
void LCD_TR_Writ_BIT_DATABUS(uint32_t gpio_base, gpio_pin_t pin,uint8_t val);	//判断数据01然后写入总线上
void LCD_WriteByte(uint8_t byte);	//写入一个字节8位
void LCD_WriteCommand(uint8_t cmd);	//写入命令
void LCD_WriteData(uint8_t data);	//写入数据8位
void LCD_WriteData16(uint16_t data);	//写入数据16位
void LCD_Init();	//屏幕初始化函数
void LCD_Clear(uint16_t color);	//清屏函数
void LCD_DrawPoint(uint16_t xStart, uint16_t yStart, uint16_t color);	//画点函数,在坐标(x,y)的位置画一个点
void LCD_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd);	//窗口设置函数
//填充一个颜色块
void LCD_FillBlock(uint16_t xStart, uint16_t yStart, uint16_t block_width, uint16_t block_height, uint16_t color);	
/*
在坐标(x,y)的位置,填充一个宽和高分别为block_width、block_height的图片
block_data为指向图片点阵数据的指针,图片点阵数据格式为 RGB:565
*/
void LCD_DrawPic(uint16_t xStart, uint16_t yStart, uint16_t block_width, uint16_t block_height, const uint8_t *block_data);

//微秒延时
void delay_us(uint16_t us);

#ifdef __cplusplus
}
#endif

#endif /* __LN_DRV_SPI_LCD_H__ */




#include "ST7789V_lcd.h"

//设置某个引脚为推挽输出
void GPIO_Init_OUTPUT(uint32_t gpio_base, gpio_pin_t pin){
		gpio_init_t_def gpio_init;
    memset(&gpio_init,0,sizeof(gpio_init));
		gpio_init.dir = GPIO_OUTPUT;
		gpio_init.pin = pin;
		gpio_init.speed = GPIO_HIGH_SPEED;
    hal_gpio_init(gpio_base,&gpio_init);
}

//初始化GPIO函数
void LCD_GPIO_Init() {
    //配置数据总线为输出模式
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D0_PIN);
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D1_PIN);
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D2_PIN);
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D3_PIN);
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D4_PIN);
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D5_PIN);
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D6_PIN);
		GPIO_Init_OUTPUT(LCD_DATA_PORT,LCD_D7_PIN);

    // 配置控制信号为输出模式
		GPIO_Init_OUTPUT(LCD_CS_PORT,LCD_CS_PIN);
		GPIO_Init_OUTPUT(LCD_RS_PORT,LCD_RS_PIN);
		GPIO_Init_OUTPUT(LCD_WR_PORT,LCD_WR_PIN);
//		GPIO_Init_OUTPUT(LCD_RD_PORT,LCD_RD_PIN);// 如果没有使用RD,可以忽略
		GPIO_Init_OUTPUT(LCD_RESET_PORT,LCD_RESET_PIN);

    // 默认状态
    LCD_CS_HIGH();
    LCD_RS_HIGH();
    LCD_WR_HIGH();
		LCD_RESET_HIGH();
		
}

//判断数据01然后写入总线上
void LCD_TR_Writ_BIT_DATABUS(uint32_t gpio_base, gpio_pin_t pin,uint8_t val){
	if(val){
		hal_gpio_pin_set(gpio_base,pin);
	}else{
		hal_gpio_pin_reset(gpio_base,pin);
	}
}

//写入一个字节8位
void LCD_WriteByte(uint8_t byte) {
		
		LCD_WR_HIGH();
//		delay_us(1); // 确保时序
	
    // 将字节写入总线数据
		LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D0_PIN,(byte >> 0) & 0x01);
		LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D1_PIN, (byte >> 1) & 0x01);
    LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D2_PIN, (byte >> 2) & 0x01);
    LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D3_PIN, (byte >> 3) & 0x01);
    LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D4_PIN, (byte >> 4) & 0x01);
    LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D5_PIN, (byte >> 5) & 0x01);
    LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D6_PIN, (byte >> 6) & 0x01);
    LCD_TR_Writ_BIT_DATABUS(LCD_DATA_PORT,LCD_D7_PIN, (byte >> 7) & 0x01);
		
		// 生成WR脉冲
    LCD_WR_LOW();
    delay_us(1); // 确保时序
	
    LCD_WR_HIGH();
		delay_us(1); // 确保时序
}

//写入命令
void LCD_WriteCommand(uint8_t cmd) {
    LCD_CS_LOW();
		LCD_RS_LOW(); // RS=0表示命令
    LCD_WriteByte(cmd);
    LCD_CS_HIGH();
}

//写入数据8位
void LCD_WriteData(uint8_t data) {
    LCD_CS_LOW();
		LCD_RS_HIGH(); // RS=1表示数据
    LCD_WriteByte(data);
    LCD_CS_HIGH();
}

//写入数据16位
void LCD_WriteData16(uint16_t data){
		LCD_CS_LOW();
		LCD_RS_HIGH(); // RS=1表示数据
		LCD_WriteByte(data >> 8);
    LCD_WriteByte(data);
    LCD_CS_HIGH();
}

//屏幕初始化函数
void LCD_Init(){
		//屏幕厂商
		//初始化GPIO
		LCD_GPIO_Init();

    //复位屏幕
    LCD_RESET_LOW();
    LCD_DELAY_MS(120);
    LCD_RESET_HIGH();
    LCD_DELAY_MS(120);
	
		//发送初始化命令
    LCD_WriteCommand(0x11); //退出休眠模式
    LCD_DELAY_MS(120);
	
		LCD_WriteCommand(0xB2);
		LCD_WriteData(0x0C);
		LCD_WriteData(0x0C);
		LCD_WriteData(0x00);
		LCD_WriteData(0x33);
		LCD_WriteData(0x33);
	
		LCD_WriteCommand(0x35);
		LCD_WriteData(0x00);
		
		LCD_WriteCommand(0x36);
		LCD_WriteData(0x00);
		
		LCD_WriteCommand(0x3A);
		LCD_WriteData(0x05);
		
		LCD_WriteCommand(0xB7);
		LCD_WriteData(0x06);
		
		LCD_WriteCommand(0xBB);
		LCD_WriteData(0x20);
		
		LCD_WriteCommand(0xC0);
		LCD_WriteData(0x2C);
		
		LCD_WriteCommand(0xC2);
		LCD_WriteData(0x01);
		
		LCD_WriteCommand(0xC3);
		LCD_WriteData(0x0F);
		
		LCD_WriteCommand(0xC6);
		LCD_WriteData(0x0F);
		
		LCD_WriteCommand(0xD0);
		LCD_WriteData(0xA7);
		
		LCD_WriteCommand(0xD0);
		LCD_WriteData(0xA4);
		LCD_WriteData(0xA1);
		
		LCD_WriteCommand(0xD6);
		LCD_WriteData(0xA1);
		
		LCD_WriteCommand(0xE0);
		LCD_WriteData(0xF0);
		LCD_WriteData(0x06);
		LCD_WriteData(0x0E);
		LCD_WriteData(0x08);
		LCD_WriteData(0x09);
		LCD_WriteData(0x17);
		LCD_WriteData(0x37);
		LCD_WriteData(0x54);
		LCD_WriteData(0x4C);
		LCD_WriteData(0x39);
		LCD_WriteData(0x14);
		LCD_WriteData(0x12);
		LCD_WriteData(0x2F);
		LCD_WriteData(0x34);

		LCD_WriteCommand(0xE1);
		LCD_WriteData(0xF0);
		LCD_WriteData(0x0F);
		LCD_WriteData(0x14);
		LCD_WriteData(0x0C);
		LCD_WriteData(0x0A);
		LCD_WriteData(0x04);
		LCD_WriteData(0x37);
		LCD_WriteData(0x43);
		LCD_WriteData(0x4C);
		LCD_WriteData(0x36);
		LCD_WriteData(0x12);
		LCD_WriteData(0x14);
		LCD_WriteData(0x2D);
		LCD_WriteData(0x36);
	
		LCD_WriteCommand(0x21); // 显示反转
		LCD_WriteCommand(0x29); // 开启显示
		
		LCD_WriteCommand(0x2C);
}

//清屏函数
void LCD_Clear(uint16_t color) {
//    LCD_WriteCommand(0x2A); // 设置列地址
//    LCD_WriteData(0x00);
//    LCD_WriteData(0x00);
//    LCD_WriteData(0x00);
//    LCD_WriteData(0xEF);

//    LCD_WriteCommand(0x2B); // 设置行地址
//    LCD_WriteData(0x00);
//    LCD_WriteData(0x00);
//    LCD_WriteData(0x01);
//    LCD_WriteData(0x3F);

//    LCD_WriteCommand(0x2C); // 写入RAM

	LCD_SetWindow(0,0,LCD_WIDTH-1,LCD_HEIGHT-1);
	LCD_WriteCommand(0x2C); // 进入 RAM 写入模式
    // 发送颜色数据
    LCD_CS_LOW();
		LCD_RS_HIGH();
    for (uint32_t i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) {
        LCD_WriteByte(color >> 8); // 高字节(D15-D8)
        LCD_WriteByte(color & 0xFF); // 低字节(D7-D0)
    }
    LCD_CS_HIGH();
}

//画点函数,在坐标(x,y)的位置画一个点
void LCD_DrawPoint(uint16_t xStart, uint16_t yStart, uint16_t color)
{
		LCD_WriteCommand(0x2a);
    LCD_WriteData16(xStart);
	
		LCD_WriteCommand(0x2b);
    LCD_WriteData16(yStart);
	
		LCD_WriteCommand(0x2c);
    LCD_WriteData16(color);
}

//窗口设置函数
void LCD_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd)
{
		LCD_WriteCommand(0x2a);
		LCD_WriteData16(xStart);
    LCD_WriteData16(xEnd);
	
		LCD_WriteCommand(0x2b);
    LCD_WriteData16(yStart);
    LCD_WriteData16(yEnd);
	
		LCD_WriteCommand(0x2c);
}

//填充一个颜色块
void LCD_FillBlock(uint16_t xStart, uint16_t yStart, uint16_t block_width, uint16_t block_height, uint16_t color)
{
	uint32_t i,j;
	
	LCD_SetWindow( xStart, yStart, (xStart+block_width-1), (yStart+block_height-1) );
	for(i=0;i<block_width;i++)
	{
		for(j=0;j<block_height;j++)
		{
       LCD_WriteData16(color);
		}
	}
}

/*
在坐标(x,y)的位置,填充一个宽和高分别为block_width、block_height的图片
block_data为指向图片点阵数据的指针,图片点阵数据格式为 RGB:565
*/
void LCD_DrawPic(uint16_t xStart, uint16_t yStart, uint16_t block_width, uint16_t block_height, const uint8_t *block_data)
{
	uint32_t i,j;
 
	LCD_SetWindow( xStart, yStart, (xStart+block_width-1), (yStart+block_height-1) );
    
	for(i=0;i<block_width;i++)
	{
		for(j=0;j<block_height;j++)
		{
			LCD_WriteData(*(block_data+1));
			LCD_WriteData(*block_data);
			
			block_data += 2;
		}
	}
}

//微秒延时
void delay_us(uint16_t us)
{
    uint32_t count; // ??????? __nop() ??
    //40M
    if(hal_clock_get_core_clk() == 40000000)
    {
        count = hal_clock_get_core_clk() / 40;
    }
    else
    //160M
    {
        count = hal_clock_get_core_clk() / 160;
    }
    count = count * us;

    while (count--) {
        __nop(); // ?????????
    }
}
用的是单片机是LN882H,屏幕是2寸的显示屏。显示屏是ST7789v的,8bit数据位的,我在使用8080时序去驱动屏幕的时候,屏幕一直是花屏的,小白头一次搞这个8080驱动屏幕,麻烦各位大佬给帮忙分析一下哪里的问题

花屏

花屏

ST7789V_lcd.c

7.21 KB, 下载次数: 0

ST7789V_lcd.h

3.67 KB, 下载次数: 1

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115679
QQ
发表于 2025-5-1 13:08:20 | 显示全部楼层
优先测试读ID,读取失败说明驱动问题。
回复

使用道具 举报

1

主题

2

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 4 天前 | 显示全部楼层
eric2013 发表于 2025-5-1 13:08
优先测试读ID,读取失败说明驱动问题。

感谢,已找到问题,在拉低WR写信号线写的时候,要保证RD读信号线拉高
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-5-11 18:45 , Processed in 0.343366 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表