SPI3+DMA外设驱动-TFTLCD初始化
前言
(1)本系列是基于STM32的项目笔记,内容涵盖了STM32各种外设的使用,由浅入深。
(2)小编使用的单片机是STM32F105RCT6,项目笔记基于小编的实际项目,但是博客中的内容适用于各种单片机开发的同学学习和使用。
学习目标
本章有五个任务:
- 了解关于TFTLCD液晶屏的硬件接口
- 学习和了解STM32 DMA驱动
- TFTLCD液晶屏的硬件接口初始化
- LCD液晶初始化
- TFTLCD液晶屏代码移植和显示测试
TFTLCD液晶屏硬件电路分析
接口说明:TFTLCD液晶屏是连接到了单片机的SPI3接口。
TFTDIO ---- PB5 SPI3-MOSI 数据发送管脚 SPI硬件控制
TFTCMD---- PB4 SPI3-MISO 数据/指令控制脚
TFTCLK ----- PB3 SPI3-SCK 数据发送时钟脚 SPI硬件控制
CS ------PB6 片选脚位
LEDA_EN— PC10 LCD屏背光控制脚
FTFRES — PA15 LCD复位脚
电路设计说明:
● 硬件电路设计是参考液晶屏官方给的参考资料设计的。基本是按照芯片资料照抄过来即可
● 为了提高液晶屏的刷屏效率,我们选择了SPI3接口。采用单线模式
● DIO CLK 必须固定连接 MOSI SCK ,其他管脚可以连任意IO口
TFTLCD液晶屏初始化
hal_tftlcd.c 代码
#include "hal_tftlcd.h"
#include "stm32F10x.h"
//#include "lcd_font.h"//-----------------LCD端口定义----------------
#define LCD_SCLK_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_3)//SCL=SCLK
#define LCD_SCLK_Set() GPIO_SetBits(GPIOB,GPIO_Pin_3)#define LCD_MOSI_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_5)//SDA=MOSI
#define LCD_MOSI_Set() GPIO_SetBits(GPIOB,GPIO_Pin_5)#define LCD_DC_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_4)//DC
#define LCD_DC_Set() GPIO_SetBits(GPIOB,GPIO_Pin_4)#define LCD_CS_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_6)//CS
#define LCD_CS_Set() GPIO_SetBits(GPIOB,GPIO_Pin_6)#define LCD_RES_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_15)//RES
#define LCD_RES_Set() GPIO_SetBits(GPIOA,GPIO_Pin_15)#define LCD_BLK_Clr() GPIO_ResetBits(GPIOC,GPIO_Pin_10)//BLK
#define LCD_BLK_Set() GPIO_SetBits(GPIOC,GPIO_Pin_10)void hal_tftlcdConfig(void)
{SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;DMA_InitTypeDef DMA_InitStructure;//DMA初始化结构体RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //相关IO的初始化GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//RES-PA15GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOAGPIO_SetBits(GPIOA,GPIO_Pin_15);//CMD-PB4//CS-PB6GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOA GPIO_SetBits(GPIOB,GPIO_Pin_4|GPIO_Pin_6);//BLK-PC10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOA GPIO_ResetBits(GPIOC,GPIO_Pin_10);//CLK-PB3//MOSI-PB5GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 |GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure); /* SPI3 configuration */ SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; //SPI1设置为单线SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI1为主模式SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行时钟在不操作时,时钟为高电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第二个时钟沿开始采样数据SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由软件(使用SSI位)管理SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //定义波特率预分频的值:波特率预分频值为8SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式SPI_Init(SPI3, &SPI_InitStructure);//使能DMA发送DMA_DeInit(DMA2_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI3->DR; //数据传输目标地址//数据缓存地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //外设作为数据传输的目的地DMA_InitStructure.DMA_BufferSize = 1024; //发送Buff数据大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置外设地址是否递增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置内存地址是否递增DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度为8位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度为8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //普通缓存模式DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //高优先级DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止DMA2个内存相互访问DMA_Init(DMA2_Channel2, &DMA_InitStructure); //初始化DMA,SPI在DMA1的通道2SPI_I2S_DMACmd(SPI3,SPI_I2S_DMAReq_Tx,ENABLE); /使能SPI2 DMA发送功能*/ SPI_Cmd(SPI3, ENABLE);//使能SPI2
}// SPI3 DMA发送
void DMA_SPI3_TX(unsigned char *buffer,unsigned short len)
{DMA2->IFCR |=(0xf<<4); //清除通道2上面所有的标志位DMA2_Channel2->CNDTR=len; //设置要传输的数据长度DMA2_Channel2->CMAR=(u32)buffer; //设置RAM缓冲区地址DMA2_Channel2->CCR|=0x1; ///启动DMAwhile(!(DMA2->ISR&(1<<5)));///等待数据数据传输完成DMA2_Channel2->CCR &=(uint32_t)~0x1;//关闭DMA
}void LCD_Writ_Bus(unsigned char dat)
{ LCD_CS_Clr();DMA_SPI3_TX(&dat,1);
}/******************************************************************************函数说明:LCD写入数据入口数据:dat 写入的数据返回值: 无
******************************************************************************/
void LCD_WR_DATA8(unsigned char dat)
{LCD_Writ_Bus(dat);
}/******************************************************************************函数说明:LCD写入数据入口数据:dat 写入的数据返回值: 无
******************************************************************************/
void LCD_WR_DATA(unsigned short dat)
{unsigned char d[2];d[0] = dat>>8;d[1] = dat;DMA_SPI3_TX(&d[0],2);
}/******************************************************************************函数说明:LCD写入命令入口数据:dat 写入的命令返回值: 无
******************************************************************************/
void LCD_WR_REG(unsigned char dat)
{LCD_DC_Clr();//写命令LCD_Writ_Bus(dat);LCD_DC_Set();//写数据
}void hal_Oled_Display_on(void)
{LCD_BLK_Set();
}void hal_Oled_Display_off(void)
{LCD_BLK_Clr();
}
///void hal_oled_RestH(void)
{LCD_RES_Set();
}
void hal_oled_RestL(void)
{LCD_RES_Clr();
}
hal_tftlcd.h 代码
#ifndef ____HAL_TFTLCD_H_
#define ____HAL_TFTLCD_H_void hal_tftlcdConfig(void);void LCD_WR_REG(unsigned char dat);
void LCD_WR_DATA8(unsigned char dat);
void LCD_WR_DATA(unsigned short dat);
void DMA_SPI3_TX(unsigned char *buffer,unsigned short len);void hal_Oled_Display_on(void);
void hal_Oled_Display_off(void);
void hal_oled_RestH(void);
void hal_oled_RestL(void);
#endif
代码分析
hal_tftlcd.c 包括
● TFTLCD液晶屏通讯接口初始化
● TFTLCD通过DMA数据发送函数
● TFTLCD液晶屏其他端口控制函数
TFTLCD SP3接口初始化流程
➢ 定义TFTLCD通讯的接口
//-----------------LCD端口定义----------------
#define LCD_SCLK_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_3)//SCL=SCLK
#define LCD_SCLK_Set() GPIO_SetBits(GPIOB,GPIO_Pin_3)#define LCD_MOSI_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_5)//SDA=MOSI
#define LCD_MOSI_Set() GPIO_SetBits(GPIOB,GPIO_Pin_5)#define LCD_DC_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_4)//DC
#define LCD_DC_Set() GPIO_SetBits(GPIOB,GPIO_Pin_4)#define LCD_CS_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_6)//CS
#define LCD_CS_Set() GPIO_SetBits(GPIOB,GPIO_Pin_6)#define LCD_RES_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_15)//RES
#define LCD_RES_Set() GPIO_SetBits(GPIOA,GPIO_Pin_15)#define LCD_BLK_Clr() GPIO_ResetBits(GPIOC,GPIO_Pin_10)//BLK
#define LCD_BLK_Set() GPIO_SetBits(GPIOC,GPIO_Pin_10)
➢ 打开相关时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); //相关IO的初始化GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//打开端口重映射,PB3、PB4端口默认的功能不是SPI3,是JTAG,所以要对端口重映射,让它们具备SPI3的功能
➢ 初始化TFTLCD 液晶屏 和SPI3相关的GPIO口
//CMD-PB4//CS-PB6GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOA GPIO_SetBits(GPIOB,GPIO_Pin_4|GPIO_Pin_6);//BLK-PC10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOA GPIO_ResetBits(GPIOC,GPIO_Pin_10);//CLK-PB3//MOSI-PB5GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 |GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);
➢ 初始化SPI3相关参数
/* SPI3 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; //SPI1设置为单线
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI1为主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行时钟在不操作时,时钟为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //第二个时钟沿开始采样数据
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由软件(使用SSI位)管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //定义波特率预分频的值:波特率预分频值为8
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI3, &SPI_InitStructure);
➢ 配置SPI3 DMA功能。
DMA介绍:
直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。
总之,当我们的功能中涉及数据传输功能时,例如ADC、DMA、USART等,为了使数据传输更快,可以在数据传输中加上DMA功能,使能DMA发送或接收。
DMA1 各个通道对应表:
DMA2 各个通道对应表:
我们项目用到是DMA2的发送功能,因为我们只需要对TFTLCD显示屏发送数据。
//使能DMA发送
DMA_DeInit(DMA2_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI3->DR; //数据传输目标地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; 数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = 1024; //发送Buff数据大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置外设地址是否递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置内存地址是否递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度为8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //普通缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止DMA2个内存相互访问
DMA_Init(DMA2_Channel2, &DMA_InitStructure); //初始化DMA,SPI在DMA1的通道2SPI_I2S_DMACmd(SPI3,SPI_I2S_DMAReq_Tx,ENABLE); /使能SPI2 DMA发送功能*/
SPI_Cmd(SPI3, ENABLE);//使能SPI2
SPI3 DMA 数据发送函数
// SPI3 DMA发送
void DMA_SPI3_TX(unsigned char *buffer,unsigned short len)
{DMA2->IFCR |=(0xf<<4); //清除通道2上面所有的标志位DMA2_Channel2->CNDTR=len; //设置要传输的数据长度DMA2_Channel2->CMAR=(u32)buffer; //设置RAM缓冲区地址DMA2_Channel2->CCR|=0x1; ///启动DMAwhile(!(DMA2->ISR&(1<<5))) ; ///等待数据数据传输完成DMA2_Channel2->CCR &=(uint32_t)~0x1;//关闭DMA
}
void LCD_Writ_Bus(unsigned char dat)
{ LCD_CS_Clr();DMA_SPI3_TX(&dat,1);
}
其他LCD脚位控制函数
void hal_Oled_Display_on(void)
{LCD_BLK_Set();
}void hal_Oled_Display_off(void)
{LCD_BLK_Clr();
}void hal_oled_RestH(void)
{LCD_RES_Set();
}
void hal_oled_RestL(void)
{LCD_RES_Clr();
}
LCD指令和数据发送函数
/******************************************************************************函数说明:LCD写入数据入口数据:dat 写入的数据返回值: 无
******************************************************************************/
void LCD_WR_DATA8(unsigned char dat)
{DMA_SPI3_TX(dat);
}/******************************************************************************函数说明:LCD写入数据入口数据:dat 写入的数据返回值: 无
******************************************************************************/
void LCD_WR_DATA(unsigned short dat)
{unsigned char d[2];d[0] = dat>>8;d[1] = dat;DMA_SPI3_TX(&d[0],2);
}/******************************************************************************函数说明:LCD写入命令入口数据:dat 写入的命令返回值: 无
******************************************************************************/
void LCD_WR_REG(unsigned char dat)
{LCD_DC_Clr();//写命令LCD_Writ_Bus(dat);LCD_DC_Set();//写数据
}
以上内容都是hal_tftlcd.c 和hal_tftlcd.h文件内容,都是有关于stm32外设 DMA SPI3 的初始化的函数.
以下内容将会是mt_tftlcd.c 和mt_tftlcd.h文件内容,都是有关于模块 LCD屏幕 的初始化内容,LCD屏幕模块的初始化都是基于stm32外设初始化的函数写的,所以模块的初始化函数都是调用外设初始化函数组合而成的,底层就是stm32外设的初始化函数,模块的初始化函数和代码,相对来说是应用层代码。所以,mt文件中是应用层驱动代码,hal文件中是底层驱动代码。
LCD屏幕初始化和LCD填充函数
LCD驱动和LCD相关其他驱动函数,我们直接从官方参考的例程移植过来使用即可,不需要自己深入的研究。
void mt_tftlcd_init(void);
LCD_Fill(unsigned short xsta,unsigned short ysta,unsigned short xend,unsigned short yend,unsigned short color);
注意:不论是底层驱动代码还是应用层驱动代码,都是基于配置STM32寄存器写的程序,不要求深入研究,会调用即可;应用层驱动程序是基于底层驱动程序编程的。
mt_tftlcd.c代码
#include "mt_Tftlcd.h"
#include "hal_tftlcd.h"static void hal_tftlcd_Delay(unsigned int de);
unsigned char ColorBuf[640];void mt_tftlcd_init(void)
{hal_tftlcdConfig();//初始化GPIOhal_tftlcd_Delay(10000);hal_oled_RestL();//复位hal_tftlcd_Delay(10000);hal_oled_RestH();hal_tftlcd_Delay(100);//************* Start Initial Sequence **********//LCD_WR_REG(0x11);hal_tftlcd_Delay(10000);//delay_ms(100); //Delay 120msLCD_WR_REG(0X36);// Memory Access Controlif(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);else LCD_WR_DATA8(0xA0);LCD_WR_REG(0X3A);// LCD_WR_DATA8(0X03); //12bitLCD_WR_DATA8(0X05); //--------------------------------ST7789S Frame rate setting-------------------------LCD_WR_REG(0xb2);LCD_WR_DATA8(0x0c);LCD_WR_DATA8(0x0c);LCD_WR_DATA8(0x00);LCD_WR_DATA8(0x33);LCD_WR_DATA8(0x33);LCD_WR_REG(0xb7);LCD_WR_DATA8(0x35);//---------------------------------ST7789S Power setting-----------------------------LCD_WR_REG(0xbb);LCD_WR_DATA8(0x35);LCD_WR_REG(0xc0);LCD_WR_DATA8(0x2c);LCD_WR_REG(0xc2);LCD_WR_DATA8(0x01);LCD_WR_REG(0xc3);LCD_WR_DATA8(0x13);LCD_WR_REG(0xc4);LCD_WR_DATA8(0x20);LCD_WR_REG(0xc6);LCD_WR_DATA8(0x0f);LCD_WR_REG(0xca);LCD_WR_DATA8(0x0f);LCD_WR_REG(0xc8);LCD_WR_DATA8(0x08);LCD_WR_REG(0x55);LCD_WR_DATA8(0x90);LCD_WR_REG(0xd0);LCD_WR_DATA8(0xa4);LCD_WR_DATA8(0xa1);//--------------------------------ST7789S gamma setting------------------------------LCD_WR_REG(0xe0);LCD_WR_DATA8(0xd0);LCD_WR_DATA8(0x00);LCD_WR_DATA8(0x06);LCD_WR_DATA8(0x09);LCD_WR_DATA8(0x0b);LCD_WR_DATA8(0x2a);LCD_WR_DATA8(0x3c);LCD_WR_DATA8(0x55);LCD_WR_DATA8(0x4b);LCD_WR_DATA8(0x08);LCD_WR_DATA8(0x16);LCD_WR_DATA8(0x14);LCD_WR_DATA8(0x19);LCD_WR_DATA8(0x20);LCD_WR_REG(0xe1);LCD_WR_DATA8(0xd0);LCD_WR_DATA8(0x00);LCD_WR_DATA8(0x06);LCD_WR_DATA8(0x09);LCD_WR_DATA8(0x0b);LCD_WR_DATA8(0x29);LCD_WR_DATA8(0x36);LCD_WR_DATA8(0x54);LCD_WR_DATA8(0x4b);LCD_WR_DATA8(0x0d);LCD_WR_DATA8(0x16);LCD_WR_DATA8(0x14);LCD_WR_DATA8(0x21);LCD_WR_DATA8(0x20);LCD_WR_REG(0x29);hal_Oled_Display_on();//打开背光LCD_Fill(0,0,LCD_W,LCD_H,RED);
} /******************************************************************************函数说明:设置起始和结束地址入口数据:x1,x2 设置列的起始和结束地址y1,y2 设置行的起始和结束地址返回值: 无
******************************************************************************/
void LCD_Address_Set(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2)
{LCD_WR_REG(0x2a);//列地址设置LCD_WR_DATA(x1+2);LCD_WR_DATA(x2+2);LCD_WR_REG(0x2b);//行地址设置LCD_WR_DATA(y1+1);LCD_WR_DATA(y2+1);LCD_WR_REG(0x2c);//储存器写
}static void hal_tftlcd_Delay(unsigned int de)
{while(de--);
}void LCD_Fill(unsigned short xsta,unsigned short ysta,unsigned short xend,unsigned short yend,unsigned short color)
{ unsigned short i; LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围for(i=0;i<xend;i++){ColorBuf[i++] = color>>8;ColorBuf[i] = color;}for(i=ysta;i<yend*2;i++){ DMA_SPI3_TX(ColorBuf,xend);}
}
mt_Tftlcd.h代码
#ifndef ____MT_TFTLCD_H_
#define ____MT_TFTLCD_H_#define USE_HORIZONTAL 3 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏#if USE_HORIZONTAL==0||USE_HORIZONTAL==1#define LCD_W 240
#define LCD_H 320#else
#define LCD_W 320
#define LCD_H 240
#endif///RGB565
#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 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色)enum
{FORTSIZE_12 = 12,FORTSIZE_16 = 16, FORTSIZE_24 = 24,FORTSIZE_32 = 32, FORTSIZE_48 = 48,
};#define HUE_LCD_FONT WHITE
#define HUE_LCD_BACK BLACK//YELLOW //BLACK//
#define HUE_FONT_BACK GRAYvoid mt_tftlcd_init(void);
void LCD_Fill(unsigned short xsta,unsigned short ysta,unsigned short xend,unsigned short yend,unsigned short color);
#endif
功能测试验证
LCD屏幕全屏显示黄色,表示驱动完成OK。
相关文章:

SPI3+DMA外设驱动-TFTLCD初始化
前言 (1)本系列是基于STM32的项目笔记,内容涵盖了STM32各种外设的使用,由浅入深。 (2)小编使用的单片机是STM32F105RCT6,项目笔记基于小编的实际项目,但是博客中的内容适用于各种单片…...
通过chatgpt 学习React的useEffect
定义: useEffect 是 React 中的一个 Hook,它用于处理函数组件中的副作用操作。副作用操作可以包括数据获取、订阅事件、定时器等。 useEffect 接受两个参数:第一个参数是一个回调函数,用于执行副作用操作;第二个参数…...
rabbitMq介绍及使用
点击跳转https://blog.csdn.net/qq_43410878/article/details/123656765...
rabbitmq载在.net中批量消费的问题记录
背景 最近遇到了一个问题,在使用rabbitmq的时候出现了丢消息、消息重复消费等一系列的问题,使用的是.net框架,背景是高并发压力下的mq消费,按理说即使队列中堆了几百条消息,我客户端可以同处理5个消息。 原因是多线程…...

【RPC 协议】序列化与反序列化 | lua-cjson | lua-protobuf
文章目录 RPC 协议gRPCJSON-RPC 数据序列化与反序列化lua-cjsonlua-protobuf RPC 协议 在分布式计算,远程过程调用(英语:Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调…...
Flutter的Timer类
文章目录 一、Timer简介Timer类的详细介绍导入dart:async包创建一个定时器取消定时器定时器的周期性执行注意事项 二、Semantics简介Flutter Semantics 的详细介绍SemanticsNode语义标签和标签形状语义属性自定义语义行为通过语义树导航 一、Timer简介 Flutter的Timer类是Dart…...

Chrome小恐龙快跑小游戏——Python实现
目录 视频演示 代码实现 视频演示 Chrome小恐龙快跑小游戏——Python实现 代码实现 import pygame import os import random pygame.init()# Global Constants SCREEN_HEIGHT 600 SCREEN_WIDTH 1100 game_over False SCREEN pygame.display.set_mode((SCREEN_WIDTH, SCR…...

Web网站服务器
目录 一、什么是Apache? 二、虚拟目录是什么? 三、Apcahe相关配置文件 四、httpd.conf主配置文件的常用配置参数 五、Web网站配置案例 5.1搭建基于用户的个人主页网站 5.2、配置虚拟目录 5.3、配置虚拟主机 5.3.1搭建两个基于IP地址的虚拟主机 5.3.2搭建两个基于域…...

Docker consul 容器服务自动发现和更新
目录 一、什么是服务注册与发现 二、Docker-consul集群 1.Docker-consul consul提供的一些关键特性 2.registrator 3.Consul-template 三、Docker-consul实现过程 以配置nginx负载均衡为例 先配置consul-agent ,有两种模式server和client 四、Docker-cons…...
CentOS 8 执行yum命令报错:Failed to set locale, defaulting to C.UTF-8
今天Docker新搞了一个CentOS镜像,在运行基于该镜像的容器,执行yum命令时,遇到了如下报错: [rootGC Administrator]# yum install -y yum-utils Failed to set locale, defaulting to C.UTF-8 CentOS Linux 8 - AppStream …...

8. 损失函数与反向传播
8.1 损失函数 ① Loss损失函数一方面计算实际输出和目标之间的差距。 ② Loss损失函数另一方面为我们更新输出提供一定的依据。 8.2 L1loss损失函数 ① L1loss数学公式如下图所示,例子如下下图所示。 import torch from torch.nn import L1Loss inputs torch.tens…...

Angular安全专辑之四 —— 避免服务端可能的资源耗尽(NodeJS)
express-rate-limit是一个简单实用的npm包,用于在Express应用程序中实现速率限制。它可以帮助防止DDoS攻击和暴力破解,同时还允许对API端点进行流控。 express-rate-limit及其主要功能 express-rate-limit是Express框架的一个流行中间件,它允许根据IP地址或其他标准轻松地对请求…...

Servlet学习总结(Request请求与转发,Response响应,Servlet生命周期、体系结构、执行流程等...)
Override 是Java中的注解(Annotation),它用于告诉编译器该方法是覆盖(重写)父类中的方法。当我们使用Override注解时,编译器会检查当前方法是否正确地覆盖了父类中的方法,如果没有覆盖成功&…...

雅思写作 三小时浓缩学习顾家北 笔记总结(二)
目录 饥饿网一百句翻译 Using government funds for pollution cleanup work can create a comfortable environment. "Allocating government funds to pollution cleanup work can contribute to the creation of a comfortable environment." Some advertise…...

Element Plus 日期选择器的使用和属性
element plus 日期选择器如果如果没有进行处理 他会返回原有的属性值data格式 如果想要获取选中的日期时间就需要通过以下的代码来实现选中的值 format"YYYY/MM/DD" value-format"YYYY-MM-DD" <el-date-pickerv-model"formInline.date" type&…...

中国五百强企业用泛微为合同加速,提升数字化办公水平
华谊集团借力泛微,融合企业微信、SAP、WPS、电子签章等多种系统,构建了业务集成、场景驱动的全程数字化合同管理平台。 上海华谊(集团)公司是由上海市政府国有资产监督管理委员会授权,通过资产重组建立的大型化工企业…...
Vue3 QRCode生成
一. 依赖安装 npm install vue-qr --save 二. 引用与使用 引用 <script> // import vueqr from vue-qr vue2的引入 import vueqr from vue-qr/src/packages/vue-qr.vue // vue3的引入 export default {components: {vueqr} } </script> 使用 <template>&…...

2023年8月随笔之有顾忌了
1. 回头看 日更坚持了243天。 读《发布!设计与部署稳定的分布式系统》终于更新完成 选读《SQL经典实例》也更新完成 读《高性能MySQL(第4版)》开更,但目前暂缓 读《SQL学习指南(第3版)》开更并持续更新…...

正中优配:红筹股是啥意思?
随着我国经济的高速开展,越来越多的人开始参加到股票出资中。其中,红筹股作为一种特别类型的股票,备受一些出资者的关注,但对于一般出资者来说,红筹股详细含义还不是特别清楚。本文将从多个角度探讨红筹股的含义、特征…...

《Linux从练气到飞升》No.19 进程等待
🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...
ThreadLocal 源码
ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...