This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hey everyone, I am trying to learn timers. I saw an example code on the internet and checked it against datasheet and values choosen for configuration seems fine.
Expected result: 1 second red led on, 1 second led off
Actual result: 0.5 sec red led on, 0.5 sec led off
Here is the code I build and load to TM4C. Code is developed on Keil Uvision. From Manage Runtime Environment, choose CMSIS->Core and Device->Startup software components.
#include "TM4C123.h" // Device header void delay_Microsecond(uint32_t time); int main() { SYSCTL->RCGCGPIO |= 0x20; // Unlock clock for Port F GPIOF->DIR = 0x02; // Set PF1(RED) LED pin as output GPIOF->DEN = 0x02; // Digital Enable PF1(RED) LED while(1) { delay_Microsecond(1000000); // Wait 1 sec GPIOF->DATA ^= 0x02; // Toggle output value of PF1(RED LED) } } void delay_Microsecond(uint32_t time) { SYSCTL->RCGCTIMER |= 0x02; // Enable and provide a clock to TIMER1 TIMER1->CTL = 0x00; // Timer 1-A is disabled. TIMER1->CFG = 0x04; // Select 16 bit timer TIMER1->TAMR = 0x2; // Set periodic timer mode TIMER1->TAILR = 16 - 1; // 0 to 15 = 16 ticks for 1 microsecond TIMER1->ICR = 0x1; // Clear interrupts from TIMER1(Unnecessary here?) TIMER1->CTL = 0x01; // Timer 1-A enabled for(int i = 0;i < time; i++){ while((TIMER1->RIS & 0x1) == 0x00); TIMER1->ICR = 0x1; // Clear Timer 1-A interrupt every 16 ticks } }
May I complement you on the, "Very nice job" you did w/your posting? Clearly described - sufficiently detailed - and (even) reveals "format-correct" code. (keeps the forum Gods (somewhat) happy ... although (even) they - are "UNABLE TO **LIKE** your post!') SO wonderfully poetic...
Mehmet Kose said:I saw an example code on the internet and checked it against datasheet
Not quite awake staff & I (it is 05:55 in Chicago - on Saturday) love the fact that you made the (extra) time & effort to review the MCU Manual - likely probing the key Timer Registers. And of course - both "you and my small tech group" - always & only - "believe every word noted on the internet." (ok - at least every (other) word...)
While your code method "DRM" is generally NOT deemed effective (by hallowed vendor - and few "opinionated" outsiders (never moi)) you have, "Commented the heck out of it" - making DRM (almost) bearable! Yet (another) "Point in your favor!" (there were/are MANY!)
Two areas "jump out" after quick examination of your well organized & presented code:
The fact that your code runs - toggling the Led at "twice" your desired rate - confirms that (even) DRM code may (sometimes) ... (almost) succeed! Employing the "tips herein" - or via other means - you must search out the reason for your (apparent) "Doubled MCU's Timer "Clock Rate." Again - you are 95%+ "home" - NICE JOB...
For the purpose of lean execution, I tried to stop and disable the clock at the end of delay function below. Is this best practice to "free" a timer once we are done with it?
void delay_millisecond(uint32_t time) { ... // Original function body is not copied here to prevent clutter TIMER1->CTL = 0x00; // Timer 1-A is disabled. SYSCTL->RCGCTIMER &= ~0x02; // Disable clock to TIMER1 }
My mistake was assuming system core clock would be 16 Mhz by default since I have not written any code to modify it.Thanks to Danny F. and cb1_mobile, I investigated the issue more. Here are the results.
When I added startup software component through Manage Run-time Environment->Device->Startup in Keil UVision, it added "system_TM4C123.c" file into the project under Project->Target->Device(in Project Explorer window). This file has clock configuration definitions and SystemInit() function in it. Here are some of definitions;
#define CLOCK_SETUP 1 // This causes to clock configuration at initialization with SystemInit() function #define CFG_RCC_SYSDIV 4 // This causes 50 Mhz system core clock speed(Check TM4C123GH6PM Datasheet) #define CFG_RCC_USESYSDIV 1 // Enables System Clock Divider(The value "4" above) #define CFG_RCC_PWRDN 0 // Do NOT disable PLL #define CFG_RCC_BYPASS 0 // Do NOT bypass PLL #define PLL_CLK (400000000UL) // PLL Clock is 400 Mhz
As we can see PLL is not disabled/bypassed, clock setup is enabled and SYSDIV is choosen to be 4. According to the values above and information in the datasheet(Page 223- "Using the SYSDIV and SYSDIV2 Fields"), expected system clock is 400 MHz / 2 /4 = 50 MHz. Division by 2 is predivision before divisor 4 is applied. To prevent clock configuration at start, I simply set CLOCK_SETUP to 0;
#define CLOCK_SETUP 0 // Disable clock configuration within SystemInit() function
Since there was no external clock configurations, MCU had 16 MHz system core clock speed happily after that.
Note: I marked this post as "resolving one". Do I have to mark other helper posts leading to the solution?
Good for you - as you have noted - my (first response) "honed in upon a "difference" between original program's clock setting and your own."
Poster Danny make a good point as to the, "Over-involvement of Interrupts" - brought on my your use of the (far too small value) of 16. For your 16 bit timer - that may be increased to 16,000 - or even 64,000 - should you be willing to "Tweak your math." (16 bit maxes out around 65.5K) Raising that value will indeed (drastically) reduce your "loop overhead."
To the "This Resolved" Issue - proper rewarding should target your Responders - in the case here it is believed that poster Danny & I should both be so awarded...
You may note that "FEW here" employ Keil AND CMSIS - and their combined operation - "behind the scenes" - HIDES key program info from your "Helper Crüe."