Write into TMR0 PIC18F26K22 - Page 1
Forum section: electronics / general

author: firstcolle
author_rank: Regular Contributor
timestamp: February 28, 2017, 08:50:28 pm
content: i'm getting a strange(??) problem.. with mplab X 3.50 and XC8 1.41..i'm working with timer 0 in 16bit mode and all works fine if i load the preload time into TMR0 direct like thisTMR0 = 24125;but if i try to put the value into a variable (unsigned int) and then use the variable to load the TMR0 only the low byte of TMR0 is loaded...example:unsigned int variable = 24125;TMR0 = variable;why i can't do this???many thanks

author: Buriedcode
author_rank: Super Contributor
timestamp: February 28, 2017, 11:38:21 pm
content: Interesting question, I always assumed that the compiler handles the writes to 16-bit registers, which it appears to do when using constants. But seems to fail with variables.I would look at the .lst file generated by the compiler for the assembly listing - its got a ton of extra crap in there, but at least then you can see what exactly is going on. Maybe a test program that first writes a constant to TMR0, lets it run, then writes a 16-bit variable/int to TMR0, and compared the generated assembly.As a work around I suppose you could just write to them manually, to TMR0H then TMR0L separately. Shouldn't have to, but it will at least provide another test.Code:unsigned int variable = 24125;TMR0H = (variable >> 8); // there are better ways to grab the high byte of an unsigned int, but this will do for nowTMR0L = (variable & 0xFF); //no need to AND it as TMR0L is 8-bit anyway.

author: Ian.M
author_rank: Super Contributor
timestamp: March 01, 2017, 01:06:59 am
content: Don't use the TMR0 SFR directly. Instead use:Code:WRITETIMER0(variable);The WRITETIMERn() and READTIMERn() macros defined in pic18.h guarantee the correct access order for 16 bit timers even if a new release changes the compiler's optimised operation ordering for 16 bit integers. See appendix A of the user guide.

author: cv007
author_rank: Frequent Contributor
timestamp: March 01, 2017, 01:12:59 am
content: If you look at the .lst file, you will see that when assigning a constant, the timer is loaded high byte then low byte which is the correct order. When using a variable, the timer is loaded low byte first, which is incorrect.Read the XC8 Compiler Manual section 5.3.6.2 - meant just for you.It appears you can also use the xc8 built in WRITETIMER0() macro to take care of writing in the correct order.(I'm too late, I see Ian wrote that while I was posting)There may have been a discussion on this sometime back on this forum.

author: Ian.M
author_rank: Super Contributor
timestamp: March 01, 2017, 01:18:39 am
content: Quote from: cv007 on March 01, 2017, 01:12:59 amYes, 12 months back.https://www.eevblog.com/forum/microcontrollers/how-to-combine-tmr0h-tmr0l-into-a-16-bit-variable-using-xc8/

author: firstcolle
author_rank: Regular Contributor
timestamp: March 01, 2017, 07:42:36 am
content: Thanks guys!!! (and sorry Ian..I did a search on the forum but could not find the old post...)i found out also that write 2 times the variable into TMR0 SFR works... but using the macro is certainly the best solution..

author: JPortici
author_rank: Super Contributor
timestamp: March 01, 2017, 07:49:31 am
content: AFAIR TMR0 is actually defined asCode:unsigned char TMR0Lso writing an int to TMR0 wouldn't do anything different. Will check in the pic include file later, if i happen to open a project with the 26k22 (probably, i use it almost on a daily basis)EDIT: It was not. unsigned short. Strange because i remember the compiled code to be different, as if i write an int to a char.writing the two variables as buriedcode did (note the order! section 11.3 of the datasheet) is still optimized as two MOVFF for local variables in free mode.