SPI communication between STM32 and 1.54inch e-Paper Module  - Page 1
Forum section: electronics / general

author: Alfąs
author_rank: Newbie
timestamp: September 04, 2018, 09:15:08 am
content: Hi, I have a strange problem which I cannot understand.I useSTM32L433RCxT Nucleo32boardI try to display anything on the 1.54inch e-Paper Module (https://www.waveshare.com/wiki/1.54inch_e-Paper_Module)I have this screen with the SPI module on which there is hardcoded4 wire SPI interface(solderedjumper)There is no MISO line- only BUSY, RST, DC, CS, CLK, BIN(MOSI), GND and 3.3VFirst I've downloaded the examplary code from the WaveShare and changed it form my board with CUBEMX - it didn't work. There were untraceable errors.I've decided to create my onw library for this screen.I use HAL libraryMy code is currently only sending initial commands.Ok so now what's the problem:When I try to send a data with the use of SPI and the screen is connected the program fails.It doesn't fail when the screen isn't connected.I don't understand it at all as I believe there should be communication only in one way (MOSI). However I didn't manage to find any description what's being changed when the jumper is soldered to the 4line SPI.I totaly don't get it. I'm new with this technology.Will be super glad if anyone helps me!Source code:Code:#include "main.h"#include "stm32l4xx_hal.h"#include <stdbool.h>SPI_HandleTypeDef hspi1;void SystemClock_Config(void);static void MX_GPIO_Init(void);static void MX_SPI1_Init(void);void system_init() {HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_SPI1_Init();HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);init_154();}void init_154() {//DRIVER_OUTPUT_CONTROLsend_command_154(0x01);/*send_data_154(199 & 0xFF);send_data_154((199 >> 8) & 0xFF);send_data_154(0x00);*/return;}void send_command_154(uint8_t data) {HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &data, 1, 1000);while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);}void send_data_154(uint8_t data) {HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_SET);HAL_SPI_Transmit(&hspi1, &data, 1, 1000);while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);}int main(void){system_init();//unsigned char* frame_buffer = (unsigned char*)malloc(200 * 200 / 8);//set_frame_mem_154(IMAGE_DATA, 1, 1, 200, 200);//display_frame_154();while (1) {HAL_GPIO_TogglePin(user_led_GPIO_Port, user_led_Pin);HAL_Delay(500);}}Below is code automatcally generated by COBEMX and HAL. I didn't change anything in it,Code:/*** @brief System Clock Configuration* @retval None*/void SystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct;RCC_ClkInitTypeDef RCC_ClkInitStruct;/**Initializes the CPU, AHB and APB busses clocks*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;RCC_OscInitStruct.MSIState = RCC_MSI_ON;RCC_OscInitStruct.MSICalibrationValue = 0;RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;RCC_OscInitStruct.PLL.PLLM = 1;RCC_OscInitStruct.PLL.PLLN = 36;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}/**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;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}/**Configure the main internal regulator output voltage*/if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}/**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);}/* SPI1 init function */static void MX_SPI1_Init(void){/* SPI1 parameter configuration*/hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 7;hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;if (HAL_SPI_Init(&hspi1) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}}/** Configure pins as* Analog* Input* Output* EVENT_OUT* EXTI*/static void MX_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStruct;/* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, RST_Pin|DC_Pin|CS_Pin, GPIO_PIN_RESET);/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(user_led_GPIO_Port, user_led_Pin, GPIO_PIN_RESET);/*Configure GPIO pin : user_button_Pin */GPIO_InitStruct.Pin = user_button_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(user_button_GPIO_Port, &GPIO_InitStruct);/*Configure GPIO pin : BUSY_Pin */GPIO_InitStruct.Pin = BUSY_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(BUSY_GPIO_Port, &GPIO_InitStruct);/*Configure GPIO pins : RST_Pin DC_Pin CS_Pin */GPIO_InitStruct.Pin = RST_Pin|DC_Pin|CS_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/*Configure GPIO pin : user_led_Pin */GPIO_InitStruct.Pin = user_led_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(user_led_GPIO_Port, &GPIO_InitStruct);}/*** @brief This function is executed in case of error occurrence.* @param file: The file name as string.* @param line: The line in file as a number.* @retval None*/void _Error_Handler(char *file, int line){/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */while(1){}/* USER CODE END Error_Handler_Debug */}#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/void assert_failed(uint8_t* file, uint32_t line){/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */}#endif /* USE_FULL_ASSERT */

author: HB9EVI
author_rank: Frequent Contributor
timestamp: September 04, 2018, 10:28:02 am
content: can you explain me this here:Code:send_data_154((199 >> 8) & 0xFF);

author: mikerj
author_rank: Super Contributor
timestamp: September 04, 2018, 10:46:14 am
content: Quote from: Alfąs on September 04, 2018, 09:15:08 amThis is not a very useful description, I presume you mean your LED doesn't flash? Have you tried to determine at which line the program stops working?

author: Alfąs
author_rank: Newbie
timestamp: September 04, 2018, 10:57:12 am
content: Quote from: HB9EVI on September 04, 2018, 10:28:02 amThis is taken from the WaveShare code and as I believe it's supposed to be a way of setting display size to the driver.In the WS code I found:Code:((EPD_HEIGHT - 1) >> 8) & 0xFFQuote from: mikerj on September 04, 2018, 10:46:14 amYes. Basically it does. But I've also tried to debug it but I didn't manage to find the reason. The program was ending in the untraceable interrupt handler with while(1) loop.

author: HB9EVI
author_rank: Frequent Contributor
timestamp: September 04, 2018, 11:37:03 am
content: I don't see any interrupt handler, and except for the loop within int main() there should nowhere be a while(1) loop - that cannot work.how did you trace the code on the uC?

author: mikerj
author_rank: Super Contributor
timestamp: September 04, 2018, 01:58:51 pm
content: Quote from: Alfąs on September 04, 2018, 10:57:12 amDo you mean it's ending up in one of the exception handlers? e.g. UsageFault_Handler(), BusFault_Handler(), MemMang_Handler() or HardFault_Handler()?Do you have a debugger attached? If so then single step through until you find the line that causes this. If not then you'll need to add some extra debugging code e.g. using a serial port or the LED to show the code progress.

author: newbrain
author_rank: Super Contributor
timestamp: September 04, 2018, 02:36:34 pm
content: I don't think there is a L433 Nucleo32, did you mean Nucleo64?Not that it makes much difference, though...The posted code is not complete, are you sure you did not touch the CubeMX generated source (or posted only part of it)?What I am missing is the SPI pins initialization. CubeMX generates anHAL_PPP_MspInit()function that contains pin initialization for the peripheralPPP, in this case I expected to see anHAL_SPI_MspInit().If you somehow deleted it, aweak, empty one is provided by default, but for sure it won't work...

author: TomS_
author_rank: Frequent Contributor
timestamp: September 05, 2018, 01:30:42 pm
content: Quote from: HB9EVI on September 04, 2018, 10:28:02 amYeah, to me this looks like its just going to result in 0.199 = 1100011111000111 >> 8 = 0000000000000000 & 0xFF = 00000000Whether or not that is correct or not for the application ... seems a little pointless though.EPD_HEIGHT must be a 16 bit or greater number.

author: thm_w
author_rank: Super Contributor
timestamp: September 05, 2018, 11:06:25 pm
content: Quote from: TomS_ on September 05, 2018, 01:30:42 pmWell that code is commented out so it won't do anything.But the full code is:Code:sendData((EPD_HEIGHT - 1) & 0xFF);sendData(((EPD_HEIGHT - 1) >> 8) & 0xFF);Which would send a 32-bit number in two steps, that is fine. Note to OP, don't replace defined constants with the decimal number, it just makes things more confusing.