STM32进阶:使用STM32驱动ST7735S(内附核心源码)

这篇具有很好参考价值的文章主要介绍了STM32进阶:使用STM32驱动ST7735S(内附核心源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用STM32驱动ST7735S(内附核心源码)

感觉很久很久没有来博客更新了,历经千难万阻,终于做出来了TFT显示屏的SPI驱动,这里分享以下核心源码,接下来一段时间开始准备考科一了,后面有时间了再来更新,有三种模式下的驱动。

一、软件SPI驱动TFT显示屏

实验环境:正点原子 STM32F103ZET6 小型系统板
实验工具:STM32F103ZET6 芯片与 ST7735S芯片(1.44寸TFT显示屏)
数据交互:STM32 芯片通过 GPIO 输入输出引脚模拟软件SPI和TFT液晶显示屏进行通信、数据传输及命令背景光等控制。
实验成效:见STM32F103VET6用SPI驱动ST7735S显示屏力所能及的最快速度了

STM32F103VET6用SPI驱动ST7735S显示屏力所能及的最快速度了

以下为部分实验源码:

//spi.c
#include "spi.h"

extern GPIO_InitTypeDef GPIO_Initure;

void spi_init() {
	RCC_APB2PeriphClockCmd(SPI_RCC_ENABLE, ENABLE);
	
#if SPI_READ_ENABLE
	//SPI	DATA_IN		PA1
	GPIO_Initure.GPIO_Mode = SPI_DATA_IN_MODE;
	GPIO_Initure.GPIO_Pin = SPI_DATA_IN_PIN;
	GPIO_Initure.GPIO_Speed = SPI_DATA_IN_SPEED;
	GPIO_Init(SPI_DATA_IN_GPIO, &GPIO_Initure);
#endif
	
#if SPI_WRITE_ENABLE
	//SPI	DATA_OUT
	GPIO_Initure.GPIO_Mode = SPI_DATA_OUT_MODE;
	GPIO_Initure.GPIO_Pin = SPI_DATA_OUT_PIN;
	GPIO_Initure.GPIO_Speed = SPI_DATA_OUT_SPEED;
	GPIO_Init(SPI_DATA_OUT_GPIO, &GPIO_Initure);
#endif
	
	//SPI	SCLK
	GPIO_Initure.GPIO_Mode = SPI_SCLK_MODE;
	GPIO_Initure.GPIO_Pin = SPI_SCLK_PIN;
	GPIO_Initure.GPIO_Speed = SPI_SCLK_SPEED;
	GPIO_Init(SPI_SCLK_GPIO, &GPIO_Initure);
	
	//SPI	CS
	GPIO_Initure.GPIO_Mode = SPI_CS_MODE;
	GPIO_Initure.GPIO_Pin = SPI_CS_PIN;
	GPIO_Initure.GPIO_Speed = SPI_CS_SPEED;
	GPIO_Init(SPI_CS_GPIO, &GPIO_Initure);
	
	SPI_CS = 1;	//拉高SPI片选引脚,使通信无效
	SPI_SCLK = SPI_DATA_OUT = 0;
}

void spi_start(){
	SPI_CS = 0;
}

void spi_write_place(u8 data) {
	SPI_DATA_OUT = data == 1 ? SPI_DATA_VALID : !SPI_DATA_VALID;
	SPI_SCLK = !SPI_EDGE_TRIGGERED;
#if (SPI_SCLK_LOW_KEEP != 0 && SPI_SCLK_HIGH_KEEP != 0)
	SPI_EDGE_TRIGGERED == 1 ? delay_us(SPI_SCLK_LOW_KEEP) : delay_us(SPI_SCLK_HIGH_KEEP);
#endif
	SPI_SCLK = SPI_EDGE_TRIGGERED;
#if (SPI_SCLK_LOW_KEEP != 0 && SPI_SCLK_HIGH_KEEP != 0)
	SPI_EDGE_TRIGGERED == 1 ? delay_us(SPI_SCLK_LOW_KEEP) : delay_us(SPI_SCLK_HIGH_KEEP);
#endif
}

void spi_write(u8 data){
	u8 i = 0, place;

    for(; i < 8; i ++) {
    	place = data & 1 << (7 - i);
    	spi_write_place(place != 0 ? 1 : 0);
	} 
}

u8 spi_read_place() {
	u8 data;

	SPI_SCLK = !SPI_EDGE_TRIGGERED;
	SPI_EDGE_TRIGGERED == 1 ? delay_us(SPI_SCLK_LOW_KEEP) : delay_us(SPI_SCLK_HIGH_KEEP);
	SPI_SCLK = SPI_EDGE_TRIGGERED;
	data = SPI_DATA_IN;
	SPI_EDGE_TRIGGERED == 1 ? delay_us(SPI_SCLK_LOW_KEEP) : delay_us(SPI_SCLK_HIGH_KEEP);

	return data;
}

u8 spi_read(){
	u8 i = 0, data, place;

	for(; i < 8; i ++) {
		place = spi_read_place();
		data |= place << (7 - i);
	}
	
	return data;
}

void spi_stop() {
	SPI_CS = 1;
}
//spi.h
#ifndef __SPI_H
#define __SPI_H

#include "sys.h"
#include "delay.h"

#define SPI_RCC_ENABLE		RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOF

#define SPI_DATA_IN_MODE	GPIO_Mode_IN_FLOATING
#define SPI_DATA_IN_PIN		GPIO_Pin_1
#define SPI_DATA_IN_SPEED	GPIO_Speed_50MHz
#define SPI_DATA_IN_GPIO	GPIOA

#define SPI_DATA_OUT_MODE	GPIO_Mode_Out_PP
#define SPI_DATA_OUT_PIN	GPIO_Pin_4
#define SPI_DATA_OUT_SPEED	GPIO_Speed_50MHz
#define SPI_DATA_OUT_GPIO	GPIOC

#define SPI_SCLK_MODE		GPIO_Mode_Out_PP
#define SPI_SCLK_PIN		GPIO_Pin_5
#define SPI_SCLK_SPEED		GPIO_Speed_50MHz
#define SPI_SCLK_GPIO		GPIOC

#define SPI_CS_MODE			GPIO_Mode_Out_PP
#define SPI_CS_PIN			GPIO_Pin_10
#define SPI_CS_SPEED		GPIO_Speed_50MHz
#define SPI_CS_GPIO			GPIOF

#define SPI_DATA_IN 	PAin(1)
#define SPI_DATA_OUT 	PCout(4)
#define SPI_SCLK		PCout(5)
#define SPI_CS			PFout(10)

#define SPI_SCLK_HIGH_KEEP	0	//时钟信号低电平维持时间
#define SPI_SCLK_LOW_KEEP	0	//时钟信号高电平维持时间

#define SPI_DATA_VALID		1	//0-低电平有效, 1-高电平有效
#define SPI_EDGE_TRIGGERED	1	//0-下降沿有效, 1-上升沿有效

#define SPI_WRITE_ENABLE	1	//0-禁止SPI写入数据,1-使能SPI读取数据
#define SPI_READ_ENABLE		0	//0-禁止SPI读取数据,1-使能SPI写入数据

void spi_init(void);
void spi_start(void);
void spi_write_place(u8 data);
void spi_write(u8 data);
u8 spi_read_place(void);
u8 spi_read(void);
void spi_stop(void);

#endif	//__SPI_H
//lcd.c
#include "lcd.h"

extern GPIO_InitTypeDef GPIO_Initure;

void lcd_init() {
	RCC_APB2PeriphClockCmd(LCD_RCC_ENABLE, ENABLE);
	
	//RESET
	GPIO_Initure.GPIO_Mode = LCD_RESET_MODE;
	GPIO_Initure.GPIO_Pin = LCD_RESET_PIN;
	GPIO_Initure.GPIO_Speed = LCD_RESET_SPEED;
	GPIO_Init(LCD_RESET_GPIO, &GPIO_Initure);
	
	//CMD DATA
	GPIO_Initure.GPIO_Mode = LCD_CMD_DATA_MODE;
	GPIO_Initure.GPIO_Pin = LCD_CMD_DATA_PIN;
	GPIO_Initure.GPIO_Speed = LCD_CMD_DATA_SPEED;
	GPIO_Init(LCD_CMD_DATA_GPIO, &GPIO_Initure);
	
	//BACK LIGHT
	GPIO_Initure.GPIO_Mode = LCD_BACK_LIGHT_MODE;
	GPIO_Initure.GPIO_Pin = LCD_BACK_LIGHT_PIN;
	GPIO_Initure.GPIO_Speed = LCD_BACK_LIGHT_SPEED;
	GPIO_Init(LCD_BACK_LIGHT_GPIO, &GPIO_Initure);
	
	LCD_RESRT = LCD_CMD_DATA = LCD_BACK_LIGHT = 1;
	
	spi_init();
	lcd_config();
}

void lcd_config() {
	//===============reset============================
	lcd_reset();

	//===============exit sleep=======================
	lcd_write(TFT_CMD ,LCD_SLPOUT);
	delay_ms(120);

	//===============frame set========================
	//Frame rate = fosc / ((RTNA x 2 + 40) x (LINE + FPA + BPA +2))
//	lcd_write(TFT_CMD, LCD_FRMCTR1);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	
//	lcd_write(TFT_CMD, LCD_FRMCTR2);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	
//	lcd_write(TFT_CMD, LCD_FRMCTR3);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
	
	lcd_write(TFT_CMD, LCD_FRMCTR1);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	lcd_write(TFT_CMD, LCD_FRMCTR2);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	lcd_write(TFT_CMD, LCD_FRMCTR3);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	//===============inversion of control=============
	lcd_write(TFT_CMD, LCD_INVCRT);
	lcd_write(TFT_DATA, 0x03);

	//===============power set========================
	lcd_write(TFT_CMD, LCD_PWCTR1);
	lcd_write(TFT_DATA, 0xA2);
	lcd_write(TFT_DATA, 0x02);
	lcd_write(TFT_DATA, 0x84);
		
	lcd_write(TFT_CMD, LCD_PWCTR2);
	lcd_write(TFT_DATA, 0xC5);

	lcd_write(TFT_CMD, LCD_PWCTR3);
	lcd_write(TFT_DATA, 0x0D);
	lcd_write(TFT_DATA, 0x00);
	
	lcd_write(TFT_CMD, LCD_PWCTR4);
	lcd_write(TFT_DATA, 0x8D);
	lcd_write(TFT_DATA, 0x2A);
	
	lcd_write(TFT_CMD, LCD_PWCTR5);
	lcd_write(TFT_DATA, 0x8D);
	lcd_write(TFT_DATA, 0xEE);

	//===============vcom set=========================
	lcd_write(TFT_CMD, LCD_VMCTR1);
	lcd_write(TFT_DATA, 0x03);

	//===============color format set=================
	set_color_format(0x05);
	
	//===============scanning direction set===========
	set_scan_direction(0x08);
	
	//===============gamma sequence set===============
	lcd_write(TFT_CMD, LCD_GMCTRP1);
	lcd_write(TFT_DATA, 0x12);
	lcd_write(TFT_DATA, 0x1C);
	lcd_write(TFT_DATA, 0x10);
	lcd_write(TFT_DATA, 0x18);
	lcd_write(TFT_DATA, 0x33);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x25);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x27);
	lcd_write(TFT_DATA, 0x2F);
	lcd_write(TFT_DATA, 0x3C);
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x10);

	lcd_write(TFT_CMD, LCD_GMCTRN1);
	lcd_write(TFT_DATA, 0x12);
	lcd_write(TFT_DATA, 0x1C);
	lcd_write(TFT_DATA, 0x10);
	lcd_write(TFT_DATA, 0x18);
	lcd_write(TFT_DATA, 0x2D);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x23);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x26);
	lcd_write(TFT_DATA, 0x2F);
	lcd_write(TFT_DATA, 0x3B);
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x10);

	//===============partial area set=================
	lcd_write(TFT_CMD, LCD_PTLAR);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x80);
	
	//===============partial mode on==================
	lcd_write(TFT_CMD, LCD_PTLON);

	//===============display on=======================
	lcd_write(TFT_CMD, LCD_DISPON);
}

void lcd_reset() {
	LCD_RESRT = 1;
	delay_ms(60);
	LCD_RESRT = 0;
	delay_ms(120);
	LCD_RESRT = 1;
	delay_ms(60);
}

void lcd_write(u8 c_d, u8 data) {
	LCD_CMD_DATA = c_d;
	spi_start();
	spi_write(data);
	spi_stop();
}

void set_background(u16 color) {
	u8 i,j;
	set_frame_size(0,0x7F,0x00,0x7F);

	for(i = 0; i < 128; i ++) {
	    for(j = 0; j < 128; j ++) {
			lcd_write(TFT_DATA, color >> 8);
			lcd_write(TFT_DATA, color);
		}
	}
}

void set_scan_direction(u8 data) {
	lcd_write(TFT_CMD, LCD_MADCTL);
	lcd_write(TFT_DATA, data);
}

void set_color_format(u8 data) {
	lcd_write(TFT_CMD, LCD_COLMOD);
	lcd_write(TFT_DATA, data);
}

void set_frame_size(u16 x_start, u16 x_end, u16 y_start, u16 y_end) {
	lcd_write(TFT_CMD, LCD_CASET);
	lcd_write(TFT_DATA, x_start >> 8);
	lcd_write(TFT_DATA, x_start);
	lcd_write(TFT_DATA, x_end >> 8);
	lcd_write(TFT_DATA, x_end);
	
	lcd_write(TFT_CMD, LCD_RASET);
	lcd_write(TFT_DATA, y_start >> 8);
	lcd_write(TFT_DATA, y_start);
	lcd_write(TFT_DATA, y_end >> 8);
	lcd_write(TFT_DATA, y_end);
	
	lcd_write(TFT_CMD, LCD_RAMWR);
}

void set_point(u16 x, u16 y, u16 color) {
	set_frame_size(x, x + 1, y, y + 1);

	lcd_write(TFT_DATA, color >> 8);
	lcd_write(TFT_DATA, color);
}

void set_rectangle(u16 x_start, u16 x_end, u16 y_start, u16 y_end, u16 color) {
	u8 i, j, w, h;
	
	w = x_end - x_start;
	h = y_end - y_start;
	
	set_frame_size(x_start, x_end, y_start, y_end);
	
	for(i = 0; i < w; i ++) {
	    for(j = 0; j < h; j ++) {
			lcd_write(TFT_DATA, color >> 8);
			lcd_write(TFT_DATA, color);
		}
	}
}

void DispGrayHor16(void) {
	u8 i,j,k;

   	set_frame_size(0, 127, 0, 127);

	for(i = 0;i < 128; i ++) {	
		for(j=0;j<16;j++) {
	        for(k=0;k< 128 / 16; k ++) {		
				lcd_write(TFT_DATA, ((j*2)<<3)|((j*4)>>3));		 
				lcd_write(TFT_DATA, ((j*4)<<5)|(j*2));
			} 
		}
	}
}

void DispFrame(void) {
	u8 i,j;
	
	set_frame_size(0, 127, 0, 127);

	lcd_write(TFT_DATA, 0xF8);
	lcd_write(TFT_DATA, 0x00);
	
	for(i = 0; i < 126; i ++){
		lcd_write(TFT_DATA, 0xFF);
		lcd_write(TFT_DATA, 0xFF);
	}
	
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x1F);

	for(j = 0; j < 126; j ++)
	{
		lcd_write(TFT_DATA, 0xF8);
		lcd_write(TFT_DATA, 0x00);
		for(i = 0; i < 126; i ++) {
			lcd_write(TFT_DATA, 0x00);
			lcd_write(TFT_DATA, 0x00);
		}
		
		lcd_write(TFT_DATA, 0x00);
		lcd_write(TFT_DATA, 0x1F);
	}
	
	lcd_write(TFT_DATA, 0xf8);
	lcd_write(TFT_DATA, 0x00);
	
	for(i=0;i<126;i++){
		lcd_write(TFT_DATA, 0xFF);
		lcd_write(TFT_DATA, 0xFF);
	}
	
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x1F);
	
}

void DispBand(void) {
	u8 i,j,k;
	u16 color[8]={0x001f,0x07e0,0xf800,0x07ff,0xf81f,0xffe0,0x0000,0xffff};
//	u16 color[8]={0xf800,0xf800,0x07e0,0x07e0,0x001f,0x001f,0xffff,0xffff};//0x94B2
	//unsigned int gray16[]={0x0000,0x1082,0x2104,0x3186,0x42,0x08,0x528a,0x630c,0x738e,0x7bcf,0x9492,0xa514,0xb596,0xc618,0xd69a,0xe71c,0xffff};

	lcd_write(TFT_CMD, 0x36); //Set Scanning Direction
	lcd_write(TFT_DATA, 0x08); //0xc8

   	set_frame_size(0, 127, 0, 127);																								  

	for(i=0;i < 8;i++)
	{
		for(j=0;j < 128 / 8;j++)
		{
	        for(k=0;k< 128;k++)
			{
				lcd_write(TFT_DATA, color[i]>>8); 
				lcd_write(TFT_DATA, color[i]);   
			} 
		}
	}
}

void DispPic(u8 x,u8 y,u8 w, u8 h,const unsigned char *p) {
	unsigned int i,j;
	unsigned char pic_h,pic_l;
	
//	lcd_write(TFT_CMD, 0x36); //Set Scanning Direction
//	lcd_write(TFT_DATA, 0xC8); //0xc8
	
	set_frame_size(x, x + w - 1, y, y + h - 1);    

	for(i = 0; i < h; i ++) {
	    for(j = 0; j < w; j ++) {    
			pic_l=(*p) ;
			pic_h=(*(p+1)) ;
			lcd_write(TFT_DATA, pic_h);				  
			lcd_write(TFT_DATA, pic_l);
			p=p+2;
		}
	}
}
//lcd.h
#ifndef __LCD_H
#define __LCD_H

#include "sys.h"
#include "spi.h"

#define LCD_RCC_ENABLE		RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOF

#define LCD_RESRT 		PBout(2)
#define LCD_CMD_DATA	PBout(1)
#define LCD_BACK_LIGHT	PFout(11)

#define LCD_RESET_MODE			GPIO_Mode_Out_PP
#define LCD_RESET_PIN			GPIO_Pin_2
#define LCD_RESET_SPEED			GPIO_Speed_50MHz
#define LCD_RESET_GPIO			GPIOB

#define LCD_CMD_DATA_MODE		GPIO_Mode_Out_PP
#define LCD_CMD_DATA_PIN		GPIO_Pin_1
#define LCD_CMD_DATA_SPEED		GPIO_Speed_50MHz
#define LCD_CMD_DATA_GPIO		GPIOB

#define LCD_BACK_LIGHT_MODE		GPIO_Mode_Out_PP
#define LCD_BACK_LIGHT_PIN		GPIO_Pin_11
#define LCD_BACK_LIGHT_SPEED	GPIO_Speed_50MHz
#define LCD_BACK_LIGHT_GPIO		GPIOF

#define LCD_NOP			0x00	//空命令
#define LCD_SWRESET		0x01	//软件复位,在睡眠和显示模式下,重置软件后需等待120ms后方可执行下一条指令
#define LCD_RDDID		0x04	//读取LCD的制造商ID(8位)、驱动版本ID(最高位为1,7位)、驱动程序ID(8位)
#define LCD_RDDST		0x09	//读取显示屏所有状态参数
#define LCD_RDDPM		0x0A	//读取显示屏能量模式
#define LCD_RDDMADCTL	0x0B	//读取显示屏MADCTL
#define LCD_RDDCOLMOD	0x0C	//读取显示屏像素定义
#define LCD_RDDIM		0x0D	//读取显示屏图片模式
#define LCD_RDDSM		0x0E	//读取显示屏单信号模式
#define LCD_RDDSDR		0x0F	//读取显示屏自我诊断结果
#define LCD_SLPIN		0x10	//进入最小功耗模式
#define LCD_SLPOUT 		0x11	//关闭睡眠模式
#define LCD_PTLON		0x12	//打开Partial模式
#define LCD_NORON		0x13	//恢复到正常模式
#define LCD_INVOFF		0x20	//显示反转模式中恢复
#define LCD_INVON		0x21	//进入反向显示模式
#define LCD_GAMSET		0x26	//当前显示选择所需的伽马曲线
#define LCD_DISPOFF		0x28	//关闭显示,帧内存的输出被禁用
#define LCD_DISPON		0x29	//开启显示,帧内存的输出被启用
#define LCD_CASET		0x2A	//列地址设置,每个值代表帧内存中的一列
#define LCD_RASET		0x2B	//行地址设置,每个值代表帧内存中的一列
#define LCD_RAMWR		0x2C	//写入内存
#define LCD_RGBSET		0x2D	//颜色模式设置
#define LCD_RAMRD		0x2E	//读取内存
#define LCD_PTLAR		0x30	//部分模式的显示区域设置
#define LCD_SCRLAR		0x33	//定义垂直滚动区域的显示
#define LCD_TEOFF		0x34	//关闭(Active Low) TE信号线的撕裂效应输出信号
#define LCD_TEON		0x35	//打开TE信号线的撕裂效果输出信号
#define LCD_MADCTL		0x36	//定义帧内存的读写扫描方向
#define LCD_VSCSAD		0x37	//设置垂直滚动起始地址,此命令与垂直滚动定义(33h)一起使用
#define LCD_IDMOFF		0x38	//关闭空闲模式
#define LCD_IDMON		0x39	//开启空闲模式
#define LCD_COLMOD		0x3A	//定义通过MCU接口传输的RGB图片数据的格式
#define LCD_FRMCTR1		0xB1	//设置全色正常模式的帧频
#define LCD_FRMCTR2 	0xB2	//设置空闲模式的帧频
#define LCD_FRMCTR3 	0xB3	//设置部分模式/全色的帧频率
#define LCD_INVCRT 		0xB4	//反转模式控制
#define LCD_PWCTR1 		0xC0	//设置AVDD、MODE、VRHP、VRHN
#define LCD_PWCTR2 		0xC1	//设置VGH与VGL的供电功率
#define LCD_PWCTR3 		0xC2	//设置正常模式/全色模式下的运放的电流
#define LCD_PWCTR4 		0xC3	//设置空闲模式/八色模式下的运放的电流
#define LCD_PWCTR5 		0xC4	//设置部分模式/全色模式下的运放的电流
#define LCD_VMCTR1 		0xC5	//设置VCOM电压电平以减少闪烁问题
#define LCD_VMOFCTR		0xC7	//VCOM偏移控制,在使用命令0xC7之前,命令0xD9的位VMF_EN必须启用(设置为1)
#define LCD_WRID2		0xD1	//写入LCD模块版本的7位数据,保存到NVM
#define LCD_WRID3		0xD2	//写入项目代码模块的8位数据,保存到NVM
#define LCD_NVFCTR1		0xD9	//NVM状态控制
#define LCD_RDID1		0xDA	//读字节返回8位LCD模块的制造商ID
#define LCD_RDID2		0xDB	//读字节返回8位LCD模块/驱动程序版本ID
#define LCD_RDID3		0xDC	//读字节返回8位LCD模块/驱动ID
#define LCD_NVFCTR2		0xDE	//NVM读取命令
#define LCD_NVFCTR3		0xDF	//NVM写取命令
#define LCD_GMCTRP1		0xE0	//Gamma ‘+’ Polarity Correction Characteristics Setting
#define LCD_GMCTRN1		0xE1	//Gamma ‘+’ Polarity Correction Characteristics Setting
#define LCD_GCV			0xFC	//自动调节门泵时钟,节省功耗


enum TFT_DATA_TYPE {
	TFT_CMD = 0,
	TFT_DATA
};

void lcd_init(void);
void lcd_config(void);
void lcd_reset(void);
void lcd_write(u8 c_d, u8 data);
void set_background(u16 color);
void set_scan_direction(u8 data);
void set_color_format(u8 data);
void set_frame_size(u16 x_start, u16 x_end, u16 y_start, u16 y_end);
void set_point(u16 x, u16 y, u16 color);
void set_rectangle(u16 x_start, u16 x_end, u16 y_start, u16 y_end, u16 color);
void DispGrayHor16(void);
void DispFrame(void);
void DispBand(void);
void DispPic(u8 x,u8 y,u8 w, u8 h,const unsigned char *p);

#endif	//__LCD_H

二、硬件SPI驱动TFT显示屏

实验环境:正点原子 STM32F103ZET6 小型系统板
实验工具:STM32F103ZET6 芯片与 ST7735S芯片(1.44寸TFT显示屏)
数据交互:STM32 芯片通过 GPIO 输入输出引脚输出SPI和TFT液晶显示屏进行通信、数据传输及命令背景光等控制。
实验成效:见STM32F103VET6硬件SPI确实比软件SPI快很多

STM32F103VET6硬件SPI确实比软件SPI快很多

以下为部分实验源码:

//spi.c
#include "spi.h"

extern GPIO_InitTypeDef GPIO_Initure;
SPI_InitTypeDef SPI_Initure;

void spi_init() {
	RCC_APB2PeriphClockCmd(SPI_RCC_ENABLE, ENABLE);
	
#if SPI_READ_ENABLE
	//SPI	DATA_IN		PA1
	GPIO_Initure.GPIO_Mode = SPI_DATA_IN_MODE;
	GPIO_Initure.GPIO_Pin = SPI_DATA_IN_PIN;
	GPIO_Initure.GPIO_Speed = SPI_DATA_IN_SPEED;
	GPIO_Init(SPI_DATA_IN_GPIO, &GPIO_Initure);
#endif
	
#if SPI_WRITE_ENABLE
	//SPI	DATA_OUT
	GPIO_Initure.GPIO_Mode = SPI_DATA_OUT_MODE;
	GPIO_Initure.GPIO_Pin = SPI_DATA_OUT_PIN;
	GPIO_Initure.GPIO_Speed = SPI_DATA_OUT_SPEED;
	GPIO_Init(SPI_DATA_OUT_GPIO, &GPIO_Initure);
#endif
	
	//SPI	SCLK
	GPIO_Initure.GPIO_Mode = SPI_SCLK_MODE;
	GPIO_Initure.GPIO_Pin = SPI_SCLK_PIN;
	GPIO_Initure.GPIO_Speed = SPI_SCLK_SPEED;
	GPIO_Init(SPI_SCLK_GPIO, &GPIO_Initure);
	
	//SPI	CS
	GPIO_Initure.GPIO_Mode = SPI_CS_MODE;
	GPIO_Initure.GPIO_Pin = SPI_CS_PIN;
	GPIO_Initure.GPIO_Speed = SPI_CS_SPEED;
	GPIO_Init(SPI_CS_GPIO, &GPIO_Initure);
	
	SPI_CS = 1;
	
	SPI_Initure.SPI_BaudRatePrescaler	= SPI_BaudRatePrescaler_2;	// 使分频值达到最大
	SPI_Initure.SPI_CPHA				= SPI_CPHA_1Edge;			// 上降沿有效
	SPI_Initure.SPI_CPOL				= SPI_CPOL_Low;				// 高电平有效
	SPI_Initure.SPI_CRCPolynomial		= 7;						// 无 CRC 校验
	SPI_Initure.SPI_DataSize			= SPI_DataSize_8b;			// 发送字长为 8 位
	SPI_Initure.SPI_Direction			= SPI_Direction_1Line_Tx;	// 方向为发送
	SPI_Initure.SPI_FirstBit			= SPI_FirstBit_MSB;			// 高位先行
	SPI_Initure.SPI_Mode				= SPI_Mode_Master;			// 主机模式
	SPI_Initure.SPI_NSS					= SPI_NSS_Soft;				// 软件控制
	SPI_Init(SPI1,&SPI_Initure);
	
	SPI_Cmd(SPI1, ENABLE);
	
	spi_write(0xff);
}

void spi_write(u8 data) {
	u16 next = 0;
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) {
		if(++ next > 500) return;
	}
	SPI_I2S_SendData(SPI1, data);
}
//spi.h
#ifndef __SPI_H
#define __SPI_H

#include "sys.h"
#include "delay.h"

#define SPI_RCC_ENABLE		RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1

#define SPI_CS PAout(4)

#define SPI_DATA_IN_MODE	GPIO_Mode_IN_FLOATING
#define SPI_DATA_IN_PIN		GPIO_Pin_6
#define SPI_DATA_IN_SPEED	GPIO_Speed_50MHz
#define SPI_DATA_IN_GPIO	GPIOA

#define SPI_DATA_OUT_MODE	GPIO_Mode_AF_PP
#define SPI_DATA_OUT_PIN	GPIO_Pin_7
#define SPI_DATA_OUT_SPEED	GPIO_Speed_50MHz
#define SPI_DATA_OUT_GPIO	GPIOA

#define SPI_SCLK_MODE		GPIO_Mode_AF_PP
#define SPI_SCLK_PIN		GPIO_Pin_5
#define SPI_SCLK_SPEED		GPIO_Speed_50MHz
#define SPI_SCLK_GPIO		GPIOA

#define SPI_CS_MODE			GPIO_Mode_Out_PP
#define SPI_CS_PIN			GPIO_Pin_4
#define SPI_CS_SPEED		GPIO_Speed_50MHz
#define SPI_CS_GPIO			GPIOA

#define SPI_WRITE_ENABLE	1	//0-禁止SPI写入数据,1-使能SPI读取数据
#define SPI_READ_ENABLE		0	//0-禁止SPI读取数据,1-使能SPI写入数据

void spi_init(void);
void spi_write(u8 data);

#endif	//__SPI_H
//lcd.c
#include "lcd.h"

extern GPIO_InitTypeDef GPIO_Initure;

void lcd_init() {
	RCC_APB2PeriphClockCmd(LCD_RCC_ENABLE, ENABLE);
	
	//RESET
	GPIO_Initure.GPIO_Mode = LCD_RESET_MODE;
	GPIO_Initure.GPIO_Pin = LCD_RESET_PIN;
	GPIO_Initure.GPIO_Speed = LCD_RESET_SPEED;
	GPIO_Init(LCD_RESET_GPIO, &GPIO_Initure);
	
	//CMD DATA
	GPIO_Initure.GPIO_Mode = LCD_CMD_DATA_MODE;
	GPIO_Initure.GPIO_Pin = LCD_CMD_DATA_PIN;
	GPIO_Initure.GPIO_Speed = LCD_CMD_DATA_SPEED;
	GPIO_Init(LCD_CMD_DATA_GPIO, &GPIO_Initure);
	
	//BACK LIGHT
	GPIO_Initure.GPIO_Mode = LCD_BACK_LIGHT_MODE;
	GPIO_Initure.GPIO_Pin = LCD_BACK_LIGHT_PIN;
	GPIO_Initure.GPIO_Speed = LCD_BACK_LIGHT_SPEED;
	GPIO_Init(LCD_BACK_LIGHT_GPIO, &GPIO_Initure);
	
	LCD_RESRT = LCD_CMD_DATA = LCD_BACK_LIGHT = 1;
	
	spi_init();
	lcd_config();
}

void lcd_config() {
	//===============reset============================
	lcd_reset();

	//===============exit sleep=======================
	lcd_write(TFT_CMD ,LCD_SLPOUT);
	delay_ms(120);

	//===============frame set========================
	//Frame rate = fosc / ((RTNA x 2 + 40) x (LINE + FPA + BPA +2))
//	lcd_write(TFT_CMD, LCD_FRMCTR1);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	
//	lcd_write(TFT_CMD, LCD_FRMCTR2);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	
//	lcd_write(TFT_CMD, LCD_FRMCTR3);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
	
	lcd_write(TFT_CMD, LCD_FRMCTR1);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	lcd_write(TFT_CMD, LCD_FRMCTR2);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	lcd_write(TFT_CMD, LCD_FRMCTR3);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	//===============inversion of control=============
	lcd_write(TFT_CMD, LCD_INVCRT);
	lcd_write(TFT_DATA, 0x03);

	//===============power set========================
	lcd_write(TFT_CMD, LCD_PWCTR1);
	lcd_write(TFT_DATA, 0xA2);
	lcd_write(TFT_DATA, 0x02);
	lcd_write(TFT_DATA, 0x84);
		
	lcd_write(TFT_CMD, LCD_PWCTR2);
	lcd_write(TFT_DATA, 0xC5);

	lcd_write(TFT_CMD, LCD_PWCTR3);
	lcd_write(TFT_DATA, 0x0D);
	lcd_write(TFT_DATA, 0x00);
	
	lcd_write(TFT_CMD, LCD_PWCTR4);
	lcd_write(TFT_DATA, 0x8D);
	lcd_write(TFT_DATA, 0x2A);
	
	lcd_write(TFT_CMD, LCD_PWCTR5);
	lcd_write(TFT_DATA, 0x8D);
	lcd_write(TFT_DATA, 0xEE);

	//===============vcom set=========================
	lcd_write(TFT_CMD, LCD_VMCTR1);
	lcd_write(TFT_DATA, 0x03);

	//===============color format set=================
	set_color_format(0x05);
	
	//===============scanning direction set===========
	set_scan_direction(0x08);
	
	//===============gamma sequence set===============
	lcd_write(TFT_CMD, LCD_GMCTRP1);
	lcd_write(TFT_DATA, 0x12);
	lcd_write(TFT_DATA, 0x1C);
	lcd_write(TFT_DATA, 0x10);
	lcd_write(TFT_DATA, 0x18);
	lcd_write(TFT_DATA, 0x33);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x25);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x27);
	lcd_write(TFT_DATA, 0x2F);
	lcd_write(TFT_DATA, 0x3C);
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x10);

	lcd_write(TFT_CMD, LCD_GMCTRN1);
	lcd_write(TFT_DATA, 0x12);
	lcd_write(TFT_DATA, 0x1C);
	lcd_write(TFT_DATA, 0x10);
	lcd_write(TFT_DATA, 0x18);
	lcd_write(TFT_DATA, 0x2D);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x23);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x26);
	lcd_write(TFT_DATA, 0x2F);
	lcd_write(TFT_DATA, 0x3B);
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x10);

	//===============partial area set=================
	lcd_write(TFT_CMD, LCD_PTLAR);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x80);
	
	//===============partial mode on==================
	lcd_write(TFT_CMD, LCD_PTLON);

	//===============display on=======================
	lcd_write(TFT_CMD, LCD_DISPON);
}

void lcd_reset() {
	LCD_RESRT = 1;
	delay_ms(60);
	LCD_RESRT = 0;
	delay_ms(120);
	LCD_RESRT = 1;
	delay_ms(60);
}

void lcd_write(u8 c_d, u8 data) {
	LCD_CMD_DATA = c_d;
	SPI_CS = 0;
	spi_write(data);
	SPI_CS = 1;
}

void set_background(u16 color) {
	u8 i,j;
	set_frame_size(0,0x7F,0x00,0x7F);

	for(i = 0; i < 128; i ++) {
	    for(j = 0; j < 128; j ++) {
			lcd_write(TFT_DATA, color >> 8);
			lcd_write(TFT_DATA, color);
		}
	}
}

void set_scan_direction(u8 data) {
	lcd_write(TFT_CMD, LCD_MADCTL);
	lcd_write(TFT_DATA, data);
}

void set_color_format(u8 data) {
	lcd_write(TFT_CMD, LCD_COLMOD);
	lcd_write(TFT_DATA, data);
}

void set_frame_size(u16 x_start, u16 x_end, u16 y_start, u16 y_end) {
	lcd_write(TFT_CMD, LCD_CASET);
	lcd_write(TFT_DATA, x_start >> 8);
	lcd_write(TFT_DATA, x_start);
	lcd_write(TFT_DATA, x_end >> 8);
	lcd_write(TFT_DATA, x_end);
	
	lcd_write(TFT_CMD, LCD_RASET);
	lcd_write(TFT_DATA, y_start >> 8);
	lcd_write(TFT_DATA, y_start);
	lcd_write(TFT_DATA, y_end >> 8);
	lcd_write(TFT_DATA, y_end);
	
	lcd_write(TFT_CMD, LCD_RAMWR);
}

void set_point(u16 x, u16 y, u16 color) {
	set_frame_size(x, x + 1, y, y + 1);

	lcd_write(TFT_DATA, color >> 8);
	lcd_write(TFT_DATA, color);
}

void set_rectangle(u16 x_start, u16 x_end, u16 y_start, u16 y_end, u16 color) {
	u8 i, j, w, h;
	
	w = x_end - x_start;
	h = y_end - y_start;
	
	set_frame_size(x_start, x_end, y_start, y_end);
	
	for(i = 0; i < w; i ++) {
	    for(j = 0; j < h; j ++) {
			lcd_write(TFT_DATA, color >> 8);
			lcd_write(TFT_DATA, color);
		}
	}
}

void DispGrayHor16(void) {
	u8 i,j,k;

   	set_frame_size(0, 127, 0, 127);

	for(i = 0;i < 128; i ++) {	
		for(j=0;j<16;j++) {
	        for(k=0;k< 128 / 16; k ++) {		
				lcd_write(TFT_DATA, ((j*2)<<3)|((j*4)>>3));		 
				lcd_write(TFT_DATA, ((j*4)<<5)|(j*2));
			} 
		}
	}
}

void DispFrame(void) {
	u8 i,j;
	
	set_frame_size(0, 127, 0, 127);

	lcd_write(TFT_DATA, 0xF8);
	lcd_write(TFT_DATA, 0x00);
	
	for(i = 0; i < 126; i ++){
		lcd_write(TFT_DATA, 0xFF);
		lcd_write(TFT_DATA, 0xFF);
	}
	
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x1F);

	for(j = 0; j < 126; j ++)
	{
		lcd_write(TFT_DATA, 0xF8);
		lcd_write(TFT_DATA, 0x00);
		for(i = 0; i < 126; i ++) {
			lcd_write(TFT_DATA, 0x00);
			lcd_write(TFT_DATA, 0x00);
		}
		
		lcd_write(TFT_DATA, 0x00);
		lcd_write(TFT_DATA, 0x1F);
	}
	
	lcd_write(TFT_DATA, 0xf8);
	lcd_write(TFT_DATA, 0x00);
	
	for(i=0;i<126;i++){
		lcd_write(TFT_DATA, 0xFF);
		lcd_write(TFT_DATA, 0xFF);
	}
	
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x1F);
	
}

void DispBand(void) {
	u8 i,j,k;
	u16 color[8]={0x001f,0x07e0,0xf800,0x07ff,0xf81f,0xffe0,0x0000,0xffff};
//	u16 color[8]={0xf800,0xf800,0x07e0,0x07e0,0x001f,0x001f,0xffff,0xffff};//0x94B2
	//unsigned int gray16[]={0x0000,0x1082,0x2104,0x3186,0x42,0x08,0x528a,0x630c,0x738e,0x7bcf,0x9492,0xa514,0xb596,0xc618,0xd69a,0xe71c,0xffff};

	lcd_write(TFT_CMD, 0x36); //Set Scanning Direction
	lcd_write(TFT_DATA, 0x08); //0xc8

   	set_frame_size(0, 127, 0, 127);																								  

	for(i=0;i < 8;i++)
	{
		for(j=0;j < 128 / 8;j++)
		{
	        for(k=0;k< 128;k++)
			{
				lcd_write(TFT_DATA, color[i]>>8); 
				lcd_write(TFT_DATA, color[i]);   
			} 
		}
	}
}

void DispPic(u8 x,u8 y,u8 w, u8 h,const unsigned char *p) {
	unsigned int i,j;
	unsigned char pic_h,pic_l;
	
//	lcd_write(TFT_CMD, 0x36); //Set Scanning Direction
//	lcd_write(TFT_DATA, 0xC8); //0xc8
	
	set_frame_size(x, x + w - 1, y, y + h - 1);    

	for(i = 0; i < h; i ++) {
	    for(j = 0; j < w; j ++) {    
			pic_l = *p ;
			pic_h = *(p+1);
			lcd_write(TFT_DATA, pic_h);				  
			lcd_write(TFT_DATA, pic_l);
			p += 2;
		}
	}
}
//lcd.h
#ifndef __LCD_H
#define __LCD_H

#include "sys.h"
#include "spi.h"

#define LCD_RCC_ENABLE		RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOF

#define LCD_RESRT 		PBout(2)
#define LCD_CMD_DATA	PBout(1)
#define LCD_BACK_LIGHT	PFout(11)

#define LCD_RESET_MODE			GPIO_Mode_Out_PP
#define LCD_RESET_PIN			GPIO_Pin_2
#define LCD_RESET_SPEED			GPIO_Speed_50MHz
#define LCD_RESET_GPIO			GPIOB

#define LCD_CMD_DATA_MODE		GPIO_Mode_Out_PP
#define LCD_CMD_DATA_PIN		GPIO_Pin_1
#define LCD_CMD_DATA_SPEED		GPIO_Speed_50MHz
#define LCD_CMD_DATA_GPIO		GPIOB

#define LCD_BACK_LIGHT_MODE		GPIO_Mode_Out_PP
#define LCD_BACK_LIGHT_PIN		GPIO_Pin_11
#define LCD_BACK_LIGHT_SPEED	GPIO_Speed_50MHz
#define LCD_BACK_LIGHT_GPIO		GPIOF

#define LCD_NOP			0x00	//空命令
#define LCD_SWRESET		0x01	//软件复位,在睡眠和显示模式下,重置软件后需等待120ms后方可执行下一条指令
#define LCD_RDDID		0x04	//读取LCD的制造商ID(8位)、驱动版本ID(最高位为1,7位)、驱动程序ID(8位)
#define LCD_RDDST		0x09	//读取显示屏所有状态参数
#define LCD_RDDPM		0x0A	//读取显示屏能量模式
#define LCD_RDDMADCTL	0x0B	//读取显示屏MADCTL
#define LCD_RDDCOLMOD	0x0C	//读取显示屏像素定义
#define LCD_RDDIM		0x0D	//读取显示屏图片模式
#define LCD_RDDSM		0x0E	//读取显示屏单信号模式
#define LCD_RDDSDR		0x0F	//读取显示屏自我诊断结果
#define LCD_SLPIN		0x10	//进入最小功耗模式
#define LCD_SLPOUT 		0x11	//关闭睡眠模式
#define LCD_PTLON		0x12	//打开Partial模式
#define LCD_NORON		0x13	//恢复到正常模式
#define LCD_INVOFF		0x20	//显示反转模式中恢复
#define LCD_INVON		0x21	//进入反向显示模式
#define LCD_GAMSET		0x26	//当前显示选择所需的伽马曲线
#define LCD_DISPOFF		0x28	//关闭显示,帧内存的输出被禁用
#define LCD_DISPON		0x29	//开启显示,帧内存的输出被启用
#define LCD_CASET		0x2A	//列地址设置,每个值代表帧内存中的一列
#define LCD_RASET		0x2B	//行地址设置,每个值代表帧内存中的一列
#define LCD_RAMWR		0x2C	//写入内存
#define LCD_RGBSET		0x2D	//颜色模式设置
#define LCD_RAMRD		0x2E	//读取内存
#define LCD_PTLAR		0x30	//部分模式的显示区域设置
#define LCD_SCRLAR		0x33	//定义垂直滚动区域的显示
#define LCD_TEOFF		0x34	//关闭(Active Low) TE信号线的撕裂效应输出信号
#define LCD_TEON		0x35	//打开TE信号线的撕裂效果输出信号
#define LCD_MADCTL		0x36	//定义帧内存的读写扫描方向
#define LCD_VSCSAD		0x37	//设置垂直滚动起始地址,此命令与垂直滚动定义(33h)一起使用
#define LCD_IDMOFF		0x38	//关闭空闲模式
#define LCD_IDMON		0x39	//开启空闲模式
#define LCD_COLMOD		0x3A	//定义通过MCU接口传输的RGB图片数据的格式
#define LCD_FRMCTR1		0xB1	//设置全色正常模式的帧频
#define LCD_FRMCTR2 	0xB2	//设置空闲模式的帧频
#define LCD_FRMCTR3 	0xB3	//设置部分模式/全色的帧频率
#define LCD_INVCRT 		0xB4	//反转模式控制
#define LCD_PWCTR1 		0xC0	//设置AVDD、MODE、VRHP、VRHN
#define LCD_PWCTR2 		0xC1	//设置VGH与VGL的供电功率
#define LCD_PWCTR3 		0xC2	//设置正常模式/全色模式下的运放的电流
#define LCD_PWCTR4 		0xC3	//设置空闲模式/八色模式下的运放的电流
#define LCD_PWCTR5 		0xC4	//设置部分模式/全色模式下的运放的电流
#define LCD_VMCTR1 		0xC5	//设置VCOM电压电平以减少闪烁问题
#define LCD_VMOFCTR		0xC7	//VCOM偏移控制,在使用命令0xC7之前,命令0xD9的位VMF_EN必须启用(设置为1)
#define LCD_WRID2		0xD1	//写入LCD模块版本的7位数据,保存到NVM
#define LCD_WRID3		0xD2	//写入项目代码模块的8位数据,保存到NVM
#define LCD_NVFCTR1		0xD9	//NVM状态控制
#define LCD_RDID1		0xDA	//读字节返回8位LCD模块的制造商ID
#define LCD_RDID2		0xDB	//读字节返回8位LCD模块/驱动程序版本ID
#define LCD_RDID3		0xDC	//读字节返回8位LCD模块/驱动ID
#define LCD_NVFCTR2		0xDE	//NVM读取命令
#define LCD_NVFCTR3		0xDF	//NVM写取命令
#define LCD_GMCTRP1		0xE0	//Gamma ‘+’ Polarity Correction Characteristics Setting
#define LCD_GMCTRN1		0xE1	//Gamma ‘+’ Polarity Correction Characteristics Setting
#define LCD_GCV			0xFC	//自动调节门泵时钟,节省功耗


enum TFT_DATA_TYPE {
	TFT_CMD = 0,
	TFT_DATA
};

void lcd_init(void);
void lcd_config(void);
void lcd_reset(void);
void lcd_write(u8 c_d, u8 data);
void set_background(u16 color);
void set_scan_direction(u8 data);
void set_color_format(u8 data);
void set_frame_size(u16 x_start, u16 x_end, u16 y_start, u16 y_end);
void set_point(u16 x, u16 y, u16 color);
void set_rectangle(u16 x_start, u16 x_end, u16 y_start, u16 y_end, u16 color);
void DispGrayHor16(void);
void DispFrame(void);
void DispBand(void);
void DispPic(u8 x,u8 y,u8 w, u8 h,const unsigned char *p);

#endif	//__LCD_H

三、硬件SPI+DMA驱动TFT显示屏

实验环境:正点原子 STM32F103ZET6 小型系统板
实验工具:STM32F103ZET6 芯片与 ST7735S芯片(1.44寸TFT显示屏)
数据交互:STM32 芯片通过 GPIO 输入输出引脚输出SPI配合DMA与TFT液晶显示屏进行通信、数据传输及命令背景光等控制。
实验成效:见STM32F103VET6硬件SPI+DMA着实快,图片上下移动的速度还可以

STM32F103VET6硬件SPI+DMA着实快,图片上下移动的速度还可以

以下为部分实验源码(lcd模块只改了部分代码,剩下的可以自己改):

//spi.c
#include "spi.h"

extern GPIO_InitTypeDef GPIO_Initure;
SPI_InitTypeDef SPI_Initure;

void spi_init() {
	RCC_APB2PeriphClockCmd(SPI_RCC_ENABLE, ENABLE);
	
#if SPI_READ_ENABLE
	//SPI	DATA_IN		PA1
	GPIO_Initure.GPIO_Mode = SPI_DATA_IN_MODE;
	GPIO_Initure.GPIO_Pin = SPI_DATA_IN_PIN;
	GPIO_Initure.GPIO_Speed = SPI_DATA_IN_SPEED;
	GPIO_Init(SPI_DATA_IN_GPIO, &GPIO_Initure);
#endif
	
#if SPI_WRITE_ENABLE
	//SPI	DATA_OUT
	GPIO_Initure.GPIO_Mode = SPI_DATA_OUT_MODE;
	GPIO_Initure.GPIO_Pin = SPI_DATA_OUT_PIN;
	GPIO_Initure.GPIO_Speed = SPI_DATA_OUT_SPEED;
	GPIO_Init(SPI_DATA_OUT_GPIO, &GPIO_Initure);
#endif
	
	//SPI	SCLK
	GPIO_Initure.GPIO_Mode = SPI_SCLK_MODE;
	GPIO_Initure.GPIO_Pin = SPI_SCLK_PIN;
	GPIO_Initure.GPIO_Speed = SPI_SCLK_SPEED;
	GPIO_Init(SPI_SCLK_GPIO, &GPIO_Initure);
	
	//SPI	CS
	GPIO_Initure.GPIO_Mode = SPI_CS_MODE;
	GPIO_Initure.GPIO_Pin = SPI_CS_PIN;
	GPIO_Initure.GPIO_Speed = SPI_CS_SPEED;
	GPIO_Init(SPI_CS_GPIO, &GPIO_Initure);
	
	SPI_CS = 1;
	
	SPI_Initure.SPI_BaudRatePrescaler	= SPI_BaudRatePrescaler_2;	// 使分频值达到最大
	SPI_Initure.SPI_CPHA				= SPI_CPHA_1Edge;			// 上降沿有效
	SPI_Initure.SPI_CPOL				= SPI_CPOL_Low;				// 高电平有效
	SPI_Initure.SPI_CRCPolynomial		= 0;						// 无 CRC 校验
	SPI_Initure.SPI_DataSize			= SPI_DataSize_8b;			// 发送字长为 8 位
	SPI_Initure.SPI_Direction			= SPI_Direction_1Line_Tx;	// 方向为发送
	SPI_Initure.SPI_FirstBit			= SPI_FirstBit_MSB;			// 高位先行
	SPI_Initure.SPI_Mode				= SPI_Mode_Master;			// 主机模式
	SPI_Initure.SPI_NSS					= SPI_NSS_Soft;				// 软件控制
	SPI_Init(SPI1,&SPI_Initure);
	
	SPI_Cmd(SPI1, ENABLE);
}

void spi_write(u8 data) {
	u16 next = 0;
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) {
		if(++ next > 500) return;
	}
	SPI_I2S_SendData(SPI1, data);
}
//spi.h
#ifndef __SPI_H
#define __SPI_H

#include "sys.h"
#include "delay.h"

#define SPI_RCC_ENABLE		RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1

#define SPI_CS PAout(4)

#define SPI_DATA_IN_MODE	GPIO_Mode_IN_FLOATING
#define SPI_DATA_IN_PIN		GPIO_Pin_6
#define SPI_DATA_IN_SPEED	GPIO_Speed_50MHz
#define SPI_DATA_IN_GPIO	GPIOA

#define SPI_DATA_OUT_MODE	GPIO_Mode_AF_PP
#define SPI_DATA_OUT_PIN	GPIO_Pin_7
#define SPI_DATA_OUT_SPEED	GPIO_Speed_50MHz
#define SPI_DATA_OUT_GPIO	GPIOA

#define SPI_SCLK_MODE		GPIO_Mode_AF_PP
#define SPI_SCLK_PIN		GPIO_Pin_5
#define SPI_SCLK_SPEED		GPIO_Speed_50MHz
#define SPI_SCLK_GPIO		GPIOA

#define SPI_CS_MODE			GPIO_Mode_Out_PP
#define SPI_CS_PIN			GPIO_Pin_4
#define SPI_CS_SPEED		GPIO_Speed_50MHz
#define SPI_CS_GPIO			GPIOA

#define SPI_WRITE_ENABLE	1	//0-禁止SPI写入数据,1-使能SPI读取数据
#define SPI_READ_ENABLE		0	//0-禁止SPI读取数据,1-使能SPI写入数据

void spi_init(void);
void spi_write(u8 data);

#endif	//__SPI_H
//dma.c
#include "dma.h"

DMA_InitTypeDef DMA_Initure;

void dma1_init(DMA_Channel_TypeDef* dma_chanel, u32 mem_addr, u32 per_addr, u32 buf_size) {
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);	// 使能 DMA 高速时钟
	
	DMA_DeInit(dma_chanel);
	
	DMA_Initure.DMA_BufferSize			= buf_size;						// 设置 DMA 缓冲区数据长度,后期可调
	DMA_Initure.DMA_DIR					= DMA_DIR_PeripheralDST;		// 设置 DMA 数据传输方向,这里为内存到外设
	DMA_Initure.DMA_M2M					= DMA_M2M_Disable;				// 禁止 DMA 的内存到内存操作
	DMA_Initure.DMA_MemoryBaseAddr		= mem_addr;						// 设置 DMA 内存访问的起始地址
	DMA_Initure.DMA_MemoryDataSize		= DMA_MemoryDataSize_Byte;		// 内存物理数据大小为一个字节占 8 位
	DMA_Initure.DMA_MemoryInc			= DMA_MemoryInc_Enable;			// 使能 DMA 内存地址递增
	DMA_Initure.DMA_Mode				= DMA_Mode_Normal;				// 选择 DMA 单次读写模式
	DMA_Initure.DMA_PeripheralBaseAddr	= per_addr;						// 设置 DMA 外设访问的起始地址
	DMA_Initure.DMA_PeripheralDataSize	= DMA_PeripheralDataSize_Byte;	// 外设物理数据大小为一个字节占 8 位
	DMA_Initure.DMA_PeripheralInc		= DMA_PeripheralInc_Disable;	// 禁止 DMA 外设地址递增
	DMA_Initure.DMA_Priority			= DMA_Priority_High;			// 高优先级
	DMA_Init(dma_chanel, &DMA_Initure);
}

void dma1_chanel_choose(DMA_Channel_TypeDef* dma_chanel, u32 buf_size) {
	DMA_Cmd(dma_chanel, DISABLE);					//禁止 DMA 通道
	DMA_SetCurrDataCounter(dma_chanel, buf_size);	//设置 DMA 通道与 DMA 缓冲区大小
	DMA_Cmd(dma_chanel, ENABLE);					//使能 DMA 通道
}

void dma1_to_spi1(DMA_Channel_TypeDef* dma_chanel, u32 buf_size, uint16_t spi_dma_req, uint32_t dma_flag) {
	//设置一个超时变量
	u16 timeout = 0;
	
	//重新初始化DMA缓冲区大小并使能 DMA 通道
	dma1_chanel_choose(DMA1_Channel3, 128*2);

	//使能 DMA1
	SPI_I2S_DMACmd(SPI1, spi_dma_req, ENABLE);

	//判断 DMA 是否完成数据传输,若超过一定时限,则中断本次传输
	while(DMA_GetFlagStatus(dma_flag) == RESET) {
		if(timeout ++ > 200) break;
	}

	// 清除 DMA 标志位
	DMA_ClearFlag(dma_flag);
}
#ifndef __DMA_H
#define __DMA_H

#include "sys.h"

void dma1_init(DMA_Channel_TypeDef* DMAy_Channelx, u32 mem_addr, u32 per_addr, u32 buf_size);
void dma1_chanel_choose(DMA_Channel_TypeDef* dma_chanel, u32 buf_size);
void dma1_to_spi1(DMA_Channel_TypeDef* dma_chanel, u32 buf_size, uint16_t spi_dma_req,uint32_t dma_flag);

#endif	//__DMA_H
//lcd.c
#include "lcd.h"
#include "led.h"

#define BUF_SIZE 128

extern GPIO_InitTypeDef GPIO_Initure;
u8 dma_data[2 * BUF_SIZE];

void lcd_init() {
	RCC_APB2PeriphClockCmd(LCD_RCC_ENABLE, ENABLE);
	
	//RESET
	GPIO_Initure.GPIO_Mode = LCD_RESET_MODE;
	GPIO_Initure.GPIO_Pin = LCD_RESET_PIN;
	GPIO_Initure.GPIO_Speed = LCD_RESET_SPEED;
	GPIO_Init(LCD_RESET_GPIO, &GPIO_Initure);
	
	//CMD DATA
	GPIO_Initure.GPIO_Mode = LCD_CMD_DATA_MODE;
	GPIO_Initure.GPIO_Pin = LCD_CMD_DATA_PIN;
	GPIO_Initure.GPIO_Speed = LCD_CMD_DATA_SPEED;
	GPIO_Init(LCD_CMD_DATA_GPIO, &GPIO_Initure);
	
	//BACK LIGHT
	GPIO_Initure.GPIO_Mode = LCD_BACK_LIGHT_MODE;
	GPIO_Initure.GPIO_Pin = LCD_BACK_LIGHT_PIN;
	GPIO_Initure.GPIO_Speed = LCD_BACK_LIGHT_SPEED;
	GPIO_Init(LCD_BACK_LIGHT_GPIO, &GPIO_Initure);
	
	LCD_RESRT = LCD_CMD_DATA = LCD_BACK_LIGHT = 1;
	
	spi_init();
	lcd_config();
	dma1_init(DMA1_Channel3, (u32)dma_data, (u32)&(SPI1 -> DR), 2 * BUF_SIZE);
}

void lcd_config() {
	//===============reset============================
	lcd_reset();

	//===============exit sleep=======================
	lcd_write(TFT_CMD ,LCD_SLPOUT);
	delay_ms(120);

	//===============frame set========================
	//Frame rate = fosc / ((RTNA x 2 + 40) x (LINE + FPA + BPA + 2))
	lcd_write(TFT_CMD, LCD_FRMCTR1);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	
//	lcd_write(TFT_CMD, LCD_FRMCTR2);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	
//	lcd_write(TFT_CMD, LCD_FRMCTR3);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
//	lcd_write(TFT_DATA, 0x02);
//	lcd_write(TFT_DATA, 0x35);
//	lcd_write(TFT_DATA, 0x36);
	
	lcd_write(TFT_CMD, LCD_FRMCTR1);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	lcd_write(TFT_CMD, LCD_FRMCTR2);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	lcd_write(TFT_CMD, LCD_FRMCTR3);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	lcd_write(TFT_DATA, 0x01);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x2D);
	
	//===============inversion of control=============
	lcd_write(TFT_CMD, LCD_INVCRT);
	lcd_write(TFT_DATA, 0x03);

	//===============power set========================
	lcd_write(TFT_CMD, LCD_PWCTR1);
	lcd_write(TFT_DATA, 0xA2);
	lcd_write(TFT_DATA, 0x02);
	lcd_write(TFT_DATA, 0x84);
		
	lcd_write(TFT_CMD, LCD_PWCTR2);
	lcd_write(TFT_DATA, 0xC5);

	lcd_write(TFT_CMD, LCD_PWCTR3);
	lcd_write(TFT_DATA, 0x0D);
	lcd_write(TFT_DATA, 0x00);
	
	lcd_write(TFT_CMD, LCD_PWCTR4);
	lcd_write(TFT_DATA, 0x8D);
	lcd_write(TFT_DATA, 0x2A);
	
	lcd_write(TFT_CMD, LCD_PWCTR5);
	lcd_write(TFT_DATA, 0x8D);
	lcd_write(TFT_DATA, 0xEE);

	//===============vcom set=========================
	lcd_write(TFT_CMD, LCD_VMCTR1);
	lcd_write(TFT_DATA, 0x03);

	//===============color format set=================
	set_color_format(0x05);
	
	//===============scanning direction set===========
	set_scan_direction(0x08);
	
	//===============gamma sequence set===============
	lcd_write(TFT_CMD, LCD_GMCTRP1);
	lcd_write(TFT_DATA, 0x12);
	lcd_write(TFT_DATA, 0x1C);
	lcd_write(TFT_DATA, 0x10);
	lcd_write(TFT_DATA, 0x18);
	lcd_write(TFT_DATA, 0x33);
	lcd_write(TFT_DATA, 0x2C);
	lcd_write(TFT_DATA, 0x25);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x27);
	lcd_write(TFT_DATA, 0x2F);
	lcd_write(TFT_DATA, 0x3C);
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x10);

	lcd_write(TFT_CMD, LCD_GMCTRN1);
	lcd_write(TFT_DATA, 0x12);
	lcd_write(TFT_DATA, 0x1C);
	lcd_write(TFT_DATA, 0x10);
	lcd_write(TFT_DATA, 0x18);
	lcd_write(TFT_DATA, 0x2D);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x23);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x28);
	lcd_write(TFT_DATA, 0x26);
	lcd_write(TFT_DATA, 0x2F);
	lcd_write(TFT_DATA, 0x3B);
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x03);
	lcd_write(TFT_DATA, 0x10);

	//===============partial area set=================
	lcd_write(TFT_CMD, LCD_PTLAR);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x00);             
	lcd_write(TFT_DATA, 0x80);
	
	//===============partial mode on==================
	lcd_write(TFT_CMD, LCD_PTLON);

	//===============display on=======================
	lcd_write(TFT_CMD, LCD_DISPON);
}

void lcd_reset() {
	LCD_RESRT = 1;
	delay_ms(60);
	LCD_RESRT = 0;
	delay_ms(120);
	LCD_RESRT = 1;
	delay_ms(60);
}

void lcd_write(u8 c_d, u8 data) {
	LCD_CMD_DATA = c_d;
	SPI_CS = 0;
	spi_write(data);
	SPI_CS = 1;
}

void set_background(u16 color) {
	u8 i,j;
	set_frame_size(0,0x7F,0x00,0x7F);

	LCD_CMD_DATA = TFT_DATA;
	SPI_CS = 0;

	for(i = 0; i < 128; i ++) {
		for(j = 0; j < BUF_SIZE; j ++) {
			dma_data[j * 2] = color >> 8;
			dma_data[j * 2 + 1] = color;
		}
		dma1_to_spi1(DMA1_Channel3, 2 * BUF_SIZE, SPI_I2S_DMAReq_Tx, DMA1_FLAG_TC3);
	}

	SPI_CS = 1;
}

void set_scan_direction(u8 data) {
	lcd_write(TFT_CMD, LCD_MADCTL);
	lcd_write(TFT_DATA, data);
}

void set_color_format(u8 data) {
	lcd_write(TFT_CMD, LCD_COLMOD);
	lcd_write(TFT_DATA, data);
}

void set_frame_size(u16 x_start, u16 x_end, u16 y_start, u16 y_end) {
	lcd_write(TFT_CMD, LCD_CASET);
	lcd_write(TFT_DATA, x_start >> 8);
	lcd_write(TFT_DATA, x_start);
	lcd_write(TFT_DATA, x_end >> 8);
	lcd_write(TFT_DATA, x_end);
	
	lcd_write(TFT_CMD, LCD_RASET);
	lcd_write(TFT_DATA, y_start >> 8);
	lcd_write(TFT_DATA, y_start);
	lcd_write(TFT_DATA, y_end >> 8);
	lcd_write(TFT_DATA, y_end);
	
	lcd_write(TFT_CMD, LCD_RAMWR);
}

void set_point(u16 x, u16 y, u16 color) {
	set_frame_size(x, x + 1, y, y + 1);

	lcd_write(TFT_DATA, color >> 8);
	lcd_write(TFT_DATA, color);
}

void set_rectangle(u16 x_start, u16 x_end, u16 y_start, u16 y_end, u16 color) {
	u8 i, j, w, h;
	
	w = x_end - x_start;
	h = y_end - y_start;
	
	set_frame_size(x_start, x_end, y_start, y_end);
	
	for(i = 0; i < w; i ++) {
	    for(j = 0; j < h; j ++) {
			lcd_write(TFT_DATA, color >> 8);
			lcd_write(TFT_DATA, color);
		}
	}
}

void DispGrayHor16(void) {
	u8 i,j,k;

   	set_frame_size(0, 127, 0, 127);

	for(i = 0;i < 128; i ++) {	
		for(j=0;j<16;j++) {
	        for(k=0;k< 128 / 16; k ++) {		
				lcd_write(TFT_DATA, ((j*2)<<3)|((j*4)>>3));		 
				lcd_write(TFT_DATA, ((j*4)<<5)|(j*2));
			} 
		}
	}
}

void DispFrame(void) {
	u8 i,j;
	
	set_frame_size(0, 127, 0, 127);

	lcd_write(TFT_DATA, 0xF8);
	lcd_write(TFT_DATA, 0x00);
	
	for(i = 0; i < 126; i ++){
		lcd_write(TFT_DATA, 0xFF);
		lcd_write(TFT_DATA, 0xFF);
	}
	
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x1F);

	for(j = 0; j < 126; j ++)
	{
		lcd_write(TFT_DATA, 0xF8);
		lcd_write(TFT_DATA, 0x00);
		for(i = 0; i < 126; i ++) {
			lcd_write(TFT_DATA, 0x00);
			lcd_write(TFT_DATA, 0x00);
		}
		
		lcd_write(TFT_DATA, 0x00);
		lcd_write(TFT_DATA, 0x1F);
	}
	
	lcd_write(TFT_DATA, 0xf8);
	lcd_write(TFT_DATA, 0x00);
	
	for(i=0;i<126;i++){
		lcd_write(TFT_DATA, 0xFF);
		lcd_write(TFT_DATA, 0xFF);
	}
	
	lcd_write(TFT_DATA, 0x00);
	lcd_write(TFT_DATA, 0x1F);
	
}

void DispBand(void) {
	u8 i,j,k;
	u16 color[8]={0x001f,0x07e0,0xf800,0x07ff,0xf81f,0xffe0,0x0000,0xffff};
//	u16 color[8]={0xf800,0xf800,0x07e0,0x07e0,0x001f,0x001f,0xffff,0xffff};//0x94B2
	//unsigned int gray16[]={0x0000,0x1082,0x2104,0x3186,0x42,0x08,0x528a,0x630c,0x738e,0x7bcf,0x9492,0xa514,0xb596,0xc618,0xd69a,0xe71c,0xffff};

	lcd_write(TFT_CMD, 0x36); //Set Scanning Direction
	lcd_write(TFT_DATA, 0x08); //0xc8

   	set_frame_size(0, 127, 0, 127);																								  

	for(i=0;i < 8;i++)
	{
		for(j=0;j < 128 / 8;j++)
		{
	        for(k = 0;k < 128;k ++)
			{
				lcd_write(TFT_DATA, color[i]>>8); 
				lcd_write(TFT_DATA, color[i]);   
			} 
		}
	}
}

void DispPic(u8 x, u8 y, u8 w, u8 h, const u8 *p) {
	u16 i, j;

	set_frame_size(x, x + w - 1, y, y + h - 1);

	LCD_CMD_DATA = TFT_DATA;
	SPI_CS = 0;

	for(i = 0; i < h; i ++) {
		for(j = 0; j < w; j ++) {
			dma_data[j * 2] = *(p + 1);
			dma_data[j * 2 + 1] = *p;
			p += 2;
		}
		dma1_to_spi1(DMA1_Channel3, 2 * BUF_SIZE, SPI_I2S_DMAReq_Tx, DMA1_FLAG_TC3);
	}

	SPI_CS = 1;
}
//lcd.h
#ifndef __LCD_H
#define __LCD_H

#include "sys.h"
#include "spi.h"
#include "dma.h"

#define LCD_RCC_ENABLE		RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOF

#define LCD_RESRT 		PBout(2)
#define LCD_CMD_DATA	PBout(1)
#define LCD_BACK_LIGHT	PFout(11)

#define LCD_RESET_MODE			GPIO_Mode_Out_PP
#define LCD_RESET_PIN			GPIO_Pin_2
#define LCD_RESET_SPEED			GPIO_Speed_50MHz
#define LCD_RESET_GPIO			GPIOB

#define LCD_CMD_DATA_MODE		GPIO_Mode_Out_PP
#define LCD_CMD_DATA_PIN		GPIO_Pin_1
#define LCD_CMD_DATA_SPEED		GPIO_Speed_50MHz
#define LCD_CMD_DATA_GPIO		GPIOB

#define LCD_BACK_LIGHT_MODE		GPIO_Mode_Out_PP
#define LCD_BACK_LIGHT_PIN		GPIO_Pin_11
#define LCD_BACK_LIGHT_SPEED	GPIO_Speed_50MHz
#define LCD_BACK_LIGHT_GPIO		GPIOF

#define LCD_NOP			0x00	//空命令
#define LCD_SWRESET		0x01	//软件复位,在睡眠和显示模式下,重置软件后需等待120ms后方可执行下一条指令
#define LCD_RDDID		0x04	//读取LCD的制造商ID(8位)、驱动版本ID(最高位为1,7位)、驱动程序ID(8位)
#define LCD_RDDST		0x09	//读取显示屏所有状态参数
#define LCD_RDDPM		0x0A	//读取显示屏能量模式
#define LCD_RDDMADCTL	0x0B	//读取显示屏MADCTL
#define LCD_RDDCOLMOD	0x0C	//读取显示屏像素定义
#define LCD_RDDIM		0x0D	//读取显示屏图片模式
#define LCD_RDDSM		0x0E	//读取显示屏单信号模式
#define LCD_RDDSDR		0x0F	//读取显示屏自我诊断结果
#define LCD_SLPIN		0x10	//进入最小功耗模式
#define LCD_SLPOUT 		0x11	//关闭睡眠模式
#define LCD_PTLON		0x12	//打开Partial模式
#define LCD_NORON		0x13	//恢复到正常模式
#define LCD_INVOFF		0x20	//显示反转模式中恢复
#define LCD_INVON		0x21	//进入反向显示模式
#define LCD_GAMSET		0x26	//当前显示选择所需的伽马曲线
#define LCD_DISPOFF		0x28	//关闭显示,帧内存的输出被禁用
#define LCD_DISPON		0x29	//开启显示,帧内存的输出被启用
#define LCD_CASET		0x2A	//列地址设置,每个值代表帧内存中的一列
#define LCD_RASET		0x2B	//行地址设置,每个值代表帧内存中的一列
#define LCD_RAMWR		0x2C	//写入内存
#define LCD_RGBSET		0x2D	//颜色模式设置
#define LCD_RAMRD		0x2E	//读取内存
#define LCD_PTLAR		0x30	//部分模式的显示区域设置
#define LCD_SCRLAR		0x33	//定义垂直滚动区域的显示
#define LCD_TEOFF		0x34	//关闭(Active Low) TE信号线的撕裂效应输出信号
#define LCD_TEON		0x35	//打开TE信号线的撕裂效果输出信号
#define LCD_MADCTL		0x36	//定义帧内存的读写扫描方向
#define LCD_VSCSAD		0x37	//设置垂直滚动起始地址,此命令与垂直滚动定义(33h)一起使用
#define LCD_IDMOFF		0x38	//关闭空闲模式
#define LCD_IDMON		0x39	//开启空闲模式
#define LCD_COLMOD		0x3A	//定义通过MCU接口传输的RGB图片数据的格式
#define LCD_FRMCTR1		0xB1	//设置全色正常模式的帧频
#define LCD_FRMCTR2 	0xB2	//设置空闲模式的帧频
#define LCD_FRMCTR3 	0xB3	//设置部分模式/全色的帧频率
#define LCD_INVCRT 		0xB4	//反转模式控制
#define LCD_PWCTR1 		0xC0	//设置AVDD、MODE、VRHP、VRHN
#define LCD_PWCTR2 		0xC1	//设置VGH与VGL的供电功率
#define LCD_PWCTR3 		0xC2	//设置正常模式/全色模式下的运放的电流
#define LCD_PWCTR4 		0xC3	//设置空闲模式/八色模式下的运放的电流
#define LCD_PWCTR5 		0xC4	//设置部分模式/全色模式下的运放的电流
#define LCD_VMCTR1 		0xC5	//设置VCOM电压电平以减少闪烁问题
#define LCD_VMOFCTR		0xC7	//VCOM偏移控制,在使用命令0xC7之前,命令0xD9的位VMF_EN必须启用(设置为1)
#define LCD_WRID2		0xD1	//写入LCD模块版本的7位数据,保存到NVM
#define LCD_WRID3		0xD2	//写入项目代码模块的8位数据,保存到NVM
#define LCD_NVFCTR1		0xD9	//NVM状态控制
#define LCD_RDID1		0xDA	//读字节返回8位LCD模块的制造商ID
#define LCD_RDID2		0xDB	//读字节返回8位LCD模块/驱动程序版本ID
#define LCD_RDID3		0xDC	//读字节返回8位LCD模块/驱动ID
#define LCD_NVFCTR2		0xDE	//NVM读取命令
#define LCD_NVFCTR3		0xDF	//NVM写取命令
#define LCD_GMCTRP1		0xE0	//Gamma ‘+’ Polarity Correction Characteristics Setting
#define LCD_GMCTRN1		0xE1	//Gamma ‘+’ Polarity Correction Characteristics Setting
#define LCD_GCV			0xFC	//自动调节门泵时钟,节省功耗


enum TFT_DATA_TYPE {
	TFT_CMD = 0,
	TFT_DATA
};

void lcd_init(void);
void lcd_config(void);
void lcd_reset(void);
void lcd_write(u8 c_d, u8 data);
void set_background(u16 color);
void set_scan_direction(u8 data);
void set_color_format(u8 data);
void set_frame_size(u16 x_start, u16 x_end, u16 y_start, u16 y_end);
void set_point(u16 x, u16 y, u16 color);
void set_rectangle(u16 x_start, u16 x_end, u16 y_start, u16 y_end, u16 color);
void DispGrayHor16(void);
void DispFrame(void);
void DispBand(void);
void DispPic(u8 x,u8 y,u8 w, u8 h,const u8 *p);

#endif	//__LCD_H

以上就是混子近段时间的研究成果吧,有很多东西还是参考了别人的,这里都分享出来,不提供源代码哈,感谢观看!

这里特别说明一下DMA配SPI,我测出来的刷帧速率最快能够达到50多帧每秒,慢点也是30多帧每秒,参数可以自己多配配,或者问问芯片原厂,具体咋操作我不是专业的,也不是很懂,我的参数部分来源于网络,部分来源于demo,理解万岁。

学习分享,一起成长!以上为小编的学习经验分享,若存在不当之处,请批评指正!文章来源地址https://www.toymoban.com/news/detail-789219.html

到了这里,关于STM32进阶:使用STM32驱动ST7735S(内附核心源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【快速上手STM32】SPI通信协议&&1.8寸TFT-LCD(ST7735S)

    SPI,英文全称Serial Peripheral Interface,即串行外围设备接口,是一种高速、全双工、同步的串行通信总线。 我们之前说过I2C,那么我们就拿I2C和SPI做个对比。 SPI和I2C对比,优势在于SPI的传输速率比I2C快得多,劣势在于SPI需要用的通信线比较多。 I2C只需要两根线,而SPI至少需要

    2024年04月27日
    浏览(37)
  • 在f1c100s上移植fbtft驱动st7735s小屏幕

    内核版本5.4 在使用spi总线接上了一个小网卡,实现了我们开发板对网络的访问之后,我还想接一个小的spi屏幕 1.44寸款,来画一只小企鹅,顺便显示一些系统的调试信息。但是由于我这个开发板向外暴露出来的spi接口就两个,而且有一个已经因为串口的设置而不能使用。所以

    2024年02月10日
    浏览(42)
  • 给linux移植fbtft驱动st7735s小屏幕(f1c100s)

    内核版本5.4 在使用spi总线接上了一个小网卡,实现了我们开发板对网络的访问之后,我还想接一个小的spi屏幕 1.44寸款,来画一只小企鹅,顺便显示一些系统的调试信息。但是由于我这个开发板向外暴露出来的spi接口就两个,而且有一个已经因为串口的设置而不能使用。所以

    2024年02月10日
    浏览(45)
  • 1.8寸TFT LCD128X160 ST7735S SPI串口屏驱动示例

    🌼1.8寸TFT LCD128X160 ST7735S SPI串口屏 📚屏幕驱动资料1 以下是由中景园提供的,里面包含了: 由于购买的是合宙的1.8寸TFT LCD128X160 ST7735S SPI串口屏随同ESP32C3一起购买的,价格是9.9RMB,比起中景园的相同规格的屏幕是16.5RMB,性价比还是很高的。 🛠汉字取模方式和软件 🔧 PCto

    2024年01月22日
    浏览(40)
  • STM32驱动ST7735彩色屏幕(任意分辨率),驱动不了你来打我

    驱动方式 硬件SPI 适用STM32型号 带SPI的任意型号,驱动不了你来打我(内心OS:HAL真好) 特别提醒 以下内容介绍如何使用HAL方式驱动ST7735,所以默认 你已经了解并且会使用STM32CubeMX软件 (如果没有接触过的话建议先安装尝试一下再继续以下内容,不然有种囫囵吞枣的意思了)

    2023年04月15日
    浏览(65)
  • STM32驱动ST7735彩色屏幕(任意分辨率),驱动不了你顺着网线来打我

    驱动方式 硬件SPI 适用STM32型号 带SPI的任意型号,驱动不了你来打我(内心OS:HAL真好) 特别提醒 以下内容介绍如何使用HAL方式驱动ST7735,所以默认 你已经了解并且会使用STM32CubeMX软件 (如果没有接触过的话建议先安装尝试一下再继续以下内容,不然有种囫囵吞枣的意思了)

    2023年04月23日
    浏览(51)
  • ST7735S应用笔记

    ST7735S是一块1.8英寸采用SPI通信的TFT全彩屏,分辨率是128*160,这里采用RGB565 16bit的色块编译模式(RGB565即高五位为Red,第五位为Blue,中间六位为Green,共16位)。本文仅设计该屏幕的简单应用,不对底层原理进行深究。 BLK:这里用不到,可以不用连接 CS:片选信号 DC:数据模

    2024年02月04日
    浏览(33)
  • ESP32C3 移植ST7735 LVGL

    关于lvgl LVGL是一个C语言编写的免费的开源图形库,其提供了用于嵌入式GUI的各种元素。用户可以利用丰富的图形库资源,在消耗极低内存的情况下构建视觉效果丰富多彩的GUI 。只需 64kB 闪存和 8kB RAM 就足以满足简单的用户界面。LVGL 可以驱动单色OLED、TFT 显示器、监视器或任

    2023年04月24日
    浏览(50)
  • STM32CubeIDE更新ST LINK驱动失败解决方法

    当使用CubeIDE下载程序时,在这里遇到个STM32CubeIDE需要ST Link更新的提示 弹出 “in order to use the attached ST-LINK with this version of STM32CubeIDE an update of the ST LINK firmware is required” “为了将连接的ST-LINK与此版本的STM32CubeIDE一起使用,需要更新ST-LINK固件” 但是使用Cube更新失败的情况,

    2024年02月16日
    浏览(45)
  • 【STM32开发环境搭建】 - st-link驱动安装和串口驱动安装

    下载地址:https://download.csdn.net/download/weixin_39035140/86248921 包含软件如下: 1、下载线我们使用了st-link,为了能够下载程序到开发板,需要先安装st-link驱动。打开设备管理器,可以通过热插拔法确认是哪一个设备(STM32 STLink显示感叹号就是缺少驱动),右击更新驱动,选择浏览

    2024年02月12日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包