Tomi made a simulation in ISIS. it is nice that it demonstrates the same behavior. I can recommend ISIS Proteus from Labview highly.
It simulates the hardware very accurate.
When i removed the setting of ICR1, it shown 0 as it is supposed to. Then i added back the settings you made :
Tccr1a = &B10000010
Tccr1b = &B00010010
Icr1 = 4096
Dummy = Icr1
Shift Dummy , Right , 2
Pwm1a = Dummy
Dummy = Icr1
and i also assigned icr1 to dummy.
Ok, next step was to show dummy instead of icr1 . Now : it shows the same value. This does mean that icr1 changes between the first and second time bin() was used.
this could be because the register was acceded(read) or for some other reason.
The fun thing is that when dec or hex was used, the same values were shown. That is also remarkable. So bin() in combination with a hardware register had to be a problem.
Ok, i then inspected the registers and i found something amazing.
the bin() function points to a word, or any other numeric variable base address which is &H86.
Then it adds 2 bytes for a word so the pointer becomes &H88
THen the bin() function will use code like : ld r24, -Z
the -z means, pre decrease pointer, then load data into register
thus &H88 becomes &H87 and loads the byte. then processes all bits, and then again used ld r24,-z
and this is done 2 times for a word.
what i see is that the wrong data is returned in r24 the first time. almost if the -z does not work because the data is loaded from &H89 !
at the screen shot you can see the state after the first loaded byte.
Z points to &H87 as expected.
So that means it pointed to &H88 before. (i checked and that was ok)
But r24 : it contains 4 which is not correct.
Then i realized that bin() read from MSB to LSB in order to get the proper bit order. But double byte (word) registers in normal AVR must be read LSB..MSB order.
So bin() is ok but not for all word IO registers.
This is from the datasheet :
The TCNT1, OCR1A/B, and ICR1 are 16-bit registers that can be accessed by the AVR CPU via the 8-bit data bus.
The 16-bit register must be byte accessed using two read or write operations. Each 16-bit timer has a single 8-bit
register for temporary storing of the high byte of the 16-bit access. The same temporary register is shared between
all 16-bit registers within each 16-bit timer. Accessing the low byte triggers the 16-bit read or write operation. When
the low byte of a 16-bit register is written by the CPU, the high byte stored in the temporary register, and the low
byte written are both copied into the 16-bit register in the same clock cycle. When the low byte of a 16-bit register is
read by the CPU, the high byte of the 16-bit register is copied into the temporary register in the same clock cycle as
the low byte is read.
Not all 16-bit accesses uses the temporary register for the high byte. Reading the OCR1A/B 16-bit registers does
not involve using the temporary register.
To do a 16-bit write, the high byte must be written before the low byte. For a 16-bit read, the low byte must be read
before the high byte.
The following code examples show how to access the 16-bit Timer Registers assuming that no interrupts updates
the temporary register. The same principle can be used directly for accessing the OCR1A/B and ICR1 Registers.
bascom takes care of using the proper order when reading/writing. but the bin() is an exception to that because it uses a pointer.
I could change it by loading the data into a register first. It does use more code however.
ok it took some time but mystery solved(the temp register value was returned by the chip) and i can conclude it was indeed a software problem.
↧