728x90

728x90

Saturday, November 15, 2025

STM32 Blue Pill HSPI1 and SN74HC595N LED Example

The SN74HC595N is an 8-bit serial-in-parallel out shift registers with latch outputs. It also has a serial data (DS) out pin for additional register cascading. This chip could operate at +3.3V level that could fit the STM32 micro-controller. For more information about using this chip, see this post.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
SN74HC595N LED Shift
 

This chip use a three-wire SPI interface, MOSI, SCK and Enable Pin for SPI master mode half duplex micro-controller. I made my own test board for this chip that outputs to LEDs.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
DIY SN74HC595N LED Test Board

 

The STM32CubeIDE has its code configure wizard enables the user to select any hardware and software setting of its micro-controller. Using HAL is very straight forward for writing code without using the micro-controller internal special registers.

The STM32F103C8T6 has two hardware SPI module, HSPI1 and HSPI2 that able to operate up to 16Mbits/s. 

I set the micro-controller to operate at 64MHz using its HSI and PLL. The SPI mode is Half Duplex Master with a 16MBits/s Baud Rate.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
Clock Configuration
 

The SPI NSS pin is can not be use with the SN74HC595. So the Enable pin must be select by user's software. I use the PA4 pin for the SPI enable pin.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
SPI and GPIO Setting

After the setting is finished click on generate code to get its skeleton program. The example below is a LED bar-graph that repeated endlessly. 

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file : main.c
  5. * @brief : Main program body
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * <h2><center>&copy; Copyright (c) 2025 STMicroelectronics.
  10. * All rights reserved.</center></h2>
  11. *
  12. * This software component is licensed by ST under BSD 3-Clause license,
  13. * the "License"; You may not use this file except in compliance with the
  14. * License. You may obtain a copy of the License at:
  15. * opensource.org/licenses/BSD-3-Clause
  16. *
  17. ******************************************************************************
  18. */
  19. /* USER CODE END Header */
  20. /* Includes ------------------------------------------------------------------*/
  21. #include "main.h"

  22. /* Private includes ----------------------------------------------------------*/
  23. /* USER CODE BEGIN Includes */

  24. /* USER CODE END Includes */

  25. /* Private typedef -----------------------------------------------------------*/
  26. /* USER CODE BEGIN PTD */

  27. /* USER CODE END PTD */

  28. /* Private define ------------------------------------------------------------*/
  29. /* USER CODE BEGIN PD */
  30. /* USER CODE END PD */

  31. /* Private macro -------------------------------------------------------------*/
  32. /* USER CODE BEGIN PM */

  33. /* USER CODE END PM */

  34. /* Private variables ---------------------------------------------------------*/
  35. SPI_HandleTypeDef hspi1;

  36. /* USER CODE BEGIN PV */

  37. /* USER CODE END PV */

  38. /* Private function prototypes -----------------------------------------------*/
  39. void SystemClock_Config(void);
  40. static void MX_GPIO_Init(void);
  41. static void MX_SPI1_Init(void);
  42. /* USER CODE BEGIN PFP */

  43. /* USER CODE END PFP */

  44. /* Private user code ---------------------------------------------------------*/
  45. /* USER CODE BEGIN 0 */

  46. /* USER CODE END 0 */

  47. /**
  48. * @brief The application entry point.
  49. * @retval int
  50. */
  51. int main(void)
  52. {
  53. /* USER CODE BEGIN 1 */

  54. /* USER CODE END 1 */

  55. /* MCU Configuration--------------------------------------------------------*/

  56. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  57. HAL_Init();

  58. /* USER CODE BEGIN Init */

  59. /* USER CODE END Init */

  60. /* Configure the system clock */
  61. SystemClock_Config();

  62. /* USER CODE BEGIN SysInit */

  63. /* USER CODE END SysInit */

  64. /* Initialize all configured peripherals */
  65. MX_GPIO_Init();
  66. MX_SPI1_Init();
  67. /* USER CODE BEGIN 2 */

  68. /* USER CODE END 2 */
  69. uint8_t data=0, i=0;
  70. /* Infinite loop */
  71. /* USER CODE BEGIN WHILE */
  72. while (1)
  73. {
  74. data|=(1<<i);
  75. if(data==0xFF) data=0;
  76. i++;
  77. if(i>7) i=0;
  78. HAL_SPI_Transmit(&hspi1,&data,1,10);

  79. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,0);
  80. HAL_Delay(100);
  81. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,1);
  82. }
  83. /* USER CODE END 3 */
  84. }

  85. /**
  86. * @brief System Clock Configuration
  87. * @retval None
  88. */
  89. void SystemClock_Config(void)
  90. {
  91. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  92. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  93. /** Initializes the RCC Oscillators according to the specified parameters
  94. * in the RCC_OscInitTypeDef structure.
  95. */
  96. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  97. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  98. RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  99. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  100. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
  101. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
  102. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  103. {
  104. Error_Handler();
  105. }
  106. /** Initializes the CPU, AHB and APB buses clocks
  107. */
  108. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  109. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  110. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  111. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  112. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  113. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  114. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  115. {
  116. Error_Handler();
  117. }
  118. }

  119. /**
  120. * @brief SPI1 Initialization Function
  121. * @param None
  122. * @retval None
  123. */
  124. static void MX_SPI1_Init(void)
  125. {

  126. /* USER CODE BEGIN SPI1_Init 0 */

  127. /* USER CODE END SPI1_Init 0 */

  128. /* USER CODE BEGIN SPI1_Init 1 */

  129. /* USER CODE END SPI1_Init 1 */
  130. /* SPI1 parameter configuration*/
  131. hspi1.Instance = SPI1;
  132. hspi1.Init.Mode = SPI_MODE_MASTER;
  133. hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  134. hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  135. hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  136. hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  137. hspi1.Init.NSS = SPI_NSS_SOFT;
  138. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  139. hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  140. hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  141. hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  142. hspi1.Init.CRCPolynomial = 10;
  143. if (HAL_SPI_Init(&hspi1) != HAL_OK)
  144. {
  145. Error_Handler();
  146. }
  147. /* USER CODE BEGIN SPI1_Init 2 */

  148. /* USER CODE END SPI1_Init 2 */

  149. }

  150. /**
  151. * @brief GPIO Initialization Function
  152. * @param None
  153. * @retval None
  154. */
  155. static void MX_GPIO_Init(void)
  156. {
  157. GPIO_InitTypeDef GPIO_InitStruct = {0};

  158. /* GPIO Ports Clock Enable */
  159. __HAL_RCC_GPIOA_CLK_ENABLE();

  160. /*Configure GPIO pin Output Level */
  161. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

  162. /*Configure GPIO pin : PA4 */
  163. GPIO_InitStruct.Pin = GPIO_PIN_4;
  164. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  165. GPIO_InitStruct.Pull = GPIO_NOPULL;
  166. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  167. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  168. }

  169. /* USER CODE BEGIN 4 */

  170. /* USER CODE END 4 */

  171. /**
  172. * @brief This function is executed in case of error occurrence.
  173. * @retval None
  174. */
  175. void Error_Handler(void)
  176. {
  177. /* USER CODE BEGIN Error_Handler_Debug */
  178. /* User can add his own implementation to report the HAL error return state */
  179. __disable_irq();
  180. while (1)
  181. {
  182. }
  183. /* USER CODE END Error_Handler_Debug */
  184. }

  185. #ifdef USE_FULL_ASSERT
  186. /**
  187. * @brief Reports the name of the source file and the source line number
  188. * where the assert_param error has occurred.
  189. * @param file: pointer to the source file name
  190. * @param line: assert_param error line source number
  191. * @retval None
  192. */
  193. void assert_failed(uint8_t *file, uint32_t line)
  194. {
  195. /* USER CODE BEGIN 6 */
  196. /* User can add his own implementation to report the file name and line number,
  197. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  198. /* USER CODE END 6 */
  199. }
  200. #endif /* USE_FULL_ASSERT */

  201. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


Proteus VSM also has a model for the STM32 Blue Pill for simulation.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example

 

I tested on bread board with my SN74HC595N LED module. It works fine. We can connect the supply voltage pin of the SN74HC595N to +5VDC while the STM32 Blue pill operates at only +3.3VDC. Or even both of them connect to the +3.3VDC they still works.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
SN74HC595N LED Bar-Graph

Now I made a little source code modification to make a simple LED shifting. 

  1. while (1)
  2. {
  3. data=(1<<i);
  4. //if(data==0xFF) data=0;
  5. i++;
  6. if(i>7) i=0;
  7. HAL_SPI_Transmit(&hspi1,&data,1,10);

  8. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,0);
  9. HAL_Delay(100);
  10. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,1);
  11. }
STM32 Blue Pill HSPI1 and SN74HC595N LED Example
SN74HC595N LED Shift

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
SN74HC595N LED Shift
 

Click here to download its source file. 

 



No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90