0
\$\begingroup\$

I am using TivaC TM4C123 MCU. I am trying to send data serially through one pin and a synchronized clock through another pin. Here is an illustration:

enter image description here

I used Timer0 module for the serial data and Timer1 for the clock. The frequency of the clock should be twice the data. Here is the important part of the code:

void DATA(long number, int iteration) //number: data to be send serially
{ 
    long x=0;                           // iteration: number of bits to send 
    for(int y=0; y<iteration ; y++) {
        while((TIMER0->RIS & 0x00000001) != 1){}  //wait until Timer0 times out 
        x= number & (0x1<<y);      //Get each bit individually  
        if(x==(0X1<<y))            //If bit is 1
            GPIOF->DATA |= (1<<1); //Make PF1 High 
        else if(x==0X0) //If bit is 0
            GPIOF->DATA &= 0XFD;   //Make PF1 Low
        TIMER0->ICR |= (1<<0);     //Reset Timer0 flag
        while((TIMER1->RIS & 0x00000001) != 1){}   //wait until Timer1 times out
        GPIOF->DATA ^= (1<<2);     //Toggle clock
        TIMER1->ICR |= (1<<0);     //Reset Timer1 flag
    }
}

int main()
{
    GPIO_INIT();   // Initiate GPIO
    TIMER_INIT();  // Initiate Timers with Timer0= 1/2 Timer1
    while (1) {
        DATA(0XAB01,16); // 0xAB01 16 bit data need to be send serially 
    }
}

There is a problem in this code, which is both of the data and the clock have the same frequency, which means that Timer0 or Timer1 are disabled.

To make my problem more clear and easy to understand. I wrote two simple codes with a graph for each of them. Here is the first code: I am using While loop

int main()
{
    GPIO_INIT();  
    TIMER_INIT();   //Timer0= 1/2 Timer1
    while (1) {
        while((TIMER0->RIS & 0x00000001) != 1){}   //Wait for TIMER0 to time out
        GPIOF->DATA ^= (1<<1);   //Toggle PF1
        TIMER0->ICR |= (1<<0);   //Reset TIMER0 flag

        while((TIMER1->RIS & 0x00000001) != 1){}    //Wait for TIMER1 to time out
        GPIOF->DATA ^= (1<<2);    // Toggle PF2
        TIMER1->ICR |= (1<<0);    //Reset TIMER1 flag
    }
}

Here is the output I got: enter image description here

Here is the 2nd code: I am using If condition

int main()
{
    GPIO_INIT();
    TIMER_INIT();    //Timer0= 1/2 Timer1
    while (1) {
        if((TIMER0->RIS & 0x00000001) == 1) {    //If TIMER0 out timed out 
            GPIOF->DATA ^= (1<<1);    //Toggle PF1
            TIMER0->ICR |= (1<<0);   //Reset TIMER0 flag
        }

        if((TIMER1->RIS & 0x00000001) == 1) {   //If TIMER1 timed out
            GPIOF->DATA ^= (1<<2); //Toggle PF2
            TIMER1->ICR |= (1<<0); //Reset TIMER1 flag
        }
    }
}

Here is the output: enter image description here

Conclusion: When I used the if condition the two timers are working normally, but when I used While loop only one timer is working and the other timer is just using the same counts of the other.

\$\endgroup\$
  • 1
    \$\begingroup\$ Do you know C is a sequential language? Do you also know that while(x){} loops until x is not true? Do you also know what an if does? \$\endgroup\$ – Asmyldof Aug 9 '16 at 21:45
  • \$\begingroup\$ @Asmyldof: I wrote the code, so of course I know what I wrote. I wrote a comment beside the while loop saying "wait until timer is timed out" !!, and I mentioned that when I used the if condition in the 2nd case the timers works but the output of the code is not what I want. what is the point of your comment anyway !!! \$\endgroup\$ – Abdelrahman Elshafiey Aug 9 '16 at 21:53
  • \$\begingroup\$ Clearly if those three questions don't already answer at least half of your question, your response to it is at the least a little insolent. I'm out. \$\endgroup\$ – Asmyldof Aug 9 '16 at 23:09
  • \$\begingroup\$ @Asmyldof: The way you commented is an insult. I can't see what did you add by asking three primitive questions. Your comment could be valid if I was asking about what is the difference between the while loop and the if condition, but it is clear I am not. I am asking why in the case of while loop, one of the timers is disabled, and in case of if condition the two timers are working. You either didn't read the problem or you can't understand what I am trying to say. I didn't force you to help, it's up to you. Thanks anyway \$\endgroup\$ – Abdelrahman Elshafiey Aug 9 '16 at 23:20
  • \$\begingroup\$ @Asmyldof: One important point: when the MCU is busy in the while loop, the other timer should be running normally. Since it's a separate module. \$\endgroup\$ – Abdelrahman Elshafiey Aug 9 '16 at 23:23
2
\$\begingroup\$

Apperently your clock timer Timer0 is slower than data timer Timer1 so there nothing suprising in represented behaviour because your code skip every second event from Timer1 when you use while.

I think there enough one timer with max used frequency - is Timer1. More over there should be one timer because data and clock must be synchronous and this condition not guaranteed by code represented in your question.

int main()
{
    char even = (char)0x1;
    GPIO_INIT();  
    TIMER_INIT();   //Timer0= 1/2 Timer1
    while (1) {
        while((TIMER1->RIS & 0x00000001) != 1);    //Wait for TIMER1 to time out
        TIMER1->ICR |= (1<<0);             //Reset TIMER1 flag
        even ^= (char)0x1;
        if (even) GPIOF->DATA ^= (1<<1);   // Toggle PF1 [Clock]
        GPIOF->DATA ^= (1<<2);             // Toggle PF2 [Data]
    }
}

So your function DATA(long number, int iteration) will be:

void DATA(long number, int iteration) //number: data to be send serially
{ 
    long x=0;                           // iteration: number of bits to send
    char even = (char)0x1; 
    for(int y=0; y<iteration;) {
        while((TIMER1->RIS & 0x00000001) != 1){}   //wait until Timer1 times out
        TIMER1->ICR |= (1<<0);     //Reset Timer1 flag
        even ^= (char)0x1;
        GPIOF->DATA ^= (1<<2);     //Toggle clock
        if (even) continue;
        // data change every odd cycle
        x= number & (0x1<<y);      //Get each bit individually  
        if(x==(0X1<<y))            //If bit is 1
            GPIOF->DATA |= (1<<1); //Make PF1 High 
        else if(x==0X0) //If bit is 0
            GPIOF->DATA &= 0XFD;   //Make PF1 Low
        y++;
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.