2024-08-21 02:50 AM
Hello,
So, I'm trying to display a 4 Digit number on 4 7-segment Display using multiplexing
The issues are - 1. I'm using different Ports for Segments and Different Ports For common Cathode Pins ( I'll add the code below)
2. I'm Directly using GPIO to segment Pins without having any IC in between
Flow of the code is as follows :-
- Start
- for UP/DOWN button press
- If UP button is pressed then increment the counter
- Display the value of the counter on 7 segment display
- check if button is still being held
- If yes continue incrementing
- If no then stop
- same for DOWN Button used for decrement
- End
Here my increment and decrement function is working as expected but I'm not getting how can I display that counter values on 4 7-segment
I wrote a code as follows
In this code when i press up button only 3rd display is constantly turning on with value all other display just turned on for fraction of sec and then turned off. I want it continuously to display the values which are incrementing and decrementing
(sorry if the code is confusing i didn't comment or remove some unnecessary part)
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define SEG_A_PORT GPIOB
#define SEG_A_PIN GPIO_PIN_9
#define SEG_B_PORT GPIOB
#define SEG_B_PIN GPIO_PIN_8
#define SEG_E_PORT GPIOD
#define SEG_E_PIN GPIO_PIN_6
#define SEG_C_PORT GPIOB
#define SEG_C_PIN GPIO_PIN_7
#define SEG_D_PORT GPIOB
#define SEG_D_PIN GPIO_PIN_6
#define SEG_F_PORT GPIOD
#define SEG_F_PIN GPIO_PIN_5
#define SEG_G_PORT GPIOD
#define SEG_G_PIN GPIO_PIN_1
#define SEG_DP_PORT GPIOC
#define SEG_DP_PIN GPIO_PIN_8
#define DIGIT1_PORT GPIOC
#define DIGIT1_PIN GPIO_PIN_10 //CC1
#define DIGIT2_PORT GPIOB
#define DIGIT2_PIN GPIO_PIN_4 //CC2
#define DIGIT3_PORT GPIOB
#define DIGIT3_PIN GPIO_PIN_3 //CC3
#define DIGIT4_PORT GPIOC
#define DIGIT4_PIN GPIO_PIN_9 //CC4
//#define START_BUTTON_GPIO_Port GPIOD
//#define START_BUTTON_Pin GPIO_PIN_9
#define UP_BUTTON_GPIO_Port GPIOD
#define UP_BUTTON_Pin GPIO_PIN_8
#define DOWN_BUTTON_GPIO_Port GPIOA
#define DOWN_BUTTON_Pin GPIO_PIN_15
#define min_down 0
#define max_down 10
#define min_up -1
#define max_up 9
#define MIN_DIGIT 0
#define MAX_DIGIT 9
#define NUM_DIGITS 4
#define DISPLAY_UPDATE_INTERVAL 2 // Time in milliseconds for display update
uint8_t counter = 0;
const uint8_t max = 9; // Example maximum value
const uint8_t min = 0; // Example minimum value
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
//volatile uint8_t current_digit_index = 0;
//volatile uint8_t display_digits[4] = {0, 0, 0, 0}; // Array to hold digits to display
//volatile uint8_t multiplexing_active = 1; // Flag to control multiplexing
uint8_t digits[4] = {0, 0, 0, 0};
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void set_segment(GPIO_TypeDef* port, uint16_t pin, uint8_t value) {
if (value) {
HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET);
}
}
void TurnOffAllDigits(void) {
HAL_GPIO_WritePin(DIGIT1_PORT, DIGIT1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(DIGIT2_PORT, DIGIT2_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(DIGIT3_PORT, DIGIT3_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(DIGIT4_PORT, DIGIT4_PIN, GPIO_PIN_SET);
}
void DisplayDigits(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4) {
// Segment representation for digits 0-9
const uint8_t segments[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};
// Array to hold digit values for the display
uint8_t segment_bits[4];
segment_bits[0] = segments[digit1];
segment_bits[1] = segments[digit2];
segment_bits[2] = segments[digit3];
segment_bits[3] = segments[digit4];
// Time to display each digit
const uint32_t digit_delay = 2; // Time in milliseconds for displaying each digit
const uint32_t total_display_time = digit_delay * NUM_DIGITS;
uint32_t start_time = HAL_GetTick();
uint8_t current_digit = 0;
while (HAL_GetTick() - start_time < total_display_time) {
// Turn off all digits
TurnOffAllDigits();
// Turn on the current digit
switch (current_digit) {
case 0: HAL_GPIO_WritePin(DIGIT1_PORT, DIGIT1_PIN, GPIO_PIN_RESET); break;
case 1: HAL_GPIO_WritePin(DIGIT2_PORT, DIGIT2_PIN, GPIO_PIN_RESET); break;
case 2: HAL_GPIO_WritePin(DIGIT3_PORT, DIGIT3_PIN, GPIO_PIN_RESET); break;
case 3: HAL_GPIO_WritePin(DIGIT4_PORT, DIGIT4_PIN, GPIO_PIN_RESET); break;
}
// Set segment values based on current digit
uint8_t bits = segment_bits[current_digit];
set_segment(SEG_A_PORT, SEG_A_PIN, !(bits & 0x01));
set_segment(SEG_B_PORT, SEG_B_PIN, !(bits & 0x02));
set_segment(SEG_C_PORT, SEG_C_PIN, !(bits & 0x04));
set_segment(SEG_D_PORT, SEG_D_PIN, !(bits & 0x08));
set_segment(SEG_E_PORT, SEG_E_PIN, !(bits & 0x10));
set_segment(SEG_F_PORT, SEG_F_PIN, !(bits & 0x20));
set_segment(SEG_G_PORT, SEG_G_PIN, !(bits & 0x40));
// Small delay to allow digit display to be visible
HAL_Delay(digit_delay);
// Move to the next digit
current_digit = (current_digit + 1) % NUM_DIGITS;
}
}
void MultiplexDisplay(uint8_t* digits) {
static uint8_t current_digit = 0;
TurnOffAllDigits(); // Turn off all digits
// Display the current digit
switch (current_digit) {
case 0: HAL_GPIO_WritePin(DIGIT1_PORT, DIGIT1_PIN, GPIO_PIN_RESET); break;
case 1: HAL_GPIO_WritePin(DIGIT2_PORT, DIGIT2_PIN, GPIO_PIN_RESET); break;
case 2: HAL_GPIO_WritePin(DIGIT3_PORT, DIGIT3_PIN, GPIO_PIN_RESET); break;
case 3: HAL_GPIO_WritePin(DIGIT4_PORT, DIGIT4_PIN, GPIO_PIN_RESET); break;
}
// Set segment values based on current digit
uint8_t digit_value = digits[current_digit];
const uint8_t segments[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};
uint8_t bits = segments[digit_value];
set_segment(SEG_A_PORT, SEG_A_PIN, !(bits & 0x01));
set_segment(SEG_B_PORT, SEG_B_PIN, !(bits & 0x02));
set_segment(SEG_C_PORT, SEG_C_PIN, !(bits & 0x04));
set_segment(SEG_D_PORT, SEG_D_PIN, !(bits & 0x08));
set_segment(SEG_E_PORT, SEG_E_PIN, !(bits & 0x10));
set_segment(SEG_F_PORT, SEG_F_PIN, !(bits & 0x20));
set_segment(SEG_G_PORT, SEG_G_PIN, !(bits & 0x40));
// Move to the next digit
current_digit = (current_digit + 1) % 4;
}
int _write(int file, char *ptr, int len){
HAL_UART_Transmit(&huart2, (uint8_t*)ptr, len, HAL_MAX_DELAY);
return len;
}
void update_counter(int *counter, int direction) {
int tens = *counter / 10;
int units = *counter % 10;
units += direction;
// Check for units digit wrapping
if (units > MAX_DIGIT) {
units = MIN_DIGIT;
tens += 1;
} else if (units < MIN_DIGIT) {
units = MAX_DIGIT;
tens -= 1;
}
// Check for tens digit wrapping
if (tens > MAX_DIGIT) {
tens = MIN_DIGIT;
} else if (tens < MIN_DIGIT) {
tens = MAX_DIGIT;
}
*counter = tens * 10 + units;
}
void handle_buttons() {
static int counter = 44;
if (HAL_GPIO_ReadPin(DOWN_BUTTON_GPIO_Port, DOWN_BUTTON_Pin) == GPIO_PIN_RESET) {
HAL_Delay(250);
if (HAL_GPIO_ReadPin(DOWN_BUTTON_GPIO_Port, DOWN_BUTTON_Pin) == GPIO_PIN_RESET) {
update_counter(&counter, -1); // Decrement
printf("%d\r\n", counter);
int tens = counter / 10;
int units = counter % 10;
//
// // Update display with the new counter value
//
// uint8_t digits[4] = {0, tens, units, 0};
// MultiplexDisplay(digits);
DisplayDigits(0,tens,units,0);
while (HAL_GPIO_ReadPin(DOWN_BUTTON_GPIO_Port, DOWN_BUTTON_Pin) == GPIO_PIN_SET) {
HAL_Delay(500);
}
}
} else if (HAL_GPIO_ReadPin(UP_BUTTON_GPIO_Port, UP_BUTTON_Pin) == GPIO_PIN_RESET) {
HAL_Delay(250);
if (HAL_GPIO_ReadPin(UP_BUTTON_GPIO_Port, UP_BUTTON_Pin) == GPIO_PIN_RESET) {
update_counter(&counter, 1); // Increment
printf("%d\r\n", counter);
int tens = counter / 10;
int units = counter % 10;
//
// uint8_t digits[4] = {0, tens, units, 0};
// MultiplexDisplay(digits);
DisplayDigits(0,tens,units ,0);
// uint8_t digits[4] = {0, counter / 10, counter % 10, 0};
while (HAL_GPIO_ReadPin(UP_BUTTON_GPIO_Port, UP_BUTTON_Pin) == GPIO_PIN_SET) {
HAL_Delay(500);
}
}
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
// uint8_t digit = 0 ;
// uint8_t value = 0;
//static uint32_t counter = 0;
// DisplayDigits(1,2,3,4);
//uint8_t digits[4] = {0, 0, 0, 0};
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
handle_buttons();
}
}
2024-08-21 03:13 AM
@Omkar23 wrote:I'm not getting how can I display that counter values on 4 7-segment
As always, the way to approach this is to get one part working at a time - don't try to do everything all at once!
So start with some code which just displays a 4-digit number - get rid of all the other complications of buttons, counters, etc.
It needs to;
Use the debugger to step your code and see that it's working.
You could also use the debugger to change the number being displayed ...
2024-08-21 04:22 AM
1. I'm using different Ports for Segments and Different Ports For common Cathode Pins ( I'll add the code below)
2. I'm Directly using GPIO to segment Pins without having any IC in between
This is not the right way to drive the 7-segment display. You need to take care about the currents source/sink as you can break the IOs of your MCU. So you need at least a current booster on GPIOs using transistors or similar on common Cathode pins to drive the display.
You can find many schematics on the net on how to do this.