Added 7-segment display with 595 shift register

master
unicod 1 month ago
parent d2ff50a161
commit 26807a7d16

@ -0,0 +1,10 @@
#ifndef DISP7SEG_H_INCLUDED
#define DISP7SEG_H_INCLUDED
#include <stdint.h>
extern void DispPutDigit(uint8_t pos, char chr, uint8_t dp);
extern void ShiftReg_Update(void);
#endif

@ -71,8 +71,14 @@ void Error_Handler(void);
/* USER CODE END EFP */ /* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/
#define SHR_CLK_Pin LL_GPIO_PIN_14
#define SHR_CLK_GPIO_Port GPIOC
#define SHR_STR_Pin LL_GPIO_PIN_15
#define SHR_STR_GPIO_Port GPIOC
#define LD2_Pin LL_GPIO_PIN_11 #define LD2_Pin LL_GPIO_PIN_11
#define LD2_GPIO_Port GPIOC #define LD2_GPIO_Port GPIOC
#define SHR_DOUT_DISP_Pin LL_GPIO_PIN_8
#define SHR_DOUT_DISP_GPIO_Port GPIOB
#ifndef NVIC_PRIORITYGROUP_0 #ifndef NVIC_PRIORITYGROUP_0
#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bit for pre-emption priority, #define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bit for pre-emption priority,
4 bits for subpriority */ 4 bits for subpriority */
@ -87,6 +93,17 @@ void Error_Handler(void);
#endif #endif
/* USER CODE BEGIN Private defines */ /* USER CODE BEGIN Private defines */
static inline void Delay_us() { LL_mDelay(1); } // TODO: implement real microsecond delay
// Shift register control macros
#define SHR_COUNT 4
static inline void SHRCLK_HI() { LL_GPIO_SetOutputPin( SHR_CLK_GPIO_Port, SHR_CLK_Pin); }
static inline void SHRCLK_LO() { LL_GPIO_ResetOutputPin( SHR_CLK_GPIO_Port, SHR_CLK_Pin); }
static inline void SHRSTR_HI() { LL_GPIO_SetOutputPin( SHR_STR_GPIO_Port, SHR_STR_Pin); }
static inline void SHRSTR_LO() { LL_GPIO_ResetOutputPin( SHR_STR_GPIO_Port, SHR_STR_Pin); }
static inline void SHRDIN_HI() { LL_GPIO_SetOutputPin( SHR_DOUT_DISP_GPIO_Port, SHR_DOUT_DISP_Pin); }
static inline void SHRDIN_LO() { LL_GPIO_ResetOutputPin( SHR_DOUT_DISP_GPIO_Port, SHR_DOUT_DISP_Pin); }
/* USER CODE END Private defines */ /* USER CODE END Private defines */

@ -0,0 +1,94 @@
/***************************************************************************//**
* @file disp7seg.c
* @brief 7-segment display handling
*******************************************************************************/
#include "disp7seg.h"
#include "main.h"
static uint8_t ShrBuf[SHR_COUNT] = {0}; // buffer for ext. shift register
static uint8_t ShrDirty = 1; // update request
/***************************************************************************//**
* @brief Write data to external shift register on changes
*******************************************************************************/
void ShiftReg_Update() {
if (ShrDirty == 0) return; // register is up to date
ShrDirty = 0;
uint_fast8_t shrsel = SHR_COUNT;
while (shrsel--) {
uint8_t reg = ShrBuf[shrsel];
uint_fast8_t clkcnt;
for (clkcnt = 0; clkcnt < 8; clkcnt++) {
SHRCLK_LO();
if (reg & 0x80) { SHRDIN_HI(); }
else { SHRDIN_LO(); }
reg <<= 1; // shift left
Delay_us(1);
SHRCLK_HI(); // clock pulse
Delay_us(1);
}
}
SHRSTR_HI(); // strobe pulse
SHRCLK_LO();
SHRDIN_LO();
Delay_us(1);
SHRSTR_LO();
}
/***************************************************************************//**
/brief Segment table for 7 segment display
For ASCII characters range 0x20...0x60
Segment <--> bit allocation
/code
0000
5 1
5 1
6666
4 2
4 2
3333 77
*******************************************************************************/
static const uint8_t LcdAscii7segTable[] = {
0x00, 0x82, 0xA2, 0x5C, 0x6D, 0x00, 0x7F, 0x02, // space ... apostrof
0x39, 0x0F, 0x00, 0x00, 0x04, 0x40, 0x00, 0x52, // ( ... slash
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, // 0 ... 9
0x48, 0x48, 0x58, 0x48, 0x4C, 0x53, 0x7B, // : ... @
0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x3D, 0x76, // ABCDEFGH
0x06, 0x1E, 0x7A, 0x38, 0x37, 0x54, 0x3F, 0x73, // IJKLMNOP
0x67, 0x50, 0x6D, 0x78, 0x3E, 0x3E, 0x3E, 0x76, // QRSTUVWX
0x6E, 0x5B, 0x39, 0x64, 0x0F, 0x23, 0x08, 0x60, // YZ[\]^_`
0x5F, 0x7C, 0x58, 0x5E, 0x79, 0x71, 0x6F, 0x74, // abcdefgh
0x04, 0x1E, 0x7A, 0x06, 0x37, 0x54, 0x5C, 0x73, // ijklmnop
0x67, 0x50, 0x6D, 0x78, 0x1C, 0x1C, 0x1C, 0x76, // qrstuvwx
0x6E, 0x5B, 0x39, 0x30, 0x0F, 0x62 // yz{|}~
};
/***************************************************************************//**
* \brief Print characters to 7 segment display
*******************************************************************************/
void DispPutDigit(uint8_t pos, char chr, uint8_t dp) {
if (pos >= SHR_COUNT) return;
uint8_t* disp_buf = ShrBuf;
uint8_t segments;
uint8_t c = chr;
if (c >= ' ' && c < 127) segments = LcdAscii7segTable[c-' '];
//else if (c == '°') segments = 0x63;
else segments = 0;
if (dp) segments |= 0x80; // decimal point
uint8_t prevseg = disp_buf[pos];
disp_buf[pos] = ~segments; // write new digit
if (prevseg != disp_buf[pos]) { // buffer changed
ShrDirty = 1; // update request
}
}

@ -21,6 +21,7 @@
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
#include "disp7seg.h"
/* USER CODE END Includes */ /* USER CODE END Includes */
@ -101,6 +102,12 @@ int main(void)
LL_Init1msTick(SystemCoreClock); LL_Init1msTick(SystemCoreClock);
DispPutDigit(0, ' ', 0);
DispPutDigit(1, ' ', 0);
DispPutDigit(2, ' ', 0);
DispPutDigit(3, ' ', 0);
ShiftReg_Update();
/* USER CODE END 2 */ /* USER CODE END 2 */
/* Infinite loop */ /* Infinite loop */
@ -109,6 +116,13 @@ int main(void)
{ {
LD2_Toggle(); LD2_Toggle();
LL_mDelay(250); LL_mDelay(250);
static uint8_t cnt = 0;
DispPutDigit(0, '0'+cnt, 0);
DispPutDigit(1, 'a'+cnt, 1);
DispPutDigit(2, 'A'+cnt, 0);
DispPutDigit(3, 'Z'-cnt, 1);
if (++cnt > 9) cnt = 0;
ShiftReg_Update();
/* USER CODE END WHILE */ /* USER CODE END WHILE */
/* USER CODE BEGIN 3 */ /* USER CODE BEGIN 3 */
@ -209,20 +223,35 @@ static void MX_GPIO_Init(void)
/* USER CODE END MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */ /* GPIO Ports Clock Enable */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
/**/
LL_GPIO_ResetOutputPin(GPIOC, SHR_CLK_Pin|SHR_STR_Pin);
/**/
LL_GPIO_ResetOutputPin(SHR_DOUT_DISP_GPIO_Port, SHR_DOUT_DISP_Pin);
/**/ /**/
LL_GPIO_SetOutputPin(LD2_GPIO_Port, LD2_Pin); LL_GPIO_SetOutputPin(LD2_GPIO_Port, LD2_Pin);
/**/ /**/
GPIO_InitStruct.Pin = LD2_Pin; GPIO_InitStruct.Pin = SHR_CLK_Pin|SHR_STR_Pin|LD2_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = SHR_DOUT_DISP_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct); LL_GPIO_Init(SHR_DOUT_DISP_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE BEGIN MX_GPIO_Init_2 */

@ -56,19 +56,22 @@ Mcu.IP8=SYS
Mcu.IPNb=9 Mcu.IPNb=9
Mcu.Name=STM32H533RETx Mcu.Name=STM32H533RETx
Mcu.Package=LQFP64 Mcu.Package=LQFP64
Mcu.Pin0=PH0-OSC_IN(PH0) Mcu.Pin0=PC14-OSC32_IN(OSC32_IN)
Mcu.Pin1=PH1-OSC_OUT(PH1) Mcu.Pin1=PC15-OSC32_OUT(OSC32_OUT)
Mcu.Pin10=VP_BOOTPATH_VS_BOOTPATH Mcu.Pin10=VP_PWR_VS_SECSignals
Mcu.Pin11=VP_MEMORYMAP_VS_MEMORYMAP Mcu.Pin11=VP_PWR_VS_LPOM
Mcu.Pin2=PA13(JTMS/SWDIO) Mcu.Pin12=VP_SYS_VS_Systick
Mcu.Pin3=PA14(JTCK/SWCLK) Mcu.Pin13=VP_BOOTPATH_VS_BOOTPATH
Mcu.Pin4=PC11 Mcu.Pin14=VP_MEMORYMAP_VS_MEMORYMAP
Mcu.Pin5=VP_CORTEX_M33_NS_VS_Hclk Mcu.Pin2=PH0-OSC_IN(PH0)
Mcu.Pin6=VP_ICACHE_VS_ICACHE Mcu.Pin3=PH1-OSC_OUT(PH1)
Mcu.Pin7=VP_PWR_VS_SECSignals Mcu.Pin4=PA13(JTMS/SWDIO)
Mcu.Pin8=VP_PWR_VS_LPOM Mcu.Pin5=PA14(JTCK/SWCLK)
Mcu.Pin9=VP_SYS_VS_Systick Mcu.Pin6=PC11
Mcu.PinsNb=12 Mcu.Pin7=PB8
Mcu.Pin8=VP_CORTEX_M33_NS_VS_Hclk
Mcu.Pin9=VP_ICACHE_VS_ICACHE
Mcu.PinsNb=15
Mcu.ThirdPartyNb=0 Mcu.ThirdPartyNb=0
Mcu.UserConstants= Mcu.UserConstants=
Mcu.UserName=STM32H533RETx Mcu.UserName=STM32H533RETx
@ -89,11 +92,23 @@ PA13(JTMS/SWDIO).Mode=Serial_Wire
PA13(JTMS/SWDIO).Signal=DEBUG_JTMS-SWDIO PA13(JTMS/SWDIO).Signal=DEBUG_JTMS-SWDIO
PA14(JTCK/SWCLK).Mode=Serial_Wire PA14(JTCK/SWCLK).Mode=Serial_Wire
PA14(JTCK/SWCLK).Signal=DEBUG_JTCK-SWCLK PA14(JTCK/SWCLK).Signal=DEBUG_JTCK-SWCLK
PB8.GPIOParameters=GPIO_Label
PB8.GPIO_Label=SHR_DOUT_DISP
PB8.Locked=true
PB8.Signal=GPIO_Output
PC11.GPIOParameters=PinState,GPIO_Label PC11.GPIOParameters=PinState,GPIO_Label
PC11.GPIO_Label=LD2 PC11.GPIO_Label=LD2
PC11.Locked=true PC11.Locked=true
PC11.PinState=GPIO_PIN_SET PC11.PinState=GPIO_PIN_SET
PC11.Signal=GPIO_Output PC11.Signal=GPIO_Output
PC14-OSC32_IN(OSC32_IN).GPIOParameters=GPIO_Label
PC14-OSC32_IN(OSC32_IN).GPIO_Label=SHR_CLK
PC14-OSC32_IN(OSC32_IN).Locked=true
PC14-OSC32_IN(OSC32_IN).Signal=GPIO_Output
PC15-OSC32_OUT(OSC32_OUT).GPIOParameters=GPIO_Label
PC15-OSC32_OUT(OSC32_OUT).GPIO_Label=SHR_STR
PC15-OSC32_OUT(OSC32_OUT).Locked=true
PC15-OSC32_OUT(OSC32_OUT).Signal=GPIO_Output
PCC.Checker=false PCC.Checker=false
PCC.Line=STM32H5x3 PCC.Line=STM32H5x3
PCC.MCU=STM32H533RETx PCC.MCU=STM32H533RETx

Loading…
Cancel
Save