[feat] add lcd driver
This commit is contained in:
parent
587c99a62e
commit
b74eceed5e
@ -7,6 +7,7 @@ src/stm32f4xx_tim.c
|
||||
src/stm32f4xx_spi.c
|
||||
src/stm32f4xx_usart.c
|
||||
src/stm32f4xx_dma.c
|
||||
src/stm32f4xx_tim.c
|
||||
)
|
||||
|
||||
add_library(driver STATIC ${FILELIST})
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "stm32f4xx_rcc.h"
|
||||
#include "led.h"
|
||||
#include "lcd.h"
|
||||
|
||||
volatile uint32_t system_tick_cnt;
|
||||
|
||||
@ -27,6 +28,7 @@ void system_init(void)
|
||||
{
|
||||
led_init();
|
||||
system_tick_init();
|
||||
lcd_init();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
@ -37,6 +39,7 @@ int main(void)
|
||||
__enable_irq();
|
||||
while (1) {
|
||||
led_loop();
|
||||
lcd_loop();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
file(GLOB FILELIST
|
||||
led.c
|
||||
lcd.c
|
||||
)
|
||||
|
||||
add_library(src STATIC ${FILELIST})
|
||||
|
||||
@ -0,0 +1,241 @@
|
||||
#include "stm32f4xx_rcc.h"
|
||||
#include "stm32f4xx_gpio.h"
|
||||
#include "stm32f4xx_spi.h"
|
||||
#include "stm32f4xx_dma.h"
|
||||
#include "stm32f4xx_tim.h"
|
||||
#include "lcd.h"
|
||||
|
||||
uint8_t lcd_buffer[LCD_PIX * 2];
|
||||
extern volatile uint32_t system_tick_cnt;
|
||||
|
||||
static void lcd_pin_cs_select(void)
|
||||
{
|
||||
GPIO_ResetBits(GPIOB, LCD_PIN_CS);
|
||||
}
|
||||
|
||||
static void lcd_pin_cs_disselect(void)
|
||||
{
|
||||
GPIO_SetBits(GPIOB, LCD_PIN_CS);
|
||||
}
|
||||
|
||||
static void lcd_pin_dc_cmd(void)
|
||||
{
|
||||
GPIO_ResetBits(GPIOB, LCD_PIN_DC);
|
||||
}
|
||||
|
||||
static void lcd_pin_dc_data(void)
|
||||
{
|
||||
GPIO_SetBits(GPIOB, LCD_PIN_DC);
|
||||
}
|
||||
|
||||
static void lcd_pin_res_reset(void)
|
||||
{
|
||||
GPIO_ResetBits(GPIOC, LCD_PIN_RES);
|
||||
}
|
||||
|
||||
static void lcd_pin_res_disreset(void)
|
||||
{
|
||||
GPIO_SetBits(GPIOC, LCD_PIN_RES);
|
||||
}
|
||||
|
||||
void lcd_bl_set(uint8_t percent)
|
||||
{
|
||||
if (percent == 0) {
|
||||
GPIO_ResetBits(GPIOC, LCD_PIN_BL);
|
||||
} else {
|
||||
GPIO_SetBits(GPIOC, LCD_PIN_BL);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
SPI_InitTypeDef SPI_InitStructure;
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
uint16_t *p;
|
||||
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
||||
|
||||
/* config pin */
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_PIN_RES | LCD_PIN_BL;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_PIN_CS | LCD_PIN_DC;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
lcd_pin_cs_disselect();
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_PIN_SCL | LCD_PIN_SDA;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);
|
||||
|
||||
/* config SPI function */
|
||||
SPI_I2S_DeInit(SPI2);
|
||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
|
||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
|
||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
|
||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
SPI_InitStructure.SPI_CRCPolynomial = 7;
|
||||
SPI_Init(SPI2, &SPI_InitStructure);
|
||||
SPI_Cmd(SPI2, ENABLE);
|
||||
// SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
|
||||
|
||||
/* Configure DMA controller to manage SPI request */
|
||||
DMA_InitStructure.DMA_BufferSize = LCD_PIX * 2;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&(SPI2->DR));
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)lcd_buffer;
|
||||
DMA_Init(DMA1_Stream4, &DMA_InitStructure);
|
||||
|
||||
/* TIM3 for delay, unit: 0.1ms */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
||||
TIM_TimeBaseStructure.TIM_Period = 84 / 100 - 1; /* 0.1ms = 100us */
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = 0;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
|
||||
TIM_PrescalerConfig(TIM3, 0, TIM_PSCReloadMode_Immediate);
|
||||
TIM_Cmd(TIM3, DISABLE);
|
||||
|
||||
/* ST7735 init */
|
||||
lcd_bl_set(100);
|
||||
lcd_pin_res_reset();
|
||||
lcd_delay_100us(1);
|
||||
lcd_pin_res_disreset();
|
||||
lcd_delay_100us(1200);
|
||||
// lcd_cmd(LCD_CMD_SWRESET);
|
||||
lcd_cmd(LCD_CMD_SLPOUT);
|
||||
lcd_buffer[0] = 0x08;
|
||||
lcd_send_data(LCD_CMD_MADCTL, lcd_buffer, 1);
|
||||
lcd_buffer[0] = 0x5; /* 16-bit/pixel */
|
||||
lcd_send_data(LCD_CMD_COLMOD, lcd_buffer, 1);
|
||||
lcd_cmd_caset(0, LCD_X - 1);
|
||||
lcd_cmd_raset(0, LCD_Y - 1);
|
||||
p = (uint16_t *)lcd_buffer;
|
||||
for (uint32_t i = 0; i < LCD_PIX; i++) {
|
||||
p[i] = 0x3800;
|
||||
}
|
||||
lcd_cmd_ramwr(lcd_buffer, LCD_PIX * 2);
|
||||
lcd_cmd(LCD_CMD_DISPON);
|
||||
}
|
||||
|
||||
void lcd_delay_100us(uint16_t cnt)
|
||||
{
|
||||
TIM_SetCounter(TIM3, 0);
|
||||
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
|
||||
TIM_Cmd(TIM3, ENABLE);
|
||||
for (uint16_t i = 0; i < cnt; i++) {
|
||||
while (RESET == TIM_GetFlagStatus(TIM3, TIM_FLAG_Update));
|
||||
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
|
||||
}
|
||||
TIM_Cmd(TIM3, DISABLE);
|
||||
}
|
||||
|
||||
void lcd_send_data_dma(uint16_t data)
|
||||
{
|
||||
DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_FEIF4 | DMA_FLAG_DMEIF4 | DMA_FLAG_TEIF4 | DMA_FLAG_HTIF4 | DMA_FLAG_TCIF4);
|
||||
// DMA_SetCurrDataCounter(DMA1_Stream4, LCD_PIX);
|
||||
DMA_Cmd(DMA1_Stream4, ENABLE);
|
||||
}
|
||||
|
||||
void lcd_send_data(uint8_t cmd, uint8_t *data, uint32_t length)
|
||||
{
|
||||
uint32_t idx = 0;
|
||||
|
||||
lcd_pin_cs_select();
|
||||
lcd_pin_dc_cmd();
|
||||
SPI_I2S_SendData(SPI2, cmd);
|
||||
while (RESET == SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE));
|
||||
while (SET == SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY));
|
||||
lcd_pin_dc_data();
|
||||
while (idx < length) {
|
||||
while (RESET == SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE));
|
||||
SPI_I2S_SendData(SPI2, data[idx++]);
|
||||
}
|
||||
while (RESET == SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE));
|
||||
while (SET == SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY));
|
||||
lcd_pin_cs_disselect();
|
||||
}
|
||||
|
||||
void lcd_cmd(uint8_t cmd)
|
||||
{
|
||||
lcd_pin_cs_select();
|
||||
lcd_pin_dc_cmd();
|
||||
SPI_I2S_SendData(SPI2, cmd);
|
||||
while (RESET == SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE));
|
||||
while (SET == SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY));
|
||||
lcd_pin_cs_disselect();
|
||||
}
|
||||
|
||||
void lcd_cmd_caset(uint16_t xs, uint16_t xe)
|
||||
{
|
||||
uint8_t data[4] = {0};
|
||||
|
||||
xs += LCD_X_START;
|
||||
xe += LCD_X_START;
|
||||
data[0] = (uint8_t)(xs >> 8);
|
||||
data[1] = (uint8_t)(xs);
|
||||
data[2] = (uint8_t)(xe >> 8);
|
||||
data[3] = (uint8_t)(xe);
|
||||
lcd_send_data(LCD_CMD_CASET, data, sizeof(data));
|
||||
}
|
||||
|
||||
void lcd_cmd_raset(uint16_t ys, uint16_t ye)
|
||||
{
|
||||
uint8_t data[4] = {0};
|
||||
|
||||
ys += LCD_Y_START;
|
||||
ye += LCD_Y_START;
|
||||
data[0] = (uint8_t)(ys >> 8);
|
||||
data[1] = (uint8_t)(ys);
|
||||
data[2] = (uint8_t)(ye >> 8);
|
||||
data[3] = (uint8_t)(ye);
|
||||
lcd_send_data(LCD_CMD_RASET, data, sizeof(data));
|
||||
}
|
||||
|
||||
void lcd_cmd_ramwr(uint8_t *data, uint32_t length)
|
||||
{
|
||||
lcd_send_data(LCD_CMD_RAMWR, data, length);
|
||||
}
|
||||
|
||||
void lcd_loop(void)
|
||||
{
|
||||
static uint32_t tick = 0;
|
||||
|
||||
if (system_tick_cnt - tick > 10) {
|
||||
tick = system_tick_cnt;
|
||||
lcd_cmd_caset(0, 0);
|
||||
lcd_cmd_raset(0, 0);
|
||||
((uint16_t *)lcd_buffer)[0] = 0x001F;
|
||||
((uint16_t *)lcd_buffer)[1] = 0x001F;
|
||||
((uint16_t *)lcd_buffer)[2] = 0x001F;
|
||||
((uint16_t *)lcd_buffer)[3] = 0x001F;
|
||||
lcd_cmd_ramwr(lcd_buffer, 8);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
#ifndef __LCD_H__
|
||||
#define __LCD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
|
||||
#define LCD_PIN_CS (GPIO_Pin_12)
|
||||
#define LCD_PIN_SCL (GPIO_Pin_13)
|
||||
#define LCD_PIN_SDA (GPIO_Pin_15)
|
||||
#define LCD_PIN_DC (GPIO_Pin_14)
|
||||
#define LCD_PIN_RES (GPIO_Pin_7)
|
||||
#define LCD_PIN_BL (GPIO_Pin_6)
|
||||
|
||||
#define LCD_X (128)
|
||||
#define LCD_Y (160)
|
||||
#define LCD_PIX (LCD_X * LCD_Y)
|
||||
#define LCD_X_START (2)
|
||||
#define LCD_Y_START (1)
|
||||
|
||||
#define LCD_CMD_NOP (0x00)
|
||||
#define LCD_CMD_SWRESET (0x01)
|
||||
#define LCD_CMD_SLPOUT (0x11)
|
||||
#define LCD_CMD_DISPOFF (0x28)
|
||||
#define LCD_CMD_DISPON (0x29)
|
||||
#define LCD_CMD_CASET (0x2A)
|
||||
#define LCD_CMD_RASET (0x2B)
|
||||
#define LCD_CMD_RAMWR (0x2C)
|
||||
#define LCD_CMD_MADCTL (0x36)
|
||||
#define LCD_CMD_COLMOD (0x3A)
|
||||
|
||||
void lcd_init(void);
|
||||
void lcd_delay_100us(uint16_t cnt);
|
||||
void lcd_send_data(uint8_t cmd, uint8_t *data, uint32_t length);
|
||||
void lcd_cmd(uint8_t cmd);
|
||||
void lcd_cmd_caset(uint16_t xs, uint16_t xe);
|
||||
void lcd_cmd_raset(uint16_t ys, uint16_t ye);
|
||||
void lcd_cmd_ramwr(uint8_t *data, uint32_t length);
|
||||
void lcd_loop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LCD_H__ */
|
||||
Loading…
Reference in New Issue
Block a user