最近在学习正点原子潘多拉开发板,在此结合原子哥的代码,
对SPI驱动LCD做一个详细介绍。
TFT-LCD 即薄膜晶体管液晶显示器。其英文全称为:Thin Film Transistor-Liquid Crystal Display。TFT-LCD 与无源TN-LCD、STN-LCD 的简单矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD 也被叫做真彩液晶显示器。
SPI 是英语Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX 系列处理器上定义的。SPI 接口主要应用在 EEPROM,FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB 的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,STM32L4 也有SPI 接口。
spi.h
void SPI3_Init(void);
void SPI3_SetSpeed(u8 SPI_BaudRatePrescaler); // 设置波特率传输速度
u8 SPI3_ReadWriteByte(u8 TxData); // 读写数据
u8 SPI3_WriteByte(u8 *TxData,u16 size); // 写字节
spi.c
#include "spi3.h"
#include "delay.h"
SPI_HandleTypeDef SPI3_Handler; // 生成SPI3句柄
/**
* 功能描述:SPI3初始化代码,配置成主机模式
*
* 参数: void
*
* 返回值:void
*/
void SPI3_Init(void)
{
SPI3_Handler.Instance=SPI3; //SPI3
SPI3_Handler.Init.Mode=SPI_MODE_MASTER; //设置SPI工作模式,设置为主模式
SPI3_Handler.Init.Direction=SPI_DIRECTION_2LINES; //设置SPI单向或者双向的数据模式:SPI设置为双线模式
SPI3_Handler.Init.DataSize=SPI_DATASIZE_8BIT; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI3_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH; //串行同步时钟的空闲状态为高电平
SPI3_Handler.Init.CLKPhase=SPI_PHASE_2EDGE; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样,偶数个跳变沿时被采样
SPI3_Handler.Init.NSS=SPI_NSS_SOFT; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI3_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2;//定义波特率预分频的值:波特率预分频值为256
SPI3_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI3_Handler.Init.TIMode=SPI_TIMODE_DISABLE; //关闭TI模式
SPI3_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
SPI3_Handler.Init.CRCPolynomial=7; //CRC值计算的多项式
HAL_SPI_Init(&SPI3_Handler); //初始化SPI3
__HAL_SPI_ENABLE(&SPI3_Handler); //使能SPI3
}
/**
* @brief SPI3底层驱动,时钟使能,引脚配置
*
* @param hspi SPI句柄
*
* @return void
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
__HAL_RCC_SPI3_CLK_ENABLE(); //使能SPI3时钟
//PB3.5
GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_5; // 先看复用配置,看到PB3,4,5为复用功能,然后3,5属于从主机输出到IO口,所以需要选用复用推挽输出
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //80Mhz
GPIO_Initure.Alternate=GPIO_AF6_SPI3; //PB3.5复用为SPI3
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
}
/**
* 功能描述:SPI3 读写一个字节
*
* 参数:TxData 要写入的字节
*
* 返回值:u8 读取到的字节
*/
u8 SPI3_ReadWriteByte(u8 TxData)
{
u8 Rxdata;
HAL_SPI_TransmitReceive(&SPI3_Handler,&TxData,&Rxdata,1, 1000);
return Rxdata; //返回收到的数据
}
/**
* 功能描述:SPI3 写入一个字节
*
* 参数:TxData 要写入的字节
* size 写入字节大小
*
* 返回值:u8 0:写入成功,其他:写入失败
*/
u8 SPI3_WriteByte(u8 *TxData,u16 size)
{
return HAL_SPI_Transmit(&SPI3_Handler,TxData,size,1000); // 发送数据,并等待1000us
}
lcd.h
#ifndef __LCD_H
#define __LCD_H
#include "sys.h"
extern u16 POINT_COLOR; //默认画笔颜色
extern u16 BACK_COLOR; //默认背景颜色
//LCD的宽和高定义
#define LCD_Width 240
#define LCD_Height 240
//画笔颜色
#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 //浅棕蓝色(选择条目的反色)
/*
LCD_PWR: PB7
LCD_RST: PB6
LCD_DC: PB4
LCD_CS: PD7
*/
#define LCD_PWR(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET)) // 背光控制
#define LCD_RST(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET)) // 复位控制
#define LCD_DC(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET)) // 选择数据或命令
#define LCD_CS(n) (n?HAL_GPIO_WritePin(GPIOD,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOD,GPIO_PIN_7,GPIO_PIN_RESET)) // 片选
void LCD_Init(void); //初始化
void LCD_DisplayOn(void); //开显示
void LCD_DisplayOff(void); //关显示
void LCD_Write_HalfWord(const u16 da); //写半个字节数据到LCD
void LCD_Address_Set(u16 x1, u16 y1, u16 x2, u16 y2); //设置数据显示区域
void LCD_Clear(u16 color); //清屏
void LCD_Fill(u16 x_start, u16 y_start, u16 x_end, u16 y_end, u16 color); //填充单色
void LCD_Draw_Point(u16 x, u16 y); //画点
void LCD_Draw_ColorPoint(u16 x, u16 y,u16 color); //画带颜色点
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2); //画线
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2); //画矩形
void LCD_Draw_Circle(u16 x0, u16 y0, u8 r); //画圆
void LCD_ShowChar(u16 x, u16 y, char chr, u8 size); //显示一个字符
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size); //显示一个数字
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode); //显示数字
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,char *p);//显示字符串
void LCD_ShowChinese(u16 x, u16 y, const u8 *ch, u8 size, u8 n, u8 mode); // 显示汉字
void LCD_Show_Image(u16 x, u16 y, u16 width, u16 height, const u8 *p);//显示图片
#endif
由于lcd.c文件中内容过多,所以在此不显示,在lcd.c文件中,可以添加需要显示的内容,比如数字、字符串等等。