I am using Timer 1 in Fast PWM mode ---> i update the special function registers associated with the timer 1 HW peripheral for achieving the above PWM mode function.
But, i am unable to update the upper byte of OCR1A register...namely OCR1AH.
I not able to do this with C programming..
If anyone can provide me a piece of C code that will successfully update the FULL 16bit OCR1A register...
or
i can try a short assembly code snippet within the setup() function as well to update the OCR1A register, but - how do i invoke the assembler to compile the snippet within the bigger c code based setup() function?
will assembly code successfully update the OCR1A register..
The compiler will NOT take care of atomic or not! The compiler knows nothing about the interrupts, only where to place the code for it in order for the micro to call it when there is an interrupt. That's why you need to make globals used in an interrupt volatile. Because as far as the compiler is concerned, interrupt functions are never called, they are outside the program flow the compiler sees. But even then, YOU have to take care of the atomic part
I am using Timer 1 in Fast PWM mode ---> i update the special function registers associated with the timer 1 HW peripheral for achieving the above PWM mode function.
But, i am unable to update the upper byte of OCR1A register...namely OCR1AH.
I not able to do this with C programming..
If anyone can provide me a piece of C code that will successfully update the FULL 16bit OCR1A register...
Simple as
noInterrupts() ;
OCR1A = 0x5555 ;
interrupts();
If outside an ISR. If no ISR is accessing any timer1 16 bit registers, there is no need for the
critical section at all.
Septillion - The atomic write to OCR1A register has nothing to do with the ISR code - my ISR code never updates the special function registers..by the way
I am able to get the PWM on the pin . I also tested the OCR1A register with multiple values to change the pwm duty cycle...
what i discovered was the Lower byte OCR1AL values get updated and the PWM varies from 0 to 50 %
the OCR1AH value always remains zero and i cannot get PWM duty cycles above 50% to 100 %
so the problem is OCR1AH --- upper byte of OCR1A register never updates...
15.3 Accessing 16-bit Registers
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 tempo- rary 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. Note that when using “C”, the compiler handles the 16-bit access.
That is NOT an excuse... It IS a good reason to read How to use the forum though.... It also tells you we're not Snippets R Us.
And after some testing, OCR1A only acts 16-bit if TCCR1x set to a 16-bit mode. And guess what. that's the part not posted...
As for the atomic, your code may not, other code may. And you may in the future. Aka, it's safety first thing. Only wanted to make clear the compiler does NOT take that into account for you.
Thanks All for ur valuable suggestions. let us continue...the dialogue
Septillion, Scroll down thru the code. my code has lot of empty lines in between to keep the reading easy..
The TCCR1X register updates are performed and the value is there...of course in my first post the absence of code tags wud have obscured it... now with the code tags it is there...
do any of u have tried timer 1 in 16 bit mode and the fast PWM works...for above 50% duty cycle.
does it work under that condition? i mean the OCR1A register gets updated with full 16 bit value? if so pls share that code...
if not, can any of u kindly use my piece of code on ur Arduino kits that have the Atmega328p Controller and check if the code works in the Fast PWM mode, i mean even with the simple OCR1A = value; statement
the registers settings in my code shud get the PWM out on the D9 pin of the micro. comment out the TIMSK1 register code line as the ISR is not needed for the pure PWM testing...
u will surely get upto 50% PWM , but if OCR1A is fully updated then u shud be able to obtain above 50% duty cycle as well....
all - in my code, u can also find the commented out code that does the simple OCR1A = decimal value statement.
i also tried that and it still doesnt work. (some of u suggested that).
strange thing the lower byte gets updated but not the upper.
John wasser- i have read the datasheet note...as well and the caution. But what is that piece of code that will work for updating the OCR1A register?
bbenji74:
Septillion, Scroll down thru the code. my code has lot of empty lines in between to keep the reading easy..
You mean to absolutely mess up ANY readability... You're a person who starts every sentence on a new page, arn't you? Or better, leave blank pages in between...
Because of that an the messed up indentation I indeed missed it.
BUT, I have you the answer The timer has to be set up for >8-bit BEFORE you can access OCR1A as 16-bit Now you try the other way around...
The code reference from the datasheet for the ATmega328/P - Atmel 42735 8 bit AVR Microcontroller
Page 152:
"
16-bit Access
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. Note that when using C, the compiler handles the 16-bit access.
Assembly Code Example
(1)
...
; Set TCNT1 to 0x01FF
ldi r17,0x01
ldi r16,0xFF
out TCNT1H,r17
out TCNT1L,r16
; Read TCNT1 into r17:r16
in r16,TCNT1L
in r17,TCNT1H
...
The assembly code example returns the TCNT1 value in the r17:r16 register pair.
C Code Example
(1)
unsigned int i;
...
/* Set TCNT1 to 0x01FF */
TCNT1 = 0x1FF;
/* Read TCNT1 into i */
i = TCNT1;
...
Note:
The example code assumes that the part specific header file is included. For I/O Registers located
in extended I/O map, “IN”, “OUT”, “SBIS”, “SBIC”, “CBI”, and “SBI” instructions must be replaced
with instructions that allow access to extended I/O. Typically “LDS” and “STS” combined with
“SBRS”, “SBRC”, “SBR”, and “CBR”. Atomic Read
It is important to notice that accessing 16-bit registers are atomic operations. If an interrupt occurs
between the two instructions accessing the 16-bit register, and the interrupt code updates the temporary
register by accessing the same or any other of the 16-bit Timer Registers, then the result of the access
outside the interrupt will be corrupted. Therefore, when both the main code and the interrupt code update
the temporary register, the main code must disable the interrupts during the 16-bit access.
The following code examples show how to perform an atomic read of the TCNT1 Register contents. The
OCR1A/B or ICR1 Registers can be ready by using the same principle.
"
bbenji74:
John wasser- i have read the datasheet note...as well and the caution. But what is that piece of code that will work for updating the OCR1A register?
I just moved the OCR1A register update code in my piece of code, as the last update of the timer 1 special function registers, before the enable interrupt command and Bingo it worked....