Tool/software: Code Composer Studio
Hi, i want to control a traffic light in that way:
Firstly i have to say that orange colour is when leds green and red are ON at same time.
At first place traffic light will be with green led ON. Then, when someone press the botton S2 of the launchpad (P1.1), green led blinks with a period of 1/8 second. After one second, traffic light change its colour to orange without blinking (as i said before both green and red are ON now) during 2 seconds. After that, traffic light change its colour to Red for 3 seconds and, when these 3 seconds finish, it begins to blink in red colour at period of 1/16 seconds during 1 last second. After this sequence, it starts over by changing traffic light colour again to Green without blinking and waiting for someone to push the button again.
A bit 'extra' is that i wanna count the number of people that pressed the button with a variable --> numero_peatones. And also i want to add a buzzer (perhaps a passive one) which i can control with a PWM signal. So, for example, when is near to finish one state and begin next one (such as changing colour green to orange), i want to increase PWM signal in order to increase the sound it goes off the buzzer.
This last part i haven't done yet, because i have some sort of a problem with the sequence. I think the problem is in the delay_segundos function but i don't know why. If anyone can take a look on my code with ideas of optimization and also to fix my issue i will apreciatte it a lot! Thanks:)
My code:
#include <msp430.h>
#include <stdint.h>
uint8_t numero_peatones = 0;
uint16_t volatile contador_segundos;
uint8_t conteo_pulsador = 0;
void Inicializacion_Relojes(void) // Para usar el reloj SMCLK a 1 MHz
{
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL0 = 0x0000; // Ponemos el DCOx y MODx al minimo posible
UCSCTL1 = DCORSEL_5; // Seleccionamos un rango de operación del DCO range de 16MHz
UCSCTL2 = FLLD_0 | 487; // Poniendo FLLD_0 hacemos tomamos como 1 el divisor de la frecuencia de entrada del cristal de cuarzo y 487 es el valor multiplicador de FLLN
// (N + 1) * (FLLRef/n) = Fdcomsp430
// (487 + 1) * (32768/1) = 16MHz
UCSCTL3 = 0; // FLL SELREF = XT1CLK y divisor de FLL = 1 (FLLREFDIV = FLLREFCLK/1)
UCSCTL4 |= SELA_0 | SELS_4 | SELM_4; // Tomamos ACLK = XT1CLK (Cuarzo externo de 2^15 bits); SMCLK = MCLK = DCOCLKDIV (DCO interno de 16 MHz)
UCSCTL5 |= DIVA_0 | DIVS_4; // Divisor para SMCLK = f(SMCLK)/16; ACLK = f(ACLK)/1
__bic_SR_register(SCG0); // Enable the FLL control loop
}
void inicializacion_pulsador(void)
{
P1SEL = 0x00; // GPIO pins
P1DIR &= ~BIT1; // input P1.1
P1REN |= BIT1; // enable Pull up/down
P1OUT |= BIT1; // Pull-up interna en pin 1.1
P1IES |= BIT1;
P1IE |= BIT1;
P1IFG &= ~BIT1;
}
void inicializacion_LEDs(void)
{
P1SEL &= ~BIT0; // LED1 of Launchpad as GPIO
P1DIR |= BIT0; // LED1 as output
P1OUT &= ~BIT0; // RED LED off at first place
P4SEL &= ~BIT7;
P4DIR |= BIT7; // LED2 as output
P4OUT |= BIT7; // GREEN LED on at first place
}
void delay_segundos(uint8_t segundos) // Function for delay sec --> Reloj ACLK
{
contador_segundos = 0;
TA2CTL |= MC_1; // UP MODE
TA2CCTL0 |= CCIE; // enable interrupts timer A2
while(contador_segundos < segundos);
TA2CTL &= ~MC_3; // Stop timer
}
void TimerA0(void) // Timer to count 1/8 sec
{
TA0CCR0 = 15624; // f(SMCLK)/8 = 125kHz --> want to count 1/8 sec --> TA0CCR0 = (125kHz/8) - 1 = 15624.
TA0CTL |= TASSEL_2 | ID_3 | MC_0; // TASSEL_2: SMCLK; ID_3: Divisor freq --> f(SMCLK)/8; MC_0: Stop Mode
}
void TimerA1(void) // Timer to count 1/16 seconds
{
TA1CCR0 = 15624; // f(SMCLK)/4 = 250kHz --> want to count 1/16 sec --> TA1CCR0 = (250kHz/16) - 1 = 15624.
TA1CTL |= TASSEL_2 | ID_2 | MC_0; // TASSEL_2: SMCLK; ID_2: Divisor freq --> f(SMCLK)/4;
}
void TimerA2(void) // Timer for seconds
{
TA2CCR0 = 8191; // f(ACLK)/4 = 8192Hz
TA2CTL |= TASSEL_1 | ID_2 | MC_0; // TASSEL_2: ACLK; ID_2: Divisor freq --> f(ACLK)/4; MC_0: Stop Mode
}
void main()
{
Inicializacion_Relojes();
inicializacion_pulsador();
inicializacion_LEDs();
TimerA0();
TimerA1();
TimerA2();
__enable_interrupt();
while(1){
if(conteo_pulsador == 1)
{
delay_segundos(1);
conteo_pulsador = 0;
P4OUT |= BIT7; // ORANGE LED
P1OUT |= BIT0;
delay_segundos(2);
P1OUT |= BIT0; when 2 seconds had passed, RED LED is ON
delay_segundos(3);
TA1CCTL0 |= CCIE; // enable interrupts of RED LED --> 1/16 sec
delay_segundos(1);
P4OUT |= BIT7; // GREEN LED on
P1OUT &= ~BIT0; // RED LED off
}
}
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void timerA0_0_isr(void)
{
P4OUT ^= BIT7; // GREEN LED blinking
TA0CCTL0 &= ~CCIFG;
}
#pragma vector=TIMER1_A0_VECTOR
__interrupt void timerA1_0_isr(void)
{
P1OUT ^= BIT0; // RED LED blinking
TA1CCTL0 &= ~CCIFG;
}
#pragma vector=TIMER2_A0_VECTOR
__interrupt void timer2_A0_ISR(void) // ISR of Timer for counting seconds to delay
{
contador_segundos++; // Increase the variable that counts the seconds
TA2CCTL0 &= ~CCIFG;
}
#pragma vector=PORT1_VECTOR // ISR del pulsador P1.1 (S2)
__interrupt void port1_ISR(void)
{
if(P1IFG & BIT1){ // when the button is pressed --> GREEN LED blinks to 1/8 sec
numero_peatones++;
P1IE &= ~BIT1; // disable temporaly interrupts on the button
TA0CTL |= MC_1; // MC_1: Up Mode
TA0CCTL0 |= CCIE; // enable interrupts
P1IFG &= ~BIT1; // clear flag
conteo_pulsador++;
}
}