242 lines
7.5 KiB
C
242 lines
7.5 KiB
C
#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);
|
|
}
|
|
}
|