本篇使用的驱动来自ST官方提供:
https://github.com/STMicroelectronics/stm32-st7735.git
需要的可以直接git clone下来移植,核心代码无关芯片型号,可移植性很不错!本篇用的ST7735库比官方新添加了一些内容,是开发板卖家提供的,地址:
第一篇中我们打通了SPI,读取到了芯片ID,这一篇只要完善几个接口函数就可以直接使用官方的驱动库了。至于要完善哪几个接口,需要看一下官方驱动库需要哪些函数。
可以参照我上图的结构把几个源文件添加进去,其中font.h可以在WeAct那个github上找到。
添加完后记得把头文件路径也包含进去。
在添加完成后,新建lcd相关源文件,比如我的文件结构:
修改 st7735.h 中一处地方:
这个变量在st7735.c中被定义。 怎么使用库如下:
其中ST7735Ctx是库里面定义好的,我们直接使用即可。但是还需要两个变量:
st7735_pObj就是设备驱动实例,实际在屏幕上显示都是操作的它。关键是st7735_pIO这个变量,它负责提供底层接口。它里面包含的一些函数指针正是我们需要完成的。
在上一章的基础上,使用了两套SPI使用方式,如果定义 USE_RTT_SPI ,就是用RTT驱动框架提供的SPI接口函数,如果把它注释掉,则直接使用HAL库的SPI函数,具体实现我会附在后面。
实际我们使用的时候调用的函数是:
比如要填充整个屏幕为黑色:
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-11-14 cx the first version
- */
- #include
- #include
- #include
- #include
- #include
- #include "st7735_reg.h"
- #include "st7735.h"
-
- #define USE_RTT_SPI
-
- SPI_HandleTypeDef *spi_handle;
-
- #ifdef USE_RTT_SPI
-
- static struct rt_spi_device *spi_lcd;
-
- #define LCD_RD_HIGH rt_pin_write(SPI_RD_PIN_NUM, PIN_HIGH)
- #define LCD_RD_LOW rt_pin_write(SPI_RD_PIN_NUM, PIN_LOW)
- #else
- SPI_HandleTypeDef hspi4;
- #define SPI_Drv (&hspi4)
- #define LCD_CS_HIGH HAL_GPIO_WritePin(GPIOE,GPIO_PIN_11,GPIO_PIN_SET)
- #define LCD_CS_LOW HAL_GPIO_WritePin(GPIOE,GPIO_PIN_11,GPIO_PIN_RESET)
-
- #define LCD_RD_HIGH HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_SET)
- #define LCD_RD_LOW HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET)
- #endif
-
- #ifdef USE_RTT_SPI
- int32_t mspi_send_reg(uint8_t reg,uint8_t *data,uint32_t len)
- {
- struct rt_spi_message msg;
- uint32_t remsg = RT_NULL;
- msg.send_buf = ®
- msg.recv_buf = RT_NULL;
- msg.length = 1;
- msg.cs_take = 1;
- msg.cs_release = 0;
- msg.next = RT_NULL;
- LCD_RD_LOW;
- remsg = (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
- LCD_RD_HIGH;
- if(len > 0)
- {
- msg.send_buf = data;
- msg.recv_buf = RT_NULL;
- msg.length = len;
- msg.cs_take = 0;
- msg.cs_release = 1;
- msg.next = RT_NULL;
- remsg += (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
- }
- if(remsg!=RT_NULL)
- return -1;
- else
- return 0;
- }
- int32_t mspi_read_reg(uint8_t reg,uint8_t *data)
- {
- struct rt_spi_message msg;
- uint32_t remsg = RT_NULL;
- uint8_t reg1 = reg;
- msg.send_buf = ®1;
- msg.recv_buf = RT_NULL;
- msg.length = 1;
- msg.cs_take = 1;
- msg.cs_release = 0;
- msg.next = RT_NULL;
- LCD_RD_LOW;
- remsg = (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
- LCD_RD_HIGH;
- if(remsg == 0)
- {
- msg.send_buf = RT_NULL;
- msg.recv_buf = data;
- msg.length = 1;
- msg.cs_take = 0;
- msg.cs_release = 1;
- msg.next = RT_NULL;
- remsg += (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
- }
- if(remsg!=RT_NULL)
- return -1;
- else
- return 0;
- }
- int32_t mspi_send_data(uint8_t *data,uint32_t len)
- {
- struct rt_spi_message msg;
- msg.send_buf = data;
- msg.recv_buf = RT_NULL;
- msg.length = len;
- msg.cs_take = 1;
- msg.cs_release = 1;
- msg.next = RT_NULL;
- return (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
- }
- int32_t mspi_read_data(uint8_t *data,uint32_t len)
- {
- struct rt_spi_message msg;
- msg.send_buf = RT_NULL;
- msg.recv_buf = data;
- msg.length = len;
- msg.cs_take = 1;
- msg.cs_release = 1;
- msg.next = RT_NULL;
- return (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
- }
-
- #else
- int32_t mspi_send_reg(uint8_t reg,uint8_t *data,uint32_t len)
- {
- int32_t result;
- LCD_CS_LOW;
- LCD_RD_LOW;
- result = HAL_SPI_Transmit(SPI_Drv,®,1,100);
- LCD_RD_HIGH;
- if(len > 0)
- result += HAL_SPI_Transmit(SPI_Drv,data,len,500);
- LCD_CS_HIGH;
- if(result>0){
- result = -1;}
- else{
- result = 0;}
- return result;
- }
-
- int32_t mspi_read_reg(uint8_t reg,uint8_t *data)
- {
- int32_t result;
- LCD_CS_LOW;
- LCD_RD_LOW;
-
- result = HAL_SPI_Transmit(SPI_Drv,®,1,100);
- LCD_RD_HIGH;
- result += HAL_SPI_Receive(SPI_Drv,data,1,500);
- LCD_CS_HIGH;
- if(result>0){
- result = -1;}
- else{
- result = 0;}
- return result;
- }
-
- int32_t mspi_send_data(uint8_t *data,uint32_t len)
- {
- int32_t result;
- LCD_CS_LOW;
- //LCD_RD_HIGH;
- result =HAL_SPI_Transmit(SPI_Drv,data,len,100);
- LCD_CS_HIGH;
- if(result>0){
- result = -1;}
- else{
- result = 0;}
- return result;
- }
-
- int32_t mspi_read_data(uint8_t *data,uint32_t len)
- {
- int32_t result;
- LCD_CS_LOW;
- //LCD_RD_HIGH;
- result = HAL_SPI_Receive(SPI_Drv,data,len,500);
- LCD_CS_HIGH;
- if(result>0){
- result = -1;}
- else{
- result = 0;}
- return result;
- }
- #endif
- int32_t mspi_get_tick(void)
- {
- return HAL_GetTick();
- }
- void mspi_rw_gpio_init(void)
- {
- #ifdef USE_RTT_SPI
- rt_pin_mode(SPI_RD_PIN_NUM, PIN_MODE_OUTPUT);
- rt_pin_write(SPI_RD_PIN_NUM, PIN_HIGH);
- #else
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- __HAL_RCC_GPIOE_CLK_ENABLE();
- HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11|GPIO_PIN_13, GPIO_PIN_SET);
- GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
- #endif
- }
- void mspi_init(void)
- {
- mspi_rw_gpio_init();
- #ifdef USE_RTT_SPI
- struct rt_spi_configuration cfg;
- rt_hw_spi_device_attach("spi4", "spi40", GPIOE, GPIO_PIN_11);
- spi_lcd = (struct rt_spi_device *)rt_device_find("spi40");
- if(!spi_lcd)
- {
- rt_kprintf("spi40 can't find\n");
- }
- else
- {
- spi_lcd->bus->owner = spi_lcd;
- cfg.data_width = 8;
- cfg.mode = RT_SPI_MASTER | RT_SPI_3WIRE | RT_SPI_MODE_0 | RT_SPI_MSB;
- cfg.max_hz = 12.5 * 1000 * 1000;
- rt_spi_configure(spi_lcd, &cfg);
- }
- //也可以初始化使用框架提供的函数,发送接收使用HAL库函数,操作对象就是下面的 spi_handle
- // struct stm32_spi *spi_drv = rt_container_of(spi_lcd->bus, struct stm32_spi, spi_bus);
- // spi_handle = &spi_drv->handle;
- #else
- hspi4.Instance = SPI4;
- hspi4.Init.Mode = SPI_MODE_MASTER;
- hspi4.Init.Direction = SPI_DIRECTION_1LINE;
- hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
- hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
- hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
- hspi4.Init.NSS = SPI_NSS_SOFT;
- hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
- hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
- hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
- hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
- hspi4.Init.CRCPolynomial = 0x0;
- hspi4.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
- hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
- hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
- hspi4.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
- hspi4.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
- hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
- hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
- hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
- hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
- hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
- if (HAL_SPI_Init(&hspi4) != HAL_OK)
- {
- rt_kprintf("ERROR\n");
- }
- #endif
- }
-
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-11-15 cx the first version
- */
- #include
- #include
- #include
- #define DBG_TAG "mlcd"
- #define DBG_LVL DBG_LOG
- #include
- #include "mpwm.h"
- #include "mspi.h"
- #include "st7735_reg.h"
- #include "st7735.h"
- #include "mlcd.h"
- #include "font.h"
- #include
-
- int32_t mlcd_st7735_init(void);
-
- ST7735_IO_t st7735_pIO = {
- mlcd_st7735_init,
- NULL,
- 0,
- mspi_send_reg,
- mspi_read_reg,
- mspi_send_data,
- mspi_read_data,
- mspi_get_tick
- };
-
- ST7735_Object_t st7735_pObj;
-
- int32_t mlcd_st7735_init(void)
- {
- int32_t result = ST7735_OK;
- mpwm_init();
- mspi_init();
- return result;
- }
-
- int mlcd_init(void)
- {
- uint32_t st7735_id;
- uint8_t text[50];
- #ifdef TFT96
- ST7735Ctx.Orientation = ST7735_ORIENTATION_LANDSCAPE_ROT180;
- ST7735Ctx.Panel = HannStar_Panel;
- ST7735Ctx.Type = ST7735_0_9_inch_screen;
- #elif TFT18
- ST7735Ctx.Orientation = ST7735_ORIENTATION_PORTRAIT;
- ST7735Ctx.Panel = BOE_Panel;
- ST7735Ctx.Type = ST7735_1_8_inch_screen;
- #else
- LOG_E("Unknown Screen");
- #endif
- ST7735_RegisterBusIO(&st7735_pObj,&st7735_pIO);
- ST7735_LCD_Driver.Init(&st7735_pObj,ST7735_FORMAT_RBG565,&ST7735Ctx);
- ST7735_LCD_Driver.ReadID(&st7735_pObj,&st7735_id);
- rt_kprintf("LCD ID:%08X\n",st7735_id);
-
- ST7735_LCD_Driver.FillRect(&st7735_pObj, 0, 0, ST7735Ctx.Width,ST7735Ctx.Height, BLACK);
-
- sprintf((char *)&text, "Something V1.0");
- LCD_ShowString(4, 4, ST7735Ctx.Width, 16, 16, text);
-
- return 0;
- }
-
- uint16_t POINT_COLOR=0xFFFF; //画笔颜色
- uint16_t BACK_COLOR=BLACK; //背景色
- //在指定位置显示一个字符
- //x,y:起始坐标
- //num:要显示的字符:" "--->"~"
- //size:字体大小 12/16
- //mode:叠加方式(1)还是非叠加方式(0)
-
- void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint8_t size,uint8_t mode)
- {
- uint8_t temp,t1,t;
- uint16_t y0=y;
- uint16_t x0=x;
- uint16_t colortemp=POINT_COLOR;
- uint32_t h,w;
-
- uint16_t write[size][size==12?6:8];
- uint16_t count;
-
- ST7735_GetXSize(&st7735_pObj,&w);
- ST7735_GetYSize(&st7735_pObj,&h);
-
- //设置窗口
- num=num-' ';//得到偏移后的值
- count = 0;
-
- if(!mode) //非叠加方式
- {
- for(t=0;t
- {
- if(size==12)temp=asc2_1206[num][t]; //调用1206字体
- else temp=asc2_1608[num][t]; //调用1608字体
-
- for(t1=0;t1<8;t1++)
- {
- if(temp&0x80)
- POINT_COLOR=(colortemp&0xFF)<<8|colortemp>>8;
- else
- POINT_COLOR=(BACK_COLOR&0xFF)<<8|BACK_COLOR>>8;
-
- write[count][t/2]=POINT_COLOR;
- count ++;
- if(count >= size) count =0;
-
- temp<<=1;
- y++;
- if(y>=h){POINT_COLOR=colortemp;return;}//超区域了
- if((y-y0)==size)
- {
- y=y0;
- x++;
- if(x>=w){POINT_COLOR=colortemp;return;}//超区域了
- break;
- }
- }
- }
- }
- else//叠加方式
- {
- for(t=0;t
- {
- if(size==12)temp=asc2_1206[num][t]; //调用1206字体
- else temp=asc2_1608[num][t]; //调用1608字体
- for(t1=0;t1<8;t1++)
- {
- if(temp&0x80)
- write[count][t/2]=(POINT_COLOR&0xFF)<<8|POINT_COLOR>>8;
- count ++;
- if(count >= size) count =0;
-
- temp<<=1;
- y++;
- if(y>=h){POINT_COLOR=colortemp;return;}//超区域了
- if((y-y0)==size)
- {
- y=y0;
- x++;
- if(x>=w){POINT_COLOR=colortemp;return;}//超区域了
- break;
- }
- }
- }
- }
- ST7735_FillRGBRect(&st7735_pObj,x0,y0,(uint8_t *)&write,size==12?6:8,size);
- POINT_COLOR=colortemp;
- }
-
- //显示字符串
- //x,y:起点坐标
- //width,height:区域大小
- //size:字体大小
- //*p:字符串起始地址
- void LCD_ShowString(uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint8_t size,uint8_t *p)
- {
- uint8_t x0=x;
- width+=x;
- height+=y;
- while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
- {
- if(x>=width){x=x0;y+=size;}
- if(y>=height)break;//退出
- LCD_ShowChar(x,y,*p,size,0);
- x+=size/2;
- p++;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
相关阅读:
系统架构设计师-第13章-层次式架构设计理论与实践-软考学习笔记
题目 1074: 数字整除
qml保姆级教程四:按钮组件
高优先线程
Laravel Routes Group-Prefix 使用变量问题
AI模型精确解析果蝇行为,未来或可预测人类行为
JaVers:自动化数据审计
Java阻塞队列中的异类,SynchronousQueue底层实现原理剖析
Java集合知识点
android 解决AVC问题
-
原文地址:https://blog.csdn.net/qwe5959798/article/details/127924308