721|3

224

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

【ACM32G103RCT6】4-点亮1.8寸RGB_TFT屏幕 [复制链接]

 
本帖最后由 qiao--- 于 2024-1-7 20:57 编辑

我这次的测评点亮这个屏幕用了两种方法,一种是硬件spi驱动屏幕一种是用软件驱动屏幕。而软硬件驱动切换用了条件编译的方法切换。首先给大家展示一下我的屏幕

 

 

对于驱动屏幕熟悉的贴友,应该知道,驱动一个屏幕首先要实现向屏幕写一个字节的数据的函数,只要这个底层做好了,其余的直接移植屏幕出厂方的代码就行了。

1.初始化硬件并编写写一个字节数据的函数

#include "st7735.h"
SPI_HandleTypeDef SPI_Handle;
DMA_HandleTypeDef DMA_SPIT_Handle;

void SPI_GPIO_Init(void){
				GPIO_InitTypeDef GPIO_Handle = {0}; 
				/* Enable Clock */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        
        /*  PA4    CS       
            PA5    SCK           
            PA12   MOSI      
            PA11   RST
            PA7    DC
            PA6    BLK
        */
#if SOFT       
        GPIO_Handle.Pin = GPIO_PIN_4 | GPIO_PIN_11 | GPIO_PIN_6 |GPIO_PIN_7 |GPIO_PIN_12 |GPIO_PIN_5;
#else
				GPIO_Handle.Pin = GPIO_PIN_4 | GPIO_PIN_11 | GPIO_PIN_6 |GPIO_PIN_7 ;
#endif
        GPIO_Handle.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_Handle.Pull = GPIO_NOPULL;
        GPIO_Handle.Drive = GPIO_DRIVE_LEVEL3;
        GPIO_Handle.Alternate = GPIO_FUNCTION_0;
        HAL_GPIO_Init(GPIOA, &GPIO_Handle);
				LCD_CS_HIGH();
}
#if SOFT 
//向SPI总线传输一个8位数据
void  SPI_WriteData(uint8_t Data)
{
	unsigned char i=0;
	for(i=8;i>0;i--)
	{
		if(Data&0x80)	
	  LCD_SDA_HIGH(); //输出数据
      else LCD_SDA_LOW();
			LCD_SCK_HIGH();
      LCD_SCK_LOW();             
      Data<<=1; 
	}
}
#else
void SPI_Init(void){
		SPI_GPIO_Init();
		SPI_Handle.Instance                 = SPI1;
    SPI_Handle.Init.SPI_Mode            = SPI_MODE_MASTER;
    SPI_Handle.Init.SPI_Work_Mode       = SPI_WORK_MODE_0;
    SPI_Handle.Init.X_Mode              = SPI_1X_MODE;
    SPI_Handle.Init.First_Bit           = SPI_FIRSTBIT_MSB;
    SPI_Handle.Init.BaudRate_Prescaler  = SPI_BAUDRATE_PRESCALER_64;

    HAL_SPI_Init(&SPI_Handle);
}
#endif




//向液晶屏写一个8位指令
void Lcd_WriteIndex(uint8_t Index)
{

   //SPI 写命令时序开始
   LCD_CS_LOW();
   LCD_DC_LOW();
#if SOFT	 
	 SPI_WriteData(Index);
#else
	HAL_SPI_Transmit(&SPI_Handle,&Index,1,HAL_MAX_DELAY);
#endif
   LCD_CS_HIGH();
}

2.实现写一个像素的函数。因为我这里用的是RGB565的数据格式,所以写一个像素的数据是写进两个字节,这里可以引用我们写一个字节的函数。

//向液晶屏写一个16位数据
void LCD_WriteData_16Bit(uint16_t Data)
{
		uint8_t tmp_1 = Data >>8;
		uint8_t tmp_2 = Data;
   LCD_CS_LOW();
   LCD_DC_HIGH();
#if SOFT	 
	 SPI_WriteData(tmp_1);
	 SPI_WriteData(tmp_2);
#else
	HAL_SPI_Transmit(&SPI_Handle,&tmp_1,1,HAL_MAX_DELAY);
	HAL_SPI_Transmit(&SPI_Handle,&tmp_2,1,HAL_MAX_DELAY);
#endif
   LCD_CS_HIGH();
}

3.修改屏幕官方的代码。上面实现好了后,我们可以把屏幕官方的代码的相关写数据的函数名改成我们自己编写的就OK了。有需要的贴友可以看下放的附件,工程已给出。

驱动部分整体代码如下

#include "st7735.h"
SPI_HandleTypeDef SPI_Handle;
DMA_HandleTypeDef DMA_SPIT_Handle;

void SPI_GPIO_Init(void){
				GPIO_InitTypeDef GPIO_Handle = {0}; 
				/* Enable Clock */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        
        /*  PA4    CS       
            PA5    SCK           
            PA12   MOSI      
            PA11   RST
            PA7    DC
            PA6    BLK
        */
#if SOFT       
        GPIO_Handle.Pin = GPIO_PIN_4 | GPIO_PIN_11 | GPIO_PIN_6 |GPIO_PIN_7 |GPIO_PIN_12 |GPIO_PIN_5;
#else
				GPIO_Handle.Pin = GPIO_PIN_4 | GPIO_PIN_11 | GPIO_PIN_6 |GPIO_PIN_7 ;
#endif
        GPIO_Handle.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_Handle.Pull = GPIO_NOPULL;
        GPIO_Handle.Drive = GPIO_DRIVE_LEVEL3;
        GPIO_Handle.Alternate = GPIO_FUNCTION_0;
        HAL_GPIO_Init(GPIOA, &GPIO_Handle);
				LCD_CS_HIGH();
}


void DMA_SPITransmit_Init(void)
{
    __HAL_RCC_DMA2_CLK_ENABLE();
    
    DMA_SPIT_Handle.Instance            = DMA2_Channel1;
    DMA_SPIT_Handle.Init.DataFlow       = DMA_DATAFLOW_M2P;
    DMA_SPIT_Handle.Init.ReqID          = DMA2_REQ47_SPI3_SEND;
    DMA_SPIT_Handle.Init.SrcInc         = DMA_SRCINC_ENABLE;
    DMA_SPIT_Handle.Init.DestInc        = DMA_DESTINC_DISABLE;
    DMA_SPIT_Handle.Init.SrcWidth       = DMA_SRCWIDTH_BYTE;
    DMA_SPIT_Handle.Init.DestWidth      = DMA_DESTWIDTH_BYTE;

    /*-----------------------------------------------------------------------------------*/
    /* Note:If user dons not apply interrupt, Set DMA_ITC_Callback?¢DMA_IE_Callback NULL */
    /*-----------------------------------------------------------------------------------*/
    DMA_SPIT_Handle.XferCpltCallback = NULL;
    DMA_SPIT_Handle.XferErrorCallback  = NULL;

    HAL_DMA_Init(&DMA_SPIT_Handle);
    
    SPI_Handle.HDMA_Tx = &DMA_SPIT_Handle;
}




#if SOFT 
//向SPI总线传输一个8位数据
void  SPI_WriteData(uint8_t Data)
{
	unsigned char i=0;
	for(i=8;i>0;i--)
	{
		if(Data&0x80)	
	  LCD_SDA_HIGH(); //输出数据
      else LCD_SDA_LOW();
			LCD_SCK_HIGH();
      LCD_SCK_LOW();             
      Data<<=1; 
	}
}
#else
void SPI_Init(void){
		SPI_GPIO_Init();
		SPI_Handle.Instance                 = SPI1;
    SPI_Handle.Init.SPI_Mode            = SPI_MODE_MASTER;
    SPI_Handle.Init.SPI_Work_Mode       = SPI_WORK_MODE_0;
    SPI_Handle.Init.X_Mode              = SPI_1X_MODE;
    SPI_Handle.Init.First_Bit           = SPI_FIRSTBIT_MSB;
    SPI_Handle.Init.BaudRate_Prescaler  = SPI_BAUDRATE_PRESCALER_64;

    HAL_SPI_Init(&SPI_Handle);
}
#endif




//向液晶屏写一个8位指令
void Lcd_WriteIndex(uint8_t Index)
{

   //SPI 写命令时序开始
   LCD_CS_LOW();
   LCD_DC_LOW();
#if SOFT	 
	 SPI_WriteData(Index);
#else
	HAL_SPI_Transmit(&SPI_Handle,&Index,1,HAL_MAX_DELAY);
#endif
   LCD_CS_HIGH();
}



//向液晶屏写一个8位数据
void Lcd_WriteData(uint8_t Index)
{
   LCD_CS_LOW();
   LCD_DC_HIGH();
#if SOFT	 
	 SPI_WriteData(Index);
#else
	HAL_SPI_Transmit(&SPI_Handle,&Index,1,HAL_MAX_DELAY);
#endif
   LCD_CS_HIGH();
}
//向液晶屏写一个16位数据
void LCD_WriteData_16Bit(uint16_t Data)
{
		uint8_t tmp_1 = Data >>8;
		uint8_t tmp_2 = Data;
   LCD_CS_LOW();
   LCD_DC_HIGH();
#if SOFT	 
	 SPI_WriteData(tmp_1);
	 SPI_WriteData(tmp_2);
#else
	HAL_SPI_Transmit(&SPI_Handle,&tmp_1,1,HAL_MAX_DELAY);
	HAL_SPI_Transmit(&SPI_Handle,&tmp_2,1,HAL_MAX_DELAY);
#endif
   LCD_CS_HIGH();
}

void Lcd_WriteReg(uint8_t Index,uint8_t Data)
{
	Lcd_WriteIndex(Index);
  Lcd_WriteData(Data);
}

void Lcd_Reset(void)
{
	LCD_RST_LOW();
	HAL_Delay(100);
	LCD_RST_HIGH();
	HAL_Delay(100);
}

void Lcd_Init(void)
{	
#if SOFT
	SPI_GPIO_Init();
#else
	SPI_Init();
#endif
	Lcd_Reset(); //Reset before LCD Init.

	//LCD Init For 1.44Inch LCD Panel with ST7735R.
	Lcd_WriteIndex(0x11);//Sleep exit 
	HAL_Delay (120);
		
	//ST7735R Frame Rate
	Lcd_WriteIndex(0xB1); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 

	Lcd_WriteIndex(0xB2); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 

	Lcd_WriteIndex(0xB3); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 
	
	Lcd_WriteIndex(0xB4); //Column inversion 
	Lcd_WriteData(0x07); 
	
	//ST7735R Power Sequence
	Lcd_WriteIndex(0xC0); 
	Lcd_WriteData(0xA2); 
	Lcd_WriteData(0x02); 
	Lcd_WriteData(0x84); 
	Lcd_WriteIndex(0xC1); 
	Lcd_WriteData(0xC5); 

	Lcd_WriteIndex(0xC2); 
	Lcd_WriteData(0x0A); 
	Lcd_WriteData(0x00); 

	Lcd_WriteIndex(0xC3); 
	Lcd_WriteData(0x8A); 
	Lcd_WriteData(0x2A); 
	Lcd_WriteIndex(0xC4); 
	Lcd_WriteData(0x8A); 
	Lcd_WriteData(0xEE); 
	
	Lcd_WriteIndex(0xC5); //VCOM 
	Lcd_WriteData(0x0E); 
	
	Lcd_WriteIndex(0x36); //MX, MY, RGB mode 
	Lcd_WriteData(0xC0); 
	
	//ST7735R Gamma Sequence
	Lcd_WriteIndex(0xe0); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x1a); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x18); 
	Lcd_WriteData(0x2f); 
	Lcd_WriteData(0x28); 
	Lcd_WriteData(0x20); 
	Lcd_WriteData(0x22); 
	Lcd_WriteData(0x1f); 
	Lcd_WriteData(0x1b); 
	Lcd_WriteData(0x23); 
	Lcd_WriteData(0x37); 
	Lcd_WriteData(0x00); 	
	Lcd_WriteData(0x07); 
	Lcd_WriteData(0x02); 
	Lcd_WriteData(0x10); 

	Lcd_WriteIndex(0xe1); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x1b); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x17); 
	Lcd_WriteData(0x33); 
	Lcd_WriteData(0x2c); 
	Lcd_WriteData(0x29); 
	Lcd_WriteData(0x2e); 
	Lcd_WriteData(0x30); 
	Lcd_WriteData(0x30); 
	Lcd_WriteData(0x39); 
	Lcd_WriteData(0x3f); 
	Lcd_WriteData(0x00); 
	Lcd_WriteData(0x07); 
	Lcd_WriteData(0x03); 
	Lcd_WriteData(0x10);  
	
	Lcd_WriteIndex(0x2a);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x7f);

	Lcd_WriteIndex(0x2b);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x9f);
	
	Lcd_WriteIndex(0xF0); //Enable test command  
	Lcd_WriteData(0x01); 
	Lcd_WriteIndex(0xF6); //Disable ram power save mode 
	Lcd_WriteData(0x00); 
	
	Lcd_WriteIndex(0x3A); //65k mode 
	Lcd_WriteData(0x05); 
	
	
	Lcd_WriteIndex(0x29);//Display on	 
}

/*************************************************
函数名:LCD_Set_Region
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:xy起点和终点
返回值:无
*************************************************/
void Lcd_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end)
{		
	Lcd_WriteIndex(0x2a);
	Lcd_WriteData(0x00);
	Lcd_WriteData(x_start);//Lcd_WriteData(x_start+2);
	Lcd_WriteData(0x00);
	Lcd_WriteData(x_end+2);

	Lcd_WriteIndex(0x2b);
	Lcd_WriteData(0x00);
	Lcd_WriteData(y_start+0);
	Lcd_WriteData(0x00);
	Lcd_WriteData(y_end+1);
	
	Lcd_WriteIndex(0x2c);

}

/*************************************************
函数名:LCD_Set_XY
功能:设置lcd显示起始点
入口参数:xy坐标
返回值:无
*************************************************/
void Lcd_SetXY(uint16_t x,uint16_t y)
{
  	Lcd_SetRegion(x,y,x,y);
}

	
/*************************************************
函数名:LCD_DrawPoint
功能:画一个点
入口参数:无
返回值:无
*************************************************/
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data)
{
	Lcd_SetRegion(x,y,x+1,y+1);
	LCD_WriteData_16Bit(Data);

}    

/*****************************************
 函数功能:读TFT某一点的颜色                          
 出口参数:color  点颜色值                                 
******************************************/
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y)
{
  unsigned int Data;
  Lcd_SetXY(x,y);

  //Lcd_ReadData();//丢掉无用字节
  //Data=Lcd_ReadData();
  Lcd_WriteData(Data);
  return Data;
}
/*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色COLOR
返回值:无
*************************************************/
void Lcd_Clear(uint16_t Color)               
{	
   unsigned int i,m;
   Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
   Lcd_WriteIndex(0x2C);
   for(i=0;i<X_MAX_PIXEL;i++)
    for(m=0;m<Y_MAX_PIXEL;m++)
    {	
	  	LCD_WriteData_16Bit(Color);
    }   
}

4.移植字库。

我们把屏幕原厂的字库移植到我们工程里,同时也要移植显示这些字库的函数文件。我的相关代码放在路径App\tft7735下面。

 

5.测试。

代码下进板子后我们上电看一下效果。

IMG_8161


 

 

总结:通过硬件SPI或者软件模拟时序可以成功的驱动1.8寸RGB_TFT液晶屏。

RGB_TFT.7z (1.15 MB, 下载次数: 1, 售价: 1 分芯积分)

 

最新回复

软件相比硬件,他们差距大吗?看您的视频,刷一屏还是挺快的呀。  详情 回复 发表于 2024-1-8 08:41
点赞 关注
 
 

回复
举报

6587

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

就结果看,直接移植屏幕出厂方的代码是成功的

 
 
 

回复

6841

帖子

11

TA的资源

版主

板凳
 
软件相比硬件,他们差距大吗?看您的视频,刷一屏还是挺快的呀。

点评

差距不大,用DMA+SPI应该就可以看出差距了  详情 回复 发表于 2024-1-8 18:04
 
 
 

回复

224

帖子

0

TA的资源

一粒金砂(高级)

4
 
lugl4313820 发表于 2024-1-8 08:41 软件相比硬件,他们差距大吗?看您的视频,刷一屏还是挺快的呀。

差距不大,用DMA+SPI应该就可以看出差距了


 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
《DSP集成开发环境CCS开发指南》下载

《DSP集成开发环境CCS开发指南》下载

单片机编程讨论

1. C语言和汇编语言在开发单片机时各有哪些优缺点? 答:汇编语言是一种用文字助记符来表示机器指令的符号语言,是最接近机器码 ...

FFT算法的实现

关于FFT算法全国大学生电子设计竞赛连续出了两年了,07年的音频信号分析仪,09年的音频均衡器也可以用FFT去做.国内的学生最不擅长 ...

我的F28035的SPI控制ADS8332程序

本帖最后由 dontium 于 2015-1-23 11:07 编辑 对ADS8332用了两种方法控制,端口模拟SPI及SPI控制器。使用宏SPI_INTEFACE来控 ...

TI Cortex MCU工业安全应用

502213502214

物联网APP开发:物联网APP软件开发需要注意什么?

物联网作为如今的发展趋势,许多企业开始把关注点放到物联网这块大蛋糕上,想要在物联网开发上有所成绩,则需要作出高质量、可延 ...

【RISC-V MCU CH32V103测评】- 8:COMTransmit - 串口调试工具

本帖最后由 MianQi 于 2021-3-9 19:25 编辑 这次的测试内容是:《按键控制LED灯》 - https://bbs.21ic.com/icview-3073806-1- ...

【i.MX6ULL】驱动开发7——按键输入捕获

本帖最后由 DDZZ669 于 2021-11-9 00:04 编辑 前面几篇文章,从最基础的寄存器点灯,到设备树点灯,再到GPIO子系统点灯, ...

BMS电池管理系统中的磁性元件

在节能减碳的大背景下,全球能源结构正在发生深刻的变化,其中一个重要的标志就是,以锂离子电池(以下简称锂电池)为代表的储能 ...

与电路无任何连接的死铜会造成EMI问题吗?

我们都知道,在PCB上那些一端接了电路,另一端悬空的铜箔有可能会造成EMI辐射问题。 但是如果有一条铜箔是和电路没有任何连接的 ...

关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表