2019-02-21 04:48 PM
Hello !
I really need your help , im working on a project and its a game of luck , random numbers will appear on 4 x 7 Segments , so i must multiplex , i understood the principe but i can't reach some good results , i don't know why ...
only the common segment will always be on and the others off when im trying to test something on main .
example > 1234 only the segment b will be on . i ll be sharing my code and circuits and some photos thank you for your help !
Circuit http://www.fritzler-avr.de/HP/tipps/multi.php first photo
> the 4 Bases are going ofc to ports of the Stm , segments are connected to eachothers and then to stm, Collectors the Common Anodes like in the photo
Code :
#include "stm32f3xx.h"
#include <stdint.h>
void activation();
void showdigit (int digit);
void showdigits1 (int number);
void showdigits2 (int number);
void showdigits3 (int number);
void showdigits4 (int number);
void delay(unsigned int x);
void mode1 () ;
void mode2 () ;
void mode3 () ;
void mode4 () ;
int main(void){
int x = 1234 ;
activation() ;
for(;;){
mode1() ;
showdigits1(x);
delay(1000);
mode2() ;
showdigits2(x);
delay(1000);
mode3() ;
showdigits3(x);
delay(1000);
mode4();
showdigits4(x);
delay(1000);
}
}
//Delay function
volatile _Bool finished;
void delay(unsigned int x){
finished = 0;
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->DIER = TIM_DIER_UIE; // Update-Interrupt
TIM2->CNT = 0; TIM2->PSC = 7999; // 1 ms
TIM2->ARR = x - 1;
TIM2->CR1 = TIM_CR1_CEN; // Timer on
NVIC_EnableIRQ(TIM2_IRQn);
while (!finished)
__WFI(); TIM2->CR1 = 0;
return;
}
void TIM2_IRQHandler(void) {
finished = 1;
TIM2->SR &= ~TIM_SR_UIF; }
// end Delay Function
// Begin digitsfrom 0
void activation(){
RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // activation PORTS A
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // activation PORTS B
RCC->AHBENR |= RCC_AHBENR_GPIOCEN; // activation PORTS C
GPIOA->MODER |= 0b01 << 0; // segment d
GPIOA->MODER |= 0b01 << 2; // segment f
GPIOA->MODER |= 0b01 << 8; // segment e
GPIOA->MODER |= 0b01 << 16 ; // segment c
GPIOB->MODER |= 0b01 << 0; // segment g
GPIOC->MODER |= 0b01 << 2; // segment a
GPIOC->MODER |= 0b01 << 0; // segment b
GPIOB->MODER |= 0b01 << 20; // transistor1
GPIOB->MODER |= 0b01 << 10; // transistor2
GPIOB->MODER |= 0b01 << 12; // transistor3
GPIOA->MODER |= 0b01 << 18 ; //transistor4
}
/* PORTS DESCIPTION
Segment a PC1
Segment b PC0
Segment c PA8
Segment d PA0
Segment e PA4
Segment f PA1
Segment g PB0 */
// 0 is active emmeter => +VCC
void digit0 (){ // 0
GPIOB->ODR |= (1<<0);
}
void digit1 (){// 1
GPIOC->ODR |= (1<<1);
GPIOA->ODR |= (1<<1);
GPIOB->ODR |= (1<<0)
GPIOA->ODR |= (1<<4);
GPIOA->ODR |= (1<<0);
}
void digit2 (){// 2
GPIOA->ODR |= (1<<8);
GPIOA->ODR |= (1<<1);
}
void digit3 (){// 3
GPIOA->ODR |= (1<<4);
GPIOA->ODR |= (1<<1);
}
void digit4 (){// 4
GPIOC->ODR |= (1<<1);
GPIOA->ODR |= (1<<4);
GPIOA->ODR |= (1<<0);
}
void digit5 (){// 5
GPIOC->ODR |= (1<<0);
GPIOA->ODR |= (1<<4);
}
void digit6 (){// 6
GPIOC->ODR |= (1<<0);
}
void digit7 (){// 7
GPIOA->ODR |= (1<<4);
GPIOB->ODR |= (1<<0);
GPIOA->ODR |= (1<<1);
GPIOA->ODR |= (1<<0);
}
void digit8 (){// 8
}
void digit9 (){// 9
GPIOA->ODR |= (1<<4);
}
void showdigit (int digit) {
switch (digit)
{
case 0: digit0 ();
break;
case 1: digit1 ();
break;
case 2: digit2 ();
break;
case 3: digit3 ();
break;
case 4: digit4 ();
break;
case 5: digit5 ();
break;
case 6: digit6 ();
break;
case 7: digit7 ();
break;
case 8: digit8 ();
break;
case 9: digit9 ();
break;
default:
break;
};
};
// end digitsdefine from 0 to 9 and showing them
void showdigits1 (int number){
int x = number / 1000 ;
showdigit(x);
}
void showdigits2 (int number){
int y = (number % 1000) / 100 ;
showdigit(y);
}
void showdigits3 (int number){
int z = (number % 100) / 10 ;
showdigit(z);
}
void showdigits4 (int number){
int e = number % 10 ;
showdigit(e);
}
void mode1 () { // transistor 1 ON others OFF
GPIOA->ODR |= (1<<9);
GPIOB->ODR |= (1<<5);
GPIOB->ODR |= (1<<6);
GPIOB->ODR ^= (1<<10);
}
void mode2 () { // transistor 2 ON others OFF
GPIOA->ODR |= (1<<9);
GPIOB->ODR |= (1<<10);
GPIOB->ODR |= (1<<6);
GPIOB->ODR ^= (1<<5);
}
void mode3 () { // transistor 3 ON others OFF
GPIOA->ODR |= (1<<9);
GPIOB->ODR |= (1<<5);
GPIOB->ODR |= (1<<10);
GPIOB->ODR ^= (1<<6);
}
void mode4 () { // transistor 4 ON others OFF
GPIOB->ODR |= (1<<10);
GPIOB->ODR |= (1<<5);
GPIOB->ODR |= (1<<6);
GPIOA->ODR ^= (1<<9);
}
2019-02-23 05:06 AM
Really don't want to wade into this too deeply
You keep ORing values onto the GPIO pins, at some point they will all be HIGH and never go LOW, you should perhaps mask the bits of interest, and clear them.
Also writing to the register multiple times with RMW is very inefficient
Consider using BSRR to set/clear multiple bits in the GPIO ODR in a single write.
You interrupt routine should be more like this
void TIM2_IRQHandler(void)
{
if (TIM2->SR & TIM_SR_UIF) // Validate source
{
TIM2->SR = ~TIM_SR_UIF; // Clear with a write, not RMW action
finished = 1;
}
}