Tool/software: TI C/C++ Compiler
I've been working on this problem for a few weeks now, and I couldn't figure it out.
I need to control five states in a strict time manner. So, I am using two different timers, as showing in the code. Timer0A to wait for 1ms in S1 and S5, and Timer1A to wait for 1us in S2, S3, and S4. The problem is; Timer1A is always off; the wait time should be 1us in S2, S3, and S4 but it always varies between 0.8us and 5us.
Although the wait in Timer1A which control S2, S3, and S4 must be 1us, I changed the Timer1A to be 10us to test if 1us too fast for the microcontroller clock, but I faced another problem which is in every cycle before it switches to Timer0A it waits for 20us instead of 10us. I couldn't stabilize it to be 10us for the S2, S3, and S4.
The questions are, how to control the S2, S3, and S4 so the wait can be 1us before it switches? Is it even passable to use to timers one with 1ms and another for 1us with TM4C123g launchpad? Is there any better way to solve this problem?
I have attached a picture if you want to to see how the FSM should behave.
Thank you all.
#include <stdint.h> #include "PLL.h" #include "..//tm4c123gh6pm.h"
#define SW1A (*((volatile unsigned long *)0x40004010)) // PA2 #define SW1B (*((volatile unsigned long *)0x40004040)) // PA4 #define SW2A (*((volatile unsigned long *)0x40004080)) // PA5 #define SW2B (*((volatile unsigned long *)0x40004200)) // PA7 void DisableInterrupts(void); // Disable interrupts void EnableInterrupts(void); // Enable interrupts // State Machines States enum state_machine {State1, State2, State3, State4, State5} ; enum state_machine State = State1; // Variable to control State Machine direction unsigned int complementary_signal = 0; unsigned int count = 0; // Timer0 initialization // This Timer is configured for 1 ms // Calultion for Timer Reload Value // 1ms / 12.5 ns void Timer0_Init() { SYSCTL_RCGCTIMER_R |= 0x01; // 0) activate TIMER0 TIMER0_CTL_R = 0x00000000; // 1) disable TIMER0A during setup TIMER0_CFG_R = 0x00000000; // 2) configure for 32-bit mode TIMER0_TAMR_R = 0x00000002; // 3) configure for periodic mode, default down-count settings TIMER0_TAILR_R = 79000; // 4) reload value TIMER0_TAPR_R = 0; // 5) bus clock resolution TIMER0_ICR_R = 0x00000001; // 6) clear TIMER0A timeout flag TIMER0_IMR_R = 0x00000001; // 7) arm timeout interrupt NVIC_PRI4_R = (NVIC_PRI4_R&0x00FFFFFF)|0x80000000; // 8) priority 4 // interrupts enabled in the main program after all devices initialized // vector number 35, interrupt number 19 NVIC_EN0_R = 1<<19; // 9) enable IRQ 19 in NVIC TIMER0_CTL_R = 0x00000001; // 10) enable TIMER0A } // Timer1 initialization // This Timer is configured for 1 us // Calultion for Timer Reload Value // 1us / 12.5 ns void Timer1_Init(){ SYSCTL_RCGCTIMER_R |= 0x02; // 0) activate TIMER1 TIMER1_CTL_R = 0x00000000; // 1) disable TIMER1A during setup TIMER1_CFG_R = 0x00000000; // 2) configure for 32-bit mode TIMER1_TAMR_R = 0x00000002; // 3) configure for periodic mode, default down-count settings TIMER1_TAILR_R = 79; // 4) reload value TIMER1_TAPR_R = 0; // 5) bus clock resolution TIMER1_ICR_R = 0x00000001; // 6) clear TIMER1A timeout flag TIMER1_IMR_R = 0x00000001; // 7) arm timeout interrupt NVIC_PRI5_R = (NVIC_PRI5_R&0xFFFF00FF)|0x00008000; // 8) priority 4 // interrupts enabled in the main program after all devices initialized // vector number 37, interrupt number 21 NVIC_EN0_R = 1<<21; // 9) enable IRQ 21 in NVIC // Timer1 will be enabled by the interrupt of Timer0 //TIMER1_CTL_R = 0x00000001; // 10) enable TIMER1A } //This timer is only for State1 and State5. It's configured for 1 ms void Timer0A_Handler(void){ TIMER0_ICR_R = TIMER_ICR_TATOCINT;// acknowledge TIMER0A timeout for State1 and State5 if(complementary_signal == 0) { State++; } else { State--; } count = 0; TIMER0_CTL_R = 0x00000000; // disable TIMER0A TIMER1_CTL_R = 0x00000001; // enable TIMER1A } //This timer is only for State2, State3 and State4. It's configured for 1 us void Timer1A_Handler(void){ TIMER1_ICR_R = TIMER_ICR_TATOCINT;// acknowledge TIMER1A timeout count++; if(count == 3) { TIMER1_CTL_R = 0x00000000; // disable TIMER1A TIMER0_CTL_R = 0x00000001; // enable TIMER0A } else { if(complementary_signal == 0) { State++; } else { State--; } } } int main(void){ volatile unsigned long delay; PLL_Init(); // bus clock at 80 MHz SYSCTL_RCGC2_R |= 0x00000001; // 1) activate clock for Port A delay = SYSCTL_RCGC2_R; // allow time for clock to start GPIO_PORTA_AMSEL_R &= ~0xB4; // 3) disable analog on PA2, PA4, PA5 and PA7 GPIO_PORTA_PCTL_R &= ~0xF0FF0F00; // 4) PCTL GPIO on PA2, PA4, PA5 and PA7 GPIO_PORTA_DIR_R |= 0xB4; // 5) PA7 out GPIO_PORTA_AFSEL_R &= ~0xB4; // 6) disable alt funct on PA2, PA4, PA5 and PA7 GPIO_PORTA_DEN_R |= 0xB4; // 7) enable digital I/O on PA2, PA4, PA5 and PA7 Timer0_Init(); // Initialize Timer0 with 1ms period Timer1_Init(); // Initialize Timer1 with 1us period EnableInterrupts(); while(1){ switch(State) { case State1 : SW1A = 0x04; SW1B = 0x10; SW2A = 0x00; SW2B = 0x00; complementary_signal = 0; break; case State2 : SW1A = 0x04; SW1B = 0x10; SW2A = 0x20; SW2B = 0x00; break; case State3 : SW1A = 0x00; SW1B = 0x10; SW2A = 0x20; SW2B = 0x00; break; case State4 : SW1A = 0x00; SW1B = 0x10; SW2A = 0x20; SW2B = 0x80; break; case State5 : SW1A = 0x00; SW1B = 0x00; SW2A = 0x20; SW2B = 0x80; complementary_signal = 1; break; default : SW1A = 0x04; SW1B = 0x10; SW2A = 0x00; SW2B = 0x00; complementary_signal = 0; } } }