硬件连接
我购买的是ili9341,2.8inch,带触摸
开发板是野火stm32f407霸天虎
LCD模块 | STM32单片机 |
---|---|
VCC | DC5V/3.3V |
GND | GND |
SDI(MOSI) | PB5 |
SDO(MISO) | PB4 |
LED | PB13 |
SCK | PB3 |
DC/RS | PB14 |
RST | PB12 |
CS | PB15 |
触摸连接 | |
T_IRQ | PB1 |
T_DO | PB2 |
T_DIN | PF11 |
T_CS | PC5 |
T_CLK | PB0 |
初始化
本次使用的是硬件SPI1,对应的(MOSI)PB5,(MISO)PB4,SCK PB3,CS片选引脚可以自定义。
spi.c
#include "spi.h"/****************************************************************************** @name :u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)* @date :2018-08-09* @function :Write a byte of data using STM32's hardware SPI* @parameters :SPIx: SPI type,x for 1,2,3Byte:Data to be written* @retvalue :Data received by the bus
******************************************************************************/
u8 SPI_WriteByte(SPI_TypeDef *SPIx, u8 Byte)
{while ((SPIx->SR & SPI_I2S_FLAG_TXE) == RESET); // 等待发送区空SPIx->DR = Byte; // 发送一个bytewhile ((SPIx->SR & SPI_I2S_FLAG_RXNE) == RESET); // 等待接收完一个bytereturn SPIx->DR; // 返回收到的数据
}/****************************************************************************** @name :void SPI_SetSpeed(SPI_TypeDef* SPIx,u8 SpeedSet)* @date :2018-08-09* @function :Set hardware SPI Speed* @parameters :SPIx: SPI type,x for 1,2,3SpeedSet:0-high speed1-low speed* @retvalue :None
******************************************************************************/
void SPI_SetSpeed(SPI_TypeDef *SPIx, u8 SpeedSet)
{SPIx->CR1 &= 0XFFC7;if (SpeedSet == 1) // 高速{SPIx->CR1 |= SPI_BaudRatePrescaler_2; // Fsck=Fpclk/2}else // 低速{SPIx->CR1 |= SPI_BaudRatePrescaler_32; // Fsck=Fpclk/32}SPIx->CR1 |= 1 << 6; // SPI设备使能
}/****************************************************************************** @name :void SPI1_Init(void)* @date :2018-08-09* @function :Initialize the STM32 hardware SPI1* @parameters :None* @retvalue :None******************************************************************************/
void SPI1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 使能GPIOB时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // 使能SPI1时钟// GPIOFB3,4,5初始化设置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; // PB3~5复用功能输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用功能GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1); // PB3复用为 SPI1GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1); // PB4复用为 SPI1GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1); // PB5复用为 SPI1// 这里只针对SPI口初始化RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE); // 复位SPI1RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE); // 停止复位SPI1SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 串行同步时钟的空闲状态为高电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 串行同步时钟的第二个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制// SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //定义波特率预分频的值:波特率预分频值为256SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC值计算的多项式SPI_Init(SPI1, &SPI_InitStructure); // 根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器SPI_Cmd(SPI1, ENABLE); // 使能SPI外设
}
spi.h
#include "sys.h"#ifndef _SPI_H_
#define _SPI_H_//本测试程序使用的是硬件SPI接口驱动
//除了SPI时钟信号以及SPI读、写信号引脚不可更改,其他引脚都可以更改
//SPI的时钟引脚定义固定为PB3
//SPI的读数据引脚定义固定为PB4
//SPI的写数据引脚定义固定为PB5u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte);
void SPI1_Init(void);
void SPI_SetSpeed(SPI_TypeDef* SPIx,u8 SpeedSet);#endif
TFT屏驱动
lcd.c
#include "lcd.h"
#include "stdlib.h"
#include "delay.h"
#include "spi.h"// 管理LCD重要参数
// 默认为竖屏
_lcd_dev lcddev;// 画笔颜色,背景颜色
u16 POINT_COLOR = 0x0000, BACK_COLOR = 0xFFFF;
u16 DeviceCode;/****************************************************************************** @name :void LCD_WR_REG(u8 data)* @date :2018-08-09* @function :Write an 8-bit command to the LCD screen* @parameters :data:Command value to be written* @retvalue :None******************************************************************************/
void LCD_WR_REG(u8 data)
{LCD_CS_CLR;LCD_RS_CLR;SPI_WriteByte(SPI1, data);LCD_CS_SET;
}/****************************************************************************** @name :void LCD_WR_DATA(u8 data)* @date :2018-08-09* @function :Write an 8-bit data to the LCD screen* @parameters :data:data value to be written* @retvalue :None******************************************************************************/
void LCD_WR_DATA(u8 data)
{LCD_CS_CLR;LCD_RS_SET;SPI_WriteByte(SPI1, data);LCD_CS_SET;
}/****************************************************************************** @name :void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)* @date :2018-08-09* @function :Write data into registers* @parameters :LCD_Reg:Register addressLCD_RegValue:Data to be written* @retvalue :None
******************************************************************************/
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{LCD_WR_REG(LCD_Reg);LCD_WR_DATA(LCD_RegValue);
}/****************************************************************************** @name :void LCD_WriteRAM_Prepare(void)* @date :2018-08-09* @function :Write GRAM* @parameters :None* @retvalue :None******************************************************************************/
void LCD_WriteRAM_Prepare(void)
{LCD_WR_REG(lcddev.wramcmd);
}/****************************************************************************** @name :void Lcd_WriteData_16Bit(u16 Data)* @date :2018-08-09* @function :Write an 16-bit command to the LCD screen* @parameters :Data:Data to be written* @retvalue :None******************************************************************************/
void Lcd_WriteData_16Bit(u16 Data)
{LCD_CS_CLR;LCD_RS_SET;SPI_WriteByte(SPI1, Data >> 8);SPI_WriteByte(SPI1, Data);LCD_CS_SET;
}/****************************************************************************** @name :void LCD_DrawPoint(u16 x,u16 y)* @date :2018-08-09* @function :Write a pixel data at a specified location* @parameters :x:the x coordinate of the pixely:the y coordinate of the pixel* @retvalue :None
******************************************************************************/
void LCD_DrawPoint(u16 x, u16 y)
{LCD_SetCursor(x, y); // 设置光标位置Lcd_WriteData_16Bit(POINT_COLOR);
}/****************************************************************************** @name :void LCD_Clear(u16 Color)* @date :2018-08-09* @function :Full screen filled LCD screen* @parameters :color:Filled color* @retvalue :None******************************************************************************/
void LCD_Clear(u16 Color)
{unsigned int i, m;LCD_SetWindows(0, 0, lcddev.width - 1, lcddev.height - 1);LCD_CS_CLR;LCD_RS_SET;for (i = 0; i < lcddev.height; i++){for (m = 0; m < lcddev.width; m++){Lcd_WriteData_16Bit(Color);}}LCD_CS_SET;
}/****************************************************************************** @name :void LCD_Clear(u16 Color)* @date :2018-08-09* @function :Initialization LCD screen GPIO* @parameters :None* @retvalue :None******************************************************************************/
void LCD_GPIOInit(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 普通输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉GPIO_Init(GPIOB, &GPIO_InitStructure);
}/****************************************************************************** @name :void LCD_RESET(void)* @date :2018-08-09* @function :Reset LCD screen* @parameters :None* @retvalue :None******************************************************************************/
void LCD_RESET(void)
{LCD_RST_CLR;delay_ms(100);LCD_RST_SET;delay_ms(50);
}/****************************************************************************** @name :void LCD_RESET(void)* @date :2018-08-09* @function :Initialization LCD screen* @parameters :None* @retvalue :None******************************************************************************/
void LCD_Init(void)
{SPI1_Init(); // 硬件SPI初始化// SPI_SetSpeed(SPI1,SPI_BaudRatePrescaler_2);LCD_GPIOInit(); // LCD GPIO初始化LCD_RESET(); // LCD 复位//*************2.8inch ILI9341初始化**********//LCD_WR_REG(0xCF);LCD_WR_DATA(0x00);LCD_WR_DATA(0xC9); // C1LCD_WR_DATA(0X30);LCD_WR_REG(0xED);LCD_WR_DATA(0x64);LCD_WR_DATA(0x03);LCD_WR_DATA(0X12);LCD_WR_DATA(0X81);LCD_WR_REG(0xE8);LCD_WR_DATA(0x85);LCD_WR_DATA(0x10);LCD_WR_DATA(0x7A);LCD_WR_REG(0xCB);LCD_WR_DATA(0x39);LCD_WR_DATA(0x2C);LCD_WR_DATA(0x00);LCD_WR_DATA(0x34);LCD_WR_DATA(0x02);LCD_WR_REG(0xF7);LCD_WR_DATA(0x20);LCD_WR_REG(0xEA);LCD_WR_DATA(0x00);LCD_WR_DATA(0x00);LCD_WR_REG(0xC0); // Power controlLCD_WR_DATA(0x1B); // VRH[5:0]LCD_WR_REG(0xC1); // Power controlLCD_WR_DATA(0x00); // SAP[2:0];BT[3:0] 01LCD_WR_REG(0xC5); // VCM controlLCD_WR_DATA(0x30); // 3FLCD_WR_DATA(0x30); // 3CLCD_WR_REG(0xC7); // VCM control2LCD_WR_DATA(0XB7);LCD_WR_REG(0x36); // Memory Access ControlLCD_WR_DATA(0x08);LCD_WR_REG(0x3A);LCD_WR_DATA(0x55);LCD_WR_REG(0xB1);LCD_WR_DATA(0x00);LCD_WR_DATA(0x1A);LCD_WR_REG(0xB6); // Display Function ControlLCD_WR_DATA(0x0A);LCD_WR_DATA(0xA2);LCD_WR_REG(0xF2); // 3Gamma Function DisableLCD_WR_DATA(0x00);LCD_WR_REG(0x26); // Gamma curve selectedLCD_WR_DATA(0x01);LCD_WR_REG(0xE0); // Set GammaLCD_WR_DATA(0x0F);LCD_WR_DATA(0x2A);LCD_WR_DATA(0x28);LCD_WR_DATA(0x08);LCD_WR_DATA(0x0E);LCD_WR_DATA(0x08);LCD_WR_DATA(0x54);LCD_WR_DATA(0XA9);LCD_WR_DATA(0x43);LCD_WR_DATA(0x0A);LCD_WR_DATA(0x0F);LCD_WR_DATA(0x00);LCD_WR_DATA(0x00);LCD_WR_DATA(0x00);LCD_WR_DATA(0x00);LCD_WR_REG(0XE1); // Set GammaLCD_WR_DATA(0x00);LCD_WR_DATA(0x15);LCD_WR_DATA(0x17);LCD_WR_DATA(0x07);LCD_WR_DATA(0x11);LCD_WR_DATA(0x06);LCD_WR_DATA(0x2B);LCD_WR_DATA(0x56);LCD_WR_DATA(0x3C);LCD_WR_DATA(0x05);LCD_WR_DATA(0x10);LCD_WR_DATA(0x0F);LCD_WR_DATA(0x3F);LCD_WR_DATA(0x3F);LCD_WR_DATA(0x0F);LCD_WR_REG(0x2B);LCD_WR_DATA(0x00);LCD_WR_DATA(0x00);LCD_WR_DATA(0x01);LCD_WR_DATA(0x3f);LCD_WR_REG(0x2A);LCD_WR_DATA(0x00);LCD_WR_DATA(0x00);LCD_WR_DATA(0x00);LCD_WR_DATA(0xef);LCD_WR_REG(0x11); // Exit Sleepdelay_ms(120);LCD_WR_REG(0x29); // display onLCD_direction(USE_HORIZONTAL); // 设置LCD显示方向LCD_LED = 1; // 点亮背光LCD_Clear(WHITE); // 清全屏白色
}/****************************************************************************** @name :void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)* @date :2018-08-09* @function :Setting LCD display window* @parameters :xStar:the bebinning x coordinate of the LCD display windowyStar:the bebinning y coordinate of the LCD display windowxEnd:the endning x coordinate of the LCD display windowyEnd:the endning y coordinate of the LCD display window* @retvalue :None
******************************************************************************/
void LCD_SetWindows(u16 xStar, u16 yStar, u16 xEnd, u16 yEnd)
{LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(xStar >> 8);LCD_WR_DATA(0x00FF & xStar);LCD_WR_DATA(xEnd >> 8);LCD_WR_DATA(0x00FF & xEnd);LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(yStar >> 8);LCD_WR_DATA(0x00FF & yStar);LCD_WR_DATA(yEnd >> 8);LCD_WR_DATA(0x00FF & yEnd);LCD_WriteRAM_Prepare(); // 开始写入GRAM
}/****************************************************************************** @name :void LCD_SetCursor(u16 Xpos, u16 Ypos)* @date :2018-08-09* @function :Set coordinate value* @parameters :Xpos:the x coordinate of the pixelYpos:the y coordinate of the pixel* @retvalue :None
******************************************************************************/
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{LCD_SetWindows(Xpos, Ypos, Xpos, Ypos);
}/****************************************************************************** @name :void LCD_direction(u8 direction)* @date :2018-08-09* @function :Setting the display direction of LCD screen* @parameters :direction:0-0 degree1-90 degree2-180 degree3-270 degree* @retvalue :None
******************************************************************************/
void LCD_direction(u8 direction)
{lcddev.setxcmd = 0x2A;lcddev.setycmd = 0x2B;lcddev.wramcmd = 0x2C;switch (direction){case 0:lcddev.width = LCD_W;lcddev.height = LCD_H;LCD_WriteReg(0x36, (1 << 3) | (0 << 6) | (0 << 7)); // BGR==1,MY==0,MX==0,MV==0break;case 1:lcddev.width = LCD_H;lcddev.height = LCD_W;LCD_WriteReg(0x36, (1 << 3) | (0 << 7) | (1 << 6) | (1 << 5)); // BGR==1,MY==1,MX==0,MV==1break;case 2:lcddev.width = LCD_W;lcddev.height = LCD_H;LCD_WriteReg(0x36, (1 << 3) | (1 << 6) | (1 << 7)); // BGR==1,MY==0,MX==0,MV==0break;case 3:lcddev.width = LCD_H;lcddev.height = LCD_W;LCD_WriteReg(0x36, (1 << 3) | (1 << 7) | (1 << 5)); // BGR==1,MY==1,MX==0,MV==1break;default:break;}
}
lcd.h
#ifndef __LCD_H
#define __LCD_H
#include "sys.h"
#include "stdlib.h"//LCD重要参数集
typedef struct
{ u16 width; //LCD 宽度u16 height; //LCD 高度u16 id; //LCD IDu8 dir; //横屏还是竖屏控制:0,竖屏;1,横屏。 u16 wramcmd; //开始写gram指令u16 setxcmd; //设置x坐标指令u16 setycmd; //设置y坐标指令
}_lcd_dev; //LCD参数
extern _lcd_dev lcddev; //管理LCD重要参数
/用户配置区///
#define USE_HORIZONTAL 0//定义液晶屏顺时针旋转方向 0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转//
//定义LCD的尺寸
#define LCD_W 240
#define LCD_H 320//TFTLCD部分外要调用的函数
extern u16 POINT_COLOR;//默认红色
extern u16 BACK_COLOR; //背景颜色.默认为白色
//-----------------LCD端口定义---------------- #define LED 13 //背光控制引脚
#define CS 15 //片选引脚
#define RS 14 //寄存器/数据选择引脚
#define RST 12 //复位引脚//QDtech全系列模块采用了三极管控制背光亮灭,用户也可以接PWM调节背光亮度
#define LCD_LED PBout(LED) //LCD背光
#define LCD_CS PBout(CS)
#define LCD_RS PBout(RS)
#define LCD_RST PBout(RST)
//如果使用官方库函数定义下列底层,速度将会下降到14帧每秒,建议采用我司推荐方法
//以下IO定义直接操作寄存器,快速IO操作,刷屏速率可以达到28帧每秒! #define LCD_CS_SET LCD_CS=1 //GPIO_TYPE->BSRRL=1<<LCD_CS //片选端口 PB11
#define LCD_RS_SET LCD_RS=1 //GPIO_TYPE->BSRRL=1<<LCD_RS //数据/命令 PB10
#define LCD_RST_SET LCD_RST=1 //GPIO_TYPE->BSRRL=1<<LCD_RST //复位 PB12#define LCD_CS_CLR LCD_CS=0 //GPIO_TYPE->BSRRH=1<<LCD_CS //片选端口 PB11
#define LCD_RS_CLR LCD_RS=0 //GPIO_TYPE->BSRRH=1<<LCD_RS //数据/命令 PB10
#define LCD_RST_CLR LCD_RST=0 //GPIO_TYPE->BSRRH=1<<LCD_RST //复位 PB12//画笔颜色
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
//GUI颜色#define DARKBLUE 0X01CF //深蓝色
#define LIGHTBLUE 0X7D7C //浅蓝色
#define GRAYBLUE 0X5458 //灰蓝色
//以上三色为PANEL的颜色 #define LIGHTGREEN 0X841F //浅绿色
#define LIGHTGRAY 0XEF5B //浅灰色(PANNEL)
#define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色)void LCD_Init(void);
void LCD_DisplayOn(void);
void LCD_DisplayOff(void);
void LCD_Clear(u16 Color);
void LCD_SetCursor(u16 Xpos, u16 Ypos);
void LCD_DrawPoint(u16 x,u16 y);//画点
u16 LCD_ReadPoint(u16 x,u16 y); //读点
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2);
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2);
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd);u16 LCD_RD_DATA(void);//读取LCD数据
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue);
void LCD_WR_DATA(u8 data);
u16 LCD_ReadReg(u8 LCD_Reg);
void LCD_WriteRAM_Prepare(void);
void LCD_WriteRAM(u16 RGB_Code);
u16 LCD_ReadRAM(void);
u16 LCD_BGR2RGB(u16 c);
void LCD_SetParam(void);
void Lcd_WriteData_16Bit(u16 Data);
void LCD_direction(u8 direction );//如果仍然觉得速度不够快,可以使用下面的宏定义,提高速度.
//注意要去掉lcd.c中void LCD_WR_DATA(u16 data)函数定义哦
/*
#if LCD_USE8BIT_MODEL==1//使用8位并行数据总线模式#define LCD_WR_DATA(data){\LCD_RS_SET;\LCD_CS_CLR;\DATAOUT(data);\LCD_WR_CLR;\LCD_WR_SET;\DATAOUT(data<<8);\LCD_WR_CLR;\LCD_WR_SET;\LCD_CS_SET;\}#else//使用16位并行数据总线模式#define LCD_WR_DATA(data){\LCD_RS_SET;\LCD_CS_CLR;\DATAOUT(data);\LCD_WR_CLR;\LCD_WR_SET;\LCD_CS_SET;\}
#endif
*/#endif
剩下的文件资源太多打包发成资源