Menu

Adskeeper - header widge

728x90

Search This Blog

468x60

Navbar

AdsKeeper - IAB Display Standard Ad Unit

Sunday, November 16, 2025

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example

In previous post I use the HSPI1 communication interface of the STM32F103C8T6 to interface with the SN74HC595N serial-in-parallel out shift registers to control LEDs and 7-Segment display. In this programming example I use this chip to control the HD44780 compatible LCD controller. I use the TC1604A-01(R) LCM module from Tinsharp that I keep it many years now.

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example

The SPI communication is one direction that the master micro-controller just send serial data including command and display data to the LCD module. Hence the LCD R/W pin must wired to GND. 

SN74HC595 chips in DIP package

 

The controlling mode is 4-bit data mode that need to send the 8-bit command/data twice via its high nibble and low nibble.

The MCU clock is 64MHz that is driven from its 8MHz HSI and PLL.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
Clock Configuration

The operate in half duplex master mode with a baud rate of 16Mbits per second.

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

The NSS pin is ignored. So the enable pin must be set via software. I select PB4 as the SPI slave select pin. The Display Data RAM (DD RAM) of the TC1604A-01(R) is shown in the figure below.

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example
I put the LCD driver with the main.c source code.

  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. uint8_t DPORT;

  48. void delay1(uint16_t dTime){
  49. for(uint16_t i=0;i<dTime;i++);
  50. }

  51. void delay2(uint8_t dTime){
  52. for(uint8_t i=0;i<dTime;i++) delay1(5000);
  53. }

  54. void en(void){
  55. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
  56. delay1(1000);
  57. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
  58. }

  59. void lcdCmd(uint8_t cmd){
  60. uint8_t temp=0x08;
  61. DPORT=temp|(cmd&0xF0);
  62. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  63. en();
  64. delay1(10);
  65. temp=0;
  66. DPORT=temp|(cmd&0xF0);
  67. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  68. en();
  69. delay1(100);

  70. temp=0x08;
  71. DPORT=temp|(cmd<<4);
  72. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  73. en();
  74. delay1(10);
  75. temp=0;
  76. DPORT=temp|(cmd<<4);
  77. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  78. en();
  79. }

  80. void lcdDat(uint8_t dat){
  81. uint8_t temp=0x0A;
  82. DPORT=temp|(dat&0xF0);
  83. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  84. en();
  85. delay1(10);
  86. temp=0x02;
  87. DPORT=temp|(dat&0xF0);
  88. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  89. en();
  90. delay1(100);

  91. temp=0x0A;
  92. DPORT=temp|(dat<<4);
  93. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  94. en();
  95. delay1(10);
  96. temp=0x02;
  97. DPORT=temp|(dat<<4);
  98. HAL_SPI_Transmit(&hspi1,&DPORT,1,10);
  99. en();
  100. }

  101. void lcdInit(void){
  102. DPORT=0x00;
  103. delay1(2000);
  104. lcdCmd(0x33);
  105. delay1(100);
  106. lcdCmd(0x32);
  107. delay1(100);
  108. lcdCmd(0x28);
  109. delay1(100);
  110. lcdCmd(0x0F);
  111. delay1(100);
  112. lcdCmd(0x01);
  113. delay1(2000);
  114. lcdCmd(0x06);
  115. delay1(100);
  116. }

  117. void lcdStr(uint8_t *str){
  118. while(*str) lcdDat(*str++);
  119. }

  120. void lcdXY(uint8_t x,uint8_t y){
  121. // 20x4 LCD
  122. //uint8_t tbe[]={0x80,0xC0,0x94,0xD4};
  123. // 16x4 LCD
  124. uint8_t tbe[]={0x80,0xC0,0x90,0xD0};
  125. lcdCmd(tbe[y-1]+x-1);
  126. delay1(100);
  127. }

  128. void lcdClear(void){
  129. lcdCmd(0x01);
  130. delay1(12000);
  131. }

  132. /**
  133. * @brief The application entry point.
  134. * @retval int
  135. */
  136. int main(void)
  137. {
  138. /* USER CODE BEGIN 1 */

  139. /* USER CODE END 1 */

  140. /* MCU Configuration--------------------------------------------------------*/

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

  143. /* USER CODE BEGIN Init */

  144. /* USER CODE END Init */

  145. /* Configure the system clock */
  146. SystemClock_Config();

  147. /* USER CODE BEGIN SysInit */

  148. /* USER CODE END SysInit */

  149. /* Initialize all configured peripherals */
  150. MX_GPIO_Init();
  151. MX_SPI1_Init();
  152. /* USER CODE BEGIN 2 */
  153. HAL_Delay(100);
  154. lcdInit();
  155. lcdClear();
  156. lcdCmd(0x0C);
  157. lcdXY(3,1);
  158. lcdStr("Hello World!");

  159. lcdXY(3,2);
  160. lcdStr("STM32F103C8T6 ");

  161. lcdXY(1,3);
  162. lcdStr("HSPI1 SN74HC595N");

  163. lcdXY(1,4);
  164. lcdStr("TC1604A-01R LCD");

  165. HAL_Delay(5000);
  166. lcdClear();

  167. lcdXY(1,1);
  168. lcdStr("STM32CubeIDE");

  169. lcdXY(1,2);
  170. lcdStr("version 1.6.0");

  171. lcdXY(1,3);
  172. lcdStr("HAL Library...");

  173. lcdXY(1,4);
  174. lcdStr("16/11/2025");

  175. /* USER CODE END 2 */

  176. /* Infinite loop */
  177. /* USER CODE BEGIN WHILE */
  178. while (1)
  179. {
  180. /* USER CODE END WHILE */

  181. /* USER CODE BEGIN 3 */
  182. }
  183. /* USER CODE END 3 */
  184. }

  185. /**
  186. * @brief System Clock Configuration
  187. * @retval None
  188. */
  189. void SystemClock_Config(void)
  190. {
  191. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  192. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  193. /** Initializes the RCC Oscillators according to the specified parameters
  194. * in the RCC_OscInitTypeDef structure.
  195. */
  196. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  197. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  198. RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  199. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  200. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
  201. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
  202. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  203. {
  204. Error_Handler();
  205. }
  206. /** Initializes the CPU, AHB and APB buses clocks
  207. */
  208. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  209. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  210. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  211. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  212. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  213. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  214. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  215. {
  216. Error_Handler();
  217. }
  218. }

  219. /**
  220. * @brief SPI1 Initialization Function
  221. * @param None
  222. * @retval None
  223. */
  224. static void MX_SPI1_Init(void)
  225. {

  226. /* USER CODE BEGIN SPI1_Init 0 */

  227. /* USER CODE END SPI1_Init 0 */

  228. /* USER CODE BEGIN SPI1_Init 1 */

  229. /* USER CODE END SPI1_Init 1 */
  230. /* SPI1 parameter configuration*/
  231. hspi1.Instance = SPI1;
  232. hspi1.Init.Mode = SPI_MODE_MASTER;
  233. hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  234. hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  235. hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  236. hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  237. hspi1.Init.NSS = SPI_NSS_SOFT;
  238. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  239. hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  240. hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  241. hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  242. hspi1.Init.CRCPolynomial = 10;
  243. if (HAL_SPI_Init(&hspi1) != HAL_OK)
  244. {
  245. Error_Handler();
  246. }
  247. /* USER CODE BEGIN SPI1_Init 2 */

  248. /* USER CODE END SPI1_Init 2 */

  249. }

  250. /**
  251. * @brief GPIO Initialization Function
  252. * @param None
  253. * @retval None
  254. */
  255. static void MX_GPIO_Init(void)
  256. {
  257. GPIO_InitTypeDef GPIO_InitStruct = {0};

  258. /* GPIO Ports Clock Enable */
  259. __HAL_RCC_GPIOA_CLK_ENABLE();

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

  262. /*Configure GPIO pin : PA4 */
  263. GPIO_InitStruct.Pin = GPIO_PIN_4;
  264. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  265. GPIO_InitStruct.Pull = GPIO_NOPULL;
  266. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  267. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  268. }

  269. /* USER CODE BEGIN 4 */

  270. /* USER CODE END 4 */

  271. /**
  272. * @brief This function is executed in case of error occurrence.
  273. * @retval None
  274. */
  275. void Error_Handler(void)
  276. {
  277. /* USER CODE BEGIN Error_Handler_Debug */
  278. /* User can add his own implementation to report the HAL error return state */
  279. __disable_irq();
  280. while (1)
  281. {
  282. }
  283. /* USER CODE END Error_Handler_Debug */
  284. }

  285. #ifdef USE_FULL_ASSERT
  286. /**
  287. * @brief Reports the name of the source file and the source line number
  288. * where the assert_param error has occurred.
  289. * @param file: pointer to the source file name
  290. * @param line: assert_param error line source number
  291. * @retval None
  292. */
  293. void assert_failed(uint8_t *file, uint32_t line)
  294. {
  295. /* USER CODE BEGIN 6 */
  296. /* User can add his own implementation to report the file name and line number,
  297. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  298. /* USER CODE END 6 */
  299. }
  300. #endif /* USE_FULL_ASSERT */

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


I made my own DIY SN74HC595N LCD driver controlling a TC1604A-01(R) LCM module.

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example

It can be used with some Arduino libraries. It is very easy to use as it needs only five pins.

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example
Simulation #1

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example
Simulation #2

I use Proteus VSM to simulate this example.

In real hardware this LCD module work at +5VDC only while the STM32 Blue pill input output logic voltage is +3.3VDC. However some newer LCD module with the HD44780 compatible LCD controller able to operate at +3.3VDC.

 

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example
Running Program #2

STM32 Blue Pill HSPI1 and SN74HC595N 16x4 LCD Example
Running Program #1

Click here to download this example. 


 


Saturday, November 15, 2025

STM32 Blue Pill HSPI1 and SN74HC595N 7-Segment Display Example

In previous post, I use the SN74HC595N and the HSPI1 of the STM32F103C8T6 to control the output LEDs. This SPI chip could interface with any parallel input devices, 7-Segment, parallel port LCD, elector-mechanical relays etc.

For a simple example here I use a single common anode 7-segment display to show received SPI data.

STM32 Blue Pill HSPI1 and SN74HC595N 7-Segment Display Example

 

I made my own SN74HC595N 7-Segment board for testing.

STM32 Blue Pill HSPI1 and SN74HC595N 7-Segment Display Example
The SN74HC595N 7-Segment Board

 

The display I took from a scrapped HP Print-Scan-Copy device. The display type is common anode.

In this example the STM32F103C8T6 run at 64MHz that is driven from its 8MHz HSI oscillator and its Phase Lock Loop.

STM32 Blue Pill HSPI1 and SN74HC595N LED Example
Clock Configuration

I use the HSPI1 module Master Half Duplex Mode operates at 16MHz. 

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

 

I use Proteus VSM to draw and simulate this programming example. The program will send the Hexadecimal from 0 to F before it reset.

STM32 Blue Pill HSPI1 and SN74HC595N 7-Segment Display Example
Proteus Simulation Program

 

The source code I wrote is just a few lines.

  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. unsigned char patterns[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
  70. 0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
  71. unsigned char i=0,temp;
  72. /* Infinite loop */
  73. /* USER CODE BEGIN WHILE */
  74. while (1)
  75. {
  76. temp=~patterns[i];
  77. HAL_SPI_Transmit(&hspi1,&temp,1,100);
  78. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_SET);
  79. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_RESET);
  80. i++;
  81. if(i>15) i=0;
  82. HAL_Delay(500);
  83. }
  84. /* USER CODE END 3 */
  85. }

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

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

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

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

  127. /* USER CODE BEGIN SPI1_Init 0 */

  128. /* USER CODE END SPI1_Init 0 */

  129. /* USER CODE BEGIN SPI1_Init 1 */

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

  149. /* USER CODE END SPI1_Init 2 */

  150. }

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

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

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

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

  169. }

  170. /* USER CODE BEGIN 4 */

  171. /* USER CODE END 4 */

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

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

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

STM32 Blue Pill HSPI1 and SN74HC595N 7-Segment Display Example

I connect the supply voltage of the SN74HC595N to +5VDC to get an appropriate brightness while the STM32 Blue Pill works at +3.3VDC only. Click here to download this example. 

 

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. 

 



Adskeep- Standard Ads

336x280

DIY Electronic Projects And Instruments

AdsKeeper - 2091654

Labels

23K256 (1) 24C16B (2) 25AA010A (2) 8051 (7) 93AA46B (1) ADC (39) Analog Comparator (1) Arduino (16) ARM (32) AT89C52 (7) ATMega32 (59) ATMega644P (27) AVR (88) AVR PCB (2) Bootloader (1) CCS PICC (31) Change Notify Interrupt (CNI) (2) DAC (2) DHT11 (5) Display (156) Distance Sensor (3) dot matrix (1) ds1307 (10) DS18B20 (6) ds3231 (1) ds3232 (2) dsPIC (12) dsPIC30F1010 (3) dsPIC30F2010 (12) EEPROM (5) Environment Sensor (6) ESP32 (1) esp8266 (1) Graphical LCD (3) HD44780 (10) I2C (38) ILI9341 (1) Input/Output (83) Interrupt (22) IoT PCB (1) Keil (5) Keypad (16) KS0108 (3) LCD (84) LM35 (4) Master/Slave (2) MAX7221 (1) MCP23017 (8) MCP23S17 (7) MCP4921 (1) MCP4922 (2) Meter (3) MikroC (2) MikroC ARM (1) MikroC dsPIC (7) Module PCB (2) Motor (15) MPLABX (73) Nokia 5110 LCD (4) OLED (2) One-Wire (7) Oscillator (8) PCB (13) PCD8544 (3) PCF8574 (10) PIC (116) PIC12F (3) PIC16 (105) PIC16F628A (3) PIC16F630 (2) PIC16F716 (4) PIC16F818 (11) PIC16F818/819 (3) PIC16F84A (16) PIC16F876A (2) PIC16F877A (9) PIC16F88 (2) PIC16F887 (60) PIC18 (19) PIC18F1220 (5) PIC18F2550 (5) PIC18F4550 (12) PICKit2 (1) PICMicro PCB (4) Pin Change Interrupt (1) PWM (12) RTC (12) SBN0064G (1) Sensor (15) SH1106 (3) Shift Register (15) Shift Registers (19) SN74HC595N (9) Software TWI (2) SPI (44) sprinf (3) ST7735 (1) STM32 (29) STM32 Black Pill (1) STM32 Blue Pill (12) STM32 HAL (23) STM32CubeIDE (32) STM32F103C8T6 (9) STM32F103R6 (18) STM32F401CCU6 (1) SysTick (7) temperature sensor (15) TFT (1) TG12864A (1) Thermometer (22) Timer/Counter (32) TM1637 (2) twi (10) UART (11) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (96)