感觉很久很久没有来博客更新了,历经千难万阻,终于做出来了TFT显示屏的SPI驱动,这里分享以下核心源码,接下来一段时间开始准备考科一了,后面有时间了再来更新,有三种模式下的驱动。
实验环境:正点原子 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
实验环境:正点原子 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
实验环境:正点原子 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,理解万岁。
学习分享,一起成长!以上为小编的学习经验分享,若存在不当之处,请批评指正!