[STM32F4] LCD via SPI - Page 1
Forum section: electronics / general

author: abc12
author_rank: Newbie
timestamp: May 22, 2017, 07:54:11 am
content: Welcome all!As a way of exercise I'm trying to convert LCD lib from a web for a HAL SPI use. I use STM32F429-DISCO board and well, I have no idea what I have done wrong but LCD doesn't work. I have checked that SPI initiates and command string for the LCD init is correct since it's taken from documentation+guides. I would really appreciate help in solving this problem.main.cCode:#include "stm32f4xx.h"#include "stm32f429i_discovery.h"#include "LCD.h"#include "SPI.h"#include "fonts.h"#define USE_MAIN_CLOCK_72MHZ 1static void SystemClock_Config(void);int main(void) {HAL_Init();// Configure the system clockSystemClock_Config();SystemCoreClockUpdate();SysTick_Config(SystemCoreClock / 1000);BSP_LED_Init(LED4);LCD_Init();for(;;){LCD_Putc(120,120, 'c', &Font8, LCD_COLOR_YELLOW);}return 0;}/*** @brief System Clock Configuration* The system Clock is configured as follow :* System Clock source = PLL (HSE)* SYSCLK(Hz) = 180000000* HCLK(Hz) = 180000000* AHB Prescaler = 1* APB1 Prescaler = 4* APB2 Prescaler = 2* HSE Frequency(Hz) = 8000000* PLL_M = 8* PLL_N = 360* PLL_P = 2* PLL_Q = 7* VDD(V) = 3.3* Main regulator output voltage = Scale1 mode* Flash Latency(WS) = 5* The LTDC Clock is configured as follow :* PLLSAIN = 192* PLLSAIR = 4* PLLSAIDivR = 8* @param None* @retval None** COPYRIGHT(c) 2014 STMicroelectronics*/#if 1 == USE_MAIN_CLOCK_180MHZstatic void SystemClock_Config(void) {RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_OscInitTypeDef RCC_OscInitStruct;RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;/* Enable Power Control clock */__PWR_CLK_ENABLE();/* The voltage scaling allows optimizing the power consumption when the device isclocked below the maximum system frequency, to update the voltage scaling valueregarding system frequency refer to product datasheet. */__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/*##-1- System Clock Configuration #########################################*//* Enable HSE Oscillator and activate PLL with HSE as source */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 8;RCC_OscInitStruct.PLL.PLLN = 360;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 7;HAL_RCC_OscConfig(&RCC_OscInitStruct);HAL_PWREx_ActivateOverDrive();/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2clocks dividers */RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);/*##-2- LTDC Clock Configuration ###########################################*//* LCD clock configuration *//* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz *//* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz *//* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz *//* LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDIVR_8 = 48/8 = 6 Mhz */PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;PeriphClkInitStruct.PLLSAI.PLLSAIR = 4;PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8;HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);}#endif/*** SYSCLK = 72* HCLK = 72* Cortex Timer 72* FCLK 72* APB1 Peripheral (PCLK1) 36* APB1 Timer 72* APB2 Peripheral (PCLK2) 72* APB2 Timer 72**/#if 1 == USE_MAIN_CLOCK_72MHZvoid SystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct;RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;/**Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);/**Initializes the CPU, AHB and APB busses clocks*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 4;RCC_OscInitStruct.PLL.PLLN = 72;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 3;HAL_RCC_OscConfig(&RCC_OscInitStruct);/**Initializes the CPU, AHB and APB busses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;PeriphClkInitStruct.PLLSAI.PLLSAIN = 50;PeriphClkInitStruct.PLLSAI.PLLSAIR = 2;PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);// /**Configure the Systick interrupt time// */// HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);//// /**Configure the Systick// */// HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//// /* SysTick_IRQn interrupt configuration */// HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);}#endifLCD.h:Code:#ifndef LCD_H_#define LCD_H_#include "fonts.h"#define LCD_WIDTH 240#define LCD_HEIGHT 320#define LCD_PIXEL 76800#define LCD_COLOR_WHITE0xFFFF#define LCD_COLOR_BLACK0x0000#define LCD_COLOR_RED 0xF800#define LCD_COLOR_GREEN0x07E0#define LCD_COLOR_GREEN20xB723#define LCD_COLOR_BLUE0x001F#define LCD_COLOR_BLUE20x051D#define LCD_COLOR_YELLOW0xFFE0#define LCD_COLOR_ORANGE0xFBE4#define LCD_COLOR_CYAN0x07FF#define LCD_COLOR_MAGENTA0xA254#define LCD_COLOR_GRAY0x7BEF#define LCD_COLOR_BROWN0xBBCA#define LCD_TRANSPARENT0x80000000typedef enum {LCD_Orientation_Portrait_1,LCD_Orientation_Portrait_2,LCD_Orientation_Landscape_1,LCD_Orientation_Landscape_2} LCD_Orientation_t;void LCD_Init(void);int LCD_InitLCD(void);void LCD_SendData(uint8_t data);void LCD_SendCommand(uint8_t data);void LCD_SetCursor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);void LCD_Pixel(uint16_t x, uint16_t y, uint32_t color);void LCD_Fill(uint32_t color);void LCD_Rotate(LCD_Orientation_t orientation);void LCD_Putc(uint16_t x, uint16_t y, char c, sFONT* font, uint32_t foreground);void LCD_Puts(uint16_t x, uint16_t y, char* str, sFONT *font, uint32_t foreground);void LCD_GetStringSize(char* str, sFONT* font, uint16_t* width, uint16_t* height);void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint32_t color);void LCD_DrawRectangle(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1, uint32_t color);void LCD_DrawCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color);void LCD_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color);void LCD_DisplayOn(void);void LCD_DisplayOff(void);void Delay(volatile unsigned int delay);#endif /* LCD_H_ */SPI.h:Code:#ifndef SPI_H_#define SPI_H_#include "stm32f4xx_hal.h"#define SPIx SPI5#define SPIxCLK_ENABLE() __HAL_RCC_SPI5_CLK_ENABLE();#define SPIxCLK_DISABLE() __HAL_RCC_SPI5_CLK_DISABLE();#define SPIx_SCK_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE();#define SPIx_MISO_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE();#define SPIxMOSI_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE();#define WRX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE();#define CS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE();#define RST_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE();#define SPIx_FORCE_RESET() __SPI5_FORCE_RESET()#define SPIx_RELEASE_RESET() __SPI5_RELEASE_RESET#define SPIx_SCK_PIN GPIO_PIN_7#define SPIx_SCK_GPIO_PORT GPIOF#define SPIx_SCK_AF GPIO_AF5_SPI5#define SPIx_MISO_PIN GPIO_PIN_8#define SPIx_MISO_GPIO_PORT GPIOF#define SPIx_MISO_AF GPIO_AF5_SPI5#define SPIx_MOSI_PIN GPIO_PIN_9#define SPIx_MOSI_GPIO_PORT GPIOF#define SPIx_MOSI_AF GPIO_AF5_SPI5#define WRX_PINGPIO_PIN_13#define WRX_GPIO_PORT GPIOD#define CS_PIN GPIO_PIN_2#define CS_GPIO_PORT GPIOC#define RST_PIN GPIO_PIN_12#define RST_GPIO_PORT GPIOD#define DMAx DMA2#define DMAx_CLOCK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE();#define DMAx_RX_STREAM DMA2_Stream3#define DMAx_RX_CHANNEL DMA_CHANNEL_2#define DMAx_TX_STREAM DMA2_Stream4#define DMAx_TX_CHANNEL DMA_CHANNEL_2#define DMAx_CLOCK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE();#define BUFFERSIZE (COUNTOF(aTxBuffer)-1)#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))void GPIO_SPI_DMA_Init(void);void SPI_Init(void);void DMA_Init(void);void GPIO_Init(void);void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi);void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi);LCD.c:Code:#include <stdlib.h>#include "LCD.h"#include "SPI.h"#include "ili9341.h"#include "stm32f4xx_hal.h"#define WRX_SET() HAL_GPIO_WritePin(WRX_GPIO_PORT, WRX_PIN, 1);#define WRX_RESET() HAL_GPIO_WritePin(WRX_GPIO_PORT, WRX_PIN, 0);#define CS_SET() HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, 1);#define CS_RESET() HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, 0);#define RST_SET() HAL_GPIO_WritePin(RST_GPIO_PORT, RST_PIN, 1);#define RST_RESET() HAL_GPIO_WritePin(RST_GPIO_PORT, RST_PIN, 0);typedef enum {LCD_Landscape,LCD_Portrait}LCD_Orientation;typedef struct {uint16_t width;uint16_t height;LCD_Orientation orientation;}LCD_Options_t;GPIO_InitTypeDef GPIO_InitStruct;SPI_HandleTypeDef hspi;DMA_HandleTypeDef hdma_spi_rx;DMA_HandleTypeDef hdma_spi_tx;uint16_t LCD_x;uint16_t LCD_y;LCD_Options_t LCD_Options;uint8_t Data_From_Puts = 0;void LCD_Init(void) {GPIO_Init();CS_SET();DMA_Init();SPI_Init();LCD_InitLCD();LCD_x = LCD_y = 0;LCD_Options.width = LCD_WIDTH;LCD_Options.height = LCD_HEIGHT;LCD_Options.orientation = LCD_Portrait;LCD_Fill(LCD_COLOR_RED);}int LCD_InitLCD(void) {RST_RESET();Delay(20000);RST_SET();Delay(20000);LCD_SendCommand(LCD_SWRESET);Delay(50000);LCD_SendCommand(LCD_POWERA);LCD_SendData(0x39);LCD_SendData(0x2C);LCD_SendData(0x00);LCD_SendData(0x34);LCD_SendData(0x02);LCD_SendCommand(LCD_POWERB);LCD_SendData(0x00);LCD_SendData(0xC1);LCD_SendData(0x30);LCD_SendCommand(LCD_DTCA);LCD_SendData(0x85);LCD_SendData(0x00);LCD_SendData(0x78);LCD_SendCommand(LCD_DTCB);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendCommand(LCD_POWER_SEQ);LCD_SendData(0x64);LCD_SendData(0x03);LCD_SendData(0x12);LCD_SendData(0x81);LCD_SendCommand(LCD_PRC);LCD_SendData(0x20);LCD_SendCommand(LCD_POWER1);LCD_SendData(0x23);LCD_SendCommand(LCD_POWER2);LCD_SendData(0x10);LCD_SendCommand(LCD_VCOM1);LCD_SendData(0x3E);LCD_SendData(0x28);LCD_SendCommand(LCD_VCOM2);LCD_SendData(0x86);LCD_SendCommand(LCD_MAC);LCD_SendData(0x48);LCD_SendCommand(LCD_PIXEL_FORMAT);LCD_SendData(0x55);LCD_SendCommand(LCD_FRMCTR1);LCD_SendData(0x00);LCD_SendData(0x18);LCD_SendCommand(LCD_DFC);LCD_SendData(0x08);LCD_SendData(0x82);LCD_SendData(0x27);LCD_SendCommand(LCD_3GAMMA_EN);LCD_SendData(0x00);LCD_SendCommand(LCD_COLUMN_ADDR);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendData(0xEF);LCD_SendCommand(LCD_PAGE_ADDR);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendData(0x01);LCD_SendData(0x3F);LCD_SendCommand(LCD_GAMMA);LCD_SendData(0x01);LCD_SendCommand(LCD_PGAMMA);LCD_SendData(0x0F);LCD_SendData(0x31);LCD_SendData(0x2B);LCD_SendData(0x0C);LCD_SendData(0x0E);LCD_SendData(0x08);LCD_SendData(0x4E);LCD_SendData(0xF1);LCD_SendData(0x37);LCD_SendData(0x07);LCD_SendData(0x10);LCD_SendData(0x03);LCD_SendData(0x0E);LCD_SendData(0x09);LCD_SendData(0x00);LCD_SendCommand(LCD_NGAMMA);LCD_SendData(0x00);LCD_SendData(0x0E);LCD_SendData(0x14);LCD_SendData(0x03);LCD_SendData(0x11);LCD_SendData(0x07);LCD_SendData(0x31);LCD_SendData(0xC1);LCD_SendData(0x48);LCD_SendData(0x08);LCD_SendData(0x0F);LCD_SendData(0x0C);LCD_SendData(0x31);LCD_SendData(0x36);LCD_SendData(0x0F);LCD_SendCommand(LCD_SLEEP_OUT);Delay(1000000);LCD_SendCommand(LCD_DISPLAY_ON);LCD_SendCommand(LCD_GRAM);return 1;}void LCD_DisplayOn(void){LCD_SendCommand(LCD_DISPLAY_ON);}void LCD_DisplayOff(void) {LCD_SendCommand(LCD_DISPLAY_OFF);}void LCD_SendCommand(uint8_t data) {WRX_RESET();CS_RESET();HAL_SPI_Transmit_IT(&hspi, &data, 1);CS_SET();}void LCD_SendData(uint8_t data) {WRX_SET();CS_RESET();HAL_SPI_Transmit_IT(&hspi, &data, 1);CS_SET();}void LCD_DrawPixel(uint16_t x, uint16_t y, uint32_t color) {LCD_SetCursor(x,y,x,y);LCD_SendCommand(LCD_GRAM);LCD_SendData(color >> 8);LCD_SendData(color & 0xFF);}void LCD_SetCursor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {LCD_SendCommand(LCD_COLUMN_ADDR);LCD_SendData(x1 >> 8);LCD_SendData(x1 & 0xFF);LCD_SendData(x2 >> 8);LCD_SendData(x2 & 0xFF);LCD_SendCommand(LCD_PAGE_ADDR);LCD_SendData(y1 >> 8);LCD_SendData(y1 & 0xFF);LCD_SendData(y2 >> 8);LCD_SendData(y2 & 0xFF);}void LCD_Fill(uint32_t color) {uint32_t n;uint8_t hi,lo;hi = color >> 8;lo = color & 0xFF;LCD_SetCursor(0,0,LCD_Options.width - 1,LCD_Options.height -1);LCD_SendCommand(LCD_GRAM);for(n=0;n<LCD_PIXEL;n++) {LCD_SendData(hi);LCD_SendData(lo);}}void LCD_Rotate(LCD_Orientation_t orientation) {LCD_SendCommand(LCD_MAC);if (orientation == LCD_Orientation_Portrait_1) {LCD_SendData(0x58);}else if (orientation == LCD_Orientation_Portrait_2) {LCD_SendData(0x88);}else if (orientation == LCD_Orientation_Landscape_1) {LCD_SendData(0x28);}else LCD_SendData(0xE8);if (orientation == LCD_Orientation_Portrait_1 || orientation == LCD_Orientation_Portrait_2) {LCD_Options.width = LCD_WIDTH;LCD_Options.height = LCD_HEIGHT;LCD_Options.orientation = LCD_Portrait;}else {LCD_Options.width = LCD_HEIGHT;LCD_Options.height = LCD_WIDTH;LCD_Options.orientation = LCD_Landscape;}}void LCD_Puts(uint16_t x, uint16_t y, char *str, sFONT* font, uint32_t foreground) {uint16_t startX = x;LCD_x = x;LCD_y = y;while (*str) {if (*str == '\n') {LCD_y += font->Height + 1;if (*(str+1) == '\r') {LCD_x = 0;str++;}else {LCD_x = startX;}str++;continue;}else if (*str == '\r') {str++;continue;}LCD_Putc(LCD_x, LCD_y, *str++, font, foreground);}}void LCD_GetStringSize(char *str, sFONT* font, uint16_t *width, uint16_t *height) {uint16_t w = 0;*height = font->Height;while (*str++) {w += font->Width;}*width = w;}void LCD_Putc(uint16_t x, uint16_t y, char c, sFONT* font, uint32_t foreground) {uint32_t i, b, j;LCD_x = x;LCD_y = y;if ((LCD_x + font->Width) > LCD_Options.width) {LCD_y += font->Width;LCD_x = 0;}for (i=0; i<font->Height; i++) {b = font->table[(c-32)*font->Height + i];for (j=0; j<font->Width;j++) {if ((b<<j) & 0x8000) {LCD_DrawPixel(LCD_x + j, LCD_y + i, foreground);}}}LCD_x += font->Width;}void LCD_DrawLine(uint16_t X1, uint16_t Y1, uint16_t X2, uint16_t Y2, uint32_t color) {int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,curpixel = 0;deltax = abs(X2 - X1);deltay = abs(Y2 - Y1);x = X1;y = Y1;if (X2 >= X1){xinc1 = 1;xinc2 = 1;}else{xinc1 = -1;xinc2 = -1;}if (Y2 >= Y1){yinc1 = 1;yinc2 = 1;}else{yinc1 = -1;yinc2 = -1;}if (deltax >= deltay){xinc1 = 0;yinc2 = 0;den = deltax;num = deltax / 2;numadd = deltay;numpixels = deltax;}else{xinc2 = 0;yinc1 = 0;den = deltay;num = deltay / 2;numadd = deltax;numpixels = deltay;}for (curpixel = 0; curpixel <= numpixels; curpixel++){LCD_DrawPixel(x, y, color);num += numadd;if (num >= den){num -= den;x += xinc1;y += yinc1;}x += xinc2;y += yinc2;}}void LCD_DrawRectangle(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1, uint32_t color) {LCD_DrawLine(x0,y0,x1,y0,color);LCD_DrawLine(x0,y0,x0,y1,color);LCD_DrawLine(x1,y0,x1,y1,color);LCD_DrawLine(x0,y1,x1,y1,color);}void LCD_DrawCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color) {int16_t f = 1 - r;int16_t ddF_x = 1;int16_t ddF_y = -2 * r;int16_t x = 0;int16_t y = r;LCD_DrawPixel(x0, y0 + r, color);LCD_DrawPixel(x0, y0 - r, color);LCD_DrawPixel(x0 + r, y0, color);LCD_DrawPixel(x0 - r, y0, color);while (x < y) {if (f >= 0) {y--;ddF_y += 2;f += ddF_y;}x++;ddF_x += 2;f += ddF_x;LCD_DrawPixel(x0 + x, y0 + y, color);LCD_DrawPixel(x0 - x, y0 + y, color);LCD_DrawPixel(x0 + x, y0 - y, color);LCD_DrawPixel(x0 - x, y0 - y, color);LCD_DrawPixel(x0 + y, y0 + x, color);LCD_DrawPixel(x0 - y, y0 + x, color);LCD_DrawPixel(x0 + y, y0 - x, color);LCD_DrawPixel(x0 - y, y0 - x, color);}}void LCD_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color) {int16_t f = 1 - r;int16_t ddF_x = 1;int16_t ddF_y = -2 * r;int16_t x = 0;int16_t y = r;LCD_DrawPixel(x0, y0 + r, color);LCD_DrawPixel(x0, y0 - r, color);LCD_DrawPixel(x0 + r, y0, color);LCD_DrawPixel(x0 - r, y0, color);LCD_DrawLine(x0 - r, y0, x0 + r, y0, color);while (x < y) {if (f >= 0) {y--;ddF_y += 2;f += ddF_y;}x++;ddF_x += 2;f += ddF_x;LCD_DrawLine(x0 - x, y0 + y, x0 + x, y0 + y, color);LCD_DrawLine(x0 + x, y0 - y, x0 - x, y0 - y, color);LCD_DrawLine(x0 + y, y0 + x, x0 - y, y0 + x, color);LCD_DrawLine(x0 + y, y0 - x, x0 - y, y0 - x, color);}}void SPI_Init(void) {hspi.Instance = SPIx;hspi.Init.Mode = SPI_MODE_MASTER;hspi.Init.Direction = SPI_DIRECTION_2LINES;hspi.Init.DataSize = SPI_DATASIZE_8BIT;hspi.Init.CLKPolarity = SPI_POLARITY_LOW;hspi.Init.CLKPhase = SPI_PHASE_1EDGE;hspi.Init.NSS = SPI_NSS_SOFT;hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi.Init.TIMode = SPI_TIMODE_DISABLE;hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi.Init.CRCPolynomial = 10;HAL_SPI_Init(&hspi);}void DMA_Init(void) {/* DMA controller clock enable */DMAx_CLOCK_ENABLE();/* DMA interrupt init *//* DMA2_Stream3_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);/* DMA2_Stream4_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);}void GPIO_Init(void) {WRX_GPIO_CLK_ENABLE();CS_GPIO_CLK_ENABLE();RST_GPIO_CLK_ENABLE();GPIO_InitStruct.Pin = WRX_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;HAL_GPIO_Init(WRX_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = CS_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;HAL_GPIO_Init(CS_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = RST_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW ;HAL_GPIO_Init(RST_GPIO_PORT, &GPIO_InitStruct);}void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) {SPIxCLK_ENABLE();SPIx_SCK_GPIO_CLK_ENABLE();SPIx_MISO_GPIO_CLK_ENABLE();SPIxMOSI_GPIO_CLK_ENABLE();GPIO_InitStruct.Pin = SPIx_SCK_PIN|SPIx_MISO_PIN|SPIx_MOSI_PIN;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;GPIO_InitStruct.Alternate = SPIx_SCK_AF;HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct);hdma_spi_rx.Instance = DMAx_RX_STREAM;hdma_spi_rx.Init.Channel = DMAx_RX_CHANNEL;hdma_spi_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_spi_rx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_spi_rx.Init.MemInc = DMA_MINC_ENABLE;hdma_spi_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_spi_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_spi_rx.Init.Mode = DMA_NORMAL;hdma_spi_rx.Init.Priority = DMA_PRIORITY_LOW;hdma_spi_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;HAL_DMA_Init(&hdma_spi_rx);__HAL_LINKDMA(hspi,hdmarx,hdma_spi_rx);hdma_spi_tx.Instance = DMAx_TX_STREAM;hdma_spi_tx.Init.Channel = DMAx_TX_CHANNEL;hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_spi_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_spi_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_spi_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_spi_tx.Init.Mode = DMA_NORMAL;hdma_spi_tx.Init.Priority = DMA_PRIORITY_LOW;hdma_spi_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;HAL_DMA_Init(&hdma_spi_tx);__HAL_LINKDMA(hspi,hdmatx,hdma_spi_tx);}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) {SPIxCLK_DISABLE();HAL_GPIO_DeInit(SPIx_SCK_GPIO_PORT, SPIx_SCK_PIN);HAL_GPIO_DeInit(SPIx_MISO_GPIO_PORT, SPIx_MISO_PIN);HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN);HAL_DMA_DeInit(hspi->hdmarx);HAL_DMA_DeInit(hspi->hdmatx);}void Delay(volatile unsigned int delay) {for(;delay != 0; delay--);}

author: FreddyVictor
author_rank: Regular Contributor
timestamp: May 22, 2017, 12:12:53 pm
content: The STM32F429-Discovery uses a parallel interface for the actual colour data sent to the screen.Take a look at theuser manualpage33The SPI code you're using I think is probably meant for using with the ILI9341 type displaysYou could always connect one of these to a spare SPI slot on the boardIncidentally, having messed around with these things, that library code is comprehensive and convenient, but, will lack alot in speed since it does alot of unnecessary pin toggling for virtually every byte sent.my early code was taking 0.5s just to clear a screen, but after improvements takes nearer 0.12s

author: abc12
author_rank: Newbie
timestamp: May 22, 2017, 02:05:05 pm
content: Are you sure? Yes, stm examples use parallel interface for LCD but it's still ILI9341 connected through SPI5 to board so I don't see why it shouldn't work (but well, it doesn't in this form...).

author: newbrain
author_rank: Super Contributor
timestamp: May 22, 2017, 05:49:48 pm
content: Quote from: FreddyVictor on May 22, 2017, 12:12:53 pmRight, but you can see that the 9341 controller is wired for SPI, as the IM0...IM3 control pins are set to 0b0110 (as duly noted in the text box).The use of parallel RGB interface is set up by SW, in the BSP part of the Cube, in the initialization function:QuoteThe default value for the relevant bits is 0, so the SPI should suffice.To the OP: if have some time later, I might have a look at the code and try it on my board. No guarantees, though!

author: newbrain
author_rank: Super Contributor
timestamp: May 22, 2017, 09:21:18 pm
content: OK, let's go for it!First of all, the initialization sequence: each TFT panel has its own specific settings, so my best bet was to copy the init sequence from the Cube BSP, as many of the values were quite off (e.g. the VCOMs).Of course, the RGB interface must be disabled, so the relevant command is changed, and the one to set the pixel format to 16bit is added.BTW, the original code also toggled a pin as reset, but that pin is RDX, not used in the SPI case.Code:int LCD_InitLCD(void) {// newbrain//// What's this supposed to be? in the BSP, but not in the datasheet!//LCD_SendCommand(0xCA);//LCD_SendData(0xC3);//LCD_SendData(0x08);//LCD_SendData(0x50);LCD_SendCommand(LCD_POWERB);LCD_SendData(0x00);LCD_SendData(0xC1);LCD_SendData(0x30);LCD_SendCommand(LCD_POWER_SEQ);LCD_SendData(0x64);LCD_SendData(0x03);LCD_SendData(0x12);LCD_SendData(0x81);LCD_SendCommand(LCD_DTCA);LCD_SendData(0x85);LCD_SendData(0x00);LCD_SendData(0x78);LCD_SendCommand(LCD_POWERA);LCD_SendData(0x39);LCD_SendData(0x2C);LCD_SendData(0x00);LCD_SendData(0x34);LCD_SendData(0x02);LCD_SendCommand(LCD_PRC);LCD_SendData(0x20);LCD_SendCommand(LCD_DTCB);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendCommand(LCD_FRMCTR1);LCD_SendData(0x00);LCD_SendData(0x1B);LCD_SendCommand(LCD_DFC);LCD_SendData(0x0A);LCD_SendData(0xA2);LCD_SendCommand(LCD_POWER1);LCD_SendData(0x10);LCD_SendCommand(LCD_POWER2);LCD_SendData(0x10);LCD_SendCommand(LCD_VCOM1);LCD_SendData(0x45);LCD_SendData(0x15);LCD_SendCommand(LCD_VCOM2);LCD_SendData(0x90);LCD_SendCommand(LCD_MAC);LCD_SendData(0xC8);LCD_SendCommand(LCD_3GAMMA_EN);LCD_SendData(0x00);// Not needed, we don't use RGB interface//LCD_SendCommand(LCD_RGB_INTERFACE);//LCD_SendData(0xC2);LCD_SendCommand(LCD_DFC);LCD_SendData(0x0A);LCD_SendData(0xA7);LCD_SendData(0x27);LCD_SendData(0x04);LCD_SendCommand(LCD_PIXEL_FORMAT);LCD_SendData(0x55);/* Colomn address set */LCD_SendCommand(LCD_COLUMN_ADDR);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendData(0xEF);/* Page address set */LCD_SendCommand(LCD_PAGE_ADDR);LCD_SendData(0x00);LCD_SendData(0x00);LCD_SendData(0x01);LCD_SendData(0x3F);LCD_SendCommand(LCD_INTERFACE);LCD_SendData(0x01);LCD_SendData(0x00);// newbrain: change from 0x02 (RGB) to 0x00 (internal clocking)LCD_SendData(0x00);LCD_SendCommand(LCD_GRAM);HAL_Delay(200);LCD_SendCommand(LCD_GAMMA);LCD_SendData(0x01);LCD_SendCommand(LCD_PGAMMA);LCD_SendData(0x0F);LCD_SendData(0x29);LCD_SendData(0x24);LCD_SendData(0x0C);LCD_SendData(0x0E);LCD_SendData(0x09);LCD_SendData(0x4E);LCD_SendData(0x78);LCD_SendData(0x3C);LCD_SendData(0x09);LCD_SendData(0x13);LCD_SendData(0x05);LCD_SendData(0x17);LCD_SendData(0x11);LCD_SendData(0x00);LCD_SendCommand(LCD_NGAMMA);LCD_SendData(0x00);LCD_SendData(0x16);LCD_SendData(0x1B);LCD_SendData(0x04);LCD_SendData(0x11);LCD_SendData(0x07);LCD_SendData(0x31);LCD_SendData(0x33);LCD_SendData(0x42);LCD_SendData(0x05);LCD_SendData(0x0C);LCD_SendData(0x0A);LCD_SendData(0x28);LCD_SendData(0x2F);LCD_SendData(0x0F);LCD_SendCommand(LCD_SLEEP_OUT);HAL_Delay(200);LCD_SendCommand(LCD_DISPLAY_ON);/* GRAM start writing */LCD_SendCommand(LCD_GRAM);return 1;}Second, the use of the HAL:You should use the regular HAL_SPI_Transmit rather the _IT variant, or provide an ISR for the SPI interrupt.Calling HAL_SPI_Transmit_IT() without waiting for the transmission to finish (as done in the code) will most assuredly give overrun errors, and, without a definition of the SPI ISR, one will end up in the default handler provided by the startup file.Code:void LCD_SendCommand(uint8_t data) {WRX_RESET();CS_RESET();// newbrainHAL_SPI_Transmit(&hspi, &data, 1, 500);// HAL_SPI_Transmit_IT(&hspi, &data, 1);CS_SET();}void LCD_SendData(uint8_t data) {WRX_SET();CS_RESET();// newbrainHAL_SPI_Transmit(&hspi, &data, 1, 500);// HAL_SPI_Transmit_IT(&hspi, &data, 1);CS_SET();}I see also that DMA channels are setup, but not used. Consider that if you intend to read from the 9341, the SPI must be configured for half-duplex (i.e. same line for MISO/MOSI), unless you change the IM0..3 bits to 0b1110 (soldering iron programming, you can find the pullup and pulldown resistors on the bottom of the baord, close to PC15 pin).Then, the character drawing routine contains a couple of minor faults, see below:Code:void LCD_Putc(uint16_t x, uint16_t y, char c, sFONT* font, uint32_t foreground) {uint32_t i, b, j;LCD_x = x;LCD_y = y;if ((LCD_x + font->Width) > LCD_Options.width) {// newbrain: this should be the height!// LCD_y += font->Width;LCD_y += font->Height;LCD_x = 0;}for (i = 0; i < font->Height; i++) {b = font->table[(c - 32)*font->Height + i];for (j = 0; j < font->Width; j++) {// newbrain: 0x8000 is too much, if you are using font8,// the whole loop should be adjusted depending on the font width!//if ((b << j) & 0x8000) {if ((b << j) & 0x80) {LCD_DrawPixel(LCD_x + j, LCD_y + i, foreground);}}}LCD_x += font->Width;}Another minor error: LCD.h declares LCD_Pixel(), but LCD.h defines LCD_DrawPixel()!For me it now works as expected, hope this helps!Oh, and welcome to the forum!

author: newbrain
author_rank: Super Contributor
timestamp: May 23, 2017, 09:19:52 am
content: OP asked for some help with different fonts...Here you go.No optimization has been done (there are several opportunities), but I hope it is at least clear enough.This is untested code!If your cat catches fire or you grow green horns, it's not my fault.Code:void LCD_Putc(uint16_t x, uint16_t y, char c, sFONT *font, uint32_t foreground){if ((x + font->Width) > LCD_Options.width){// Here, a check on display height would be in order!y += font->Height;x = 0;}// How many bytes in one font line?uint32_t lineSize = (font->Width + 7) / 8;// char offset in the tableuint32_t charOffset = (c - 32) * font->Height * lineSize;// Outer loop, repeat for every line of lineSize bytes in the fontfor (uint32_t line = 0; line < font->Height; line++){// Loop over the bytes in one linefor (uint32_t byte = 0; byte < lineSize; byte++){// How many bits are used in this byte?uint32_t stopBit = 8;// Last byte in line?if (byte == lineSize - 1)stopBit = font->Width % 8;// Get the byteuint32_t value = font->table[charOffset + line*lineSize + byte];for (uint32_t bit = 0; bit < stopBit; bit++){// Draw the pixel, if neededif ((value << bit) & 0x80){LCD_DrawPixel(x + byte * 8 + bit, y + line, foreground);}}}}}Edit: x update fixed.Edit2:QuoteI'm terribly sorry for the poor animal.I hope the green horns at least match your hairstyle and colour.Fixed for real this time (pinky swear), and lightly tested for Font8-24.It was, admittedly, written hastily (work break).

author: FreddyVictor
author_rank: Regular Contributor
timestamp: May 23, 2017, 02:58:51 pm
content: My cat caught fireslightly revised code for LCD_Putc()Code:void LCD_Putc(uint16_t x, uint16_t y, char c, sFONT *font, uint32_t foreground){if ((x + font->Width) > LCD_Options.width){// Here, a check on display height would be in order!y += font->Height;x = 0;}// How many bytes in one font line?uint32_t lineSize = (font->Width + 7) / 8;// char offset in the tableuint32_t charOffset = (c - 32) * font->Height * lineSize;// Outer loop, repeat for every line of lineSize bytes in the fontfor (uint32_t line = 0; line < font->Height; line ++){// get ptr to start of this lineconst uint8_t * value = font->table+(charOffset + line*lineSize);// terrible code but it worksuint8_t bit = 0;while(bit<font->Width){if ((*value << (bit%8)) & 0x80){LCD_DrawPixel(x + bit, y + line, foreground);}if (++bit%8==0) { value++; } // if end-of byte, skip to start of next byte}}}also slight mod needed for LCD_Puts():Code:LCD_Putc(LCD_x, LCD_y, *str++, font, foreground);LCD_x+=font->Width; //<-- FV added lineappears to work ok with 8,12 & 16 font size