As mentioned in a previous thread I came across an apparent discrepancy in the ATmega32 manual that I thought might interest people. I've been experimenting with programming the fast PWM capabilities of Timer/Counter 0 and found that after I'd initialised the control registers to disconnect the timer and give normal operation of the digital I/O on port B the port wouldn't function. By a process of elimination I discovered the problem lay in TCCR0B. According to the manual the initial values of all bits in this register after a reset is zero so I expected that writing it with zeros after using the timer would set it back to it's default state. However after using Serial.print() to examine the initial state I found that the clock select bits CS00 and CS01 were, in fact set to ones. After writing these to ones the normal I/O function worked properly.
Thanks for the quick reply and link. That explains several of the things I've been wondering about.
Since init() sets those bits it's presumably to overcome the problem I discovered which raises the question of why Atmel designed the hardware like that.
fenman:
Since init() sets those bits it's presumably to overcome the problem I discovered which raises the question of why Atmel designed the hardware like that.
Nope.
They are being set to 1 because Timer0 is used for millis() so the init function is enabling the timer module and getting it ready for that purpose.
If you compile this program:
int main (void) {
Serial.begin(9600);
Serial.print(TCCR0,BIN);
while(1);
}
You will find that it is set to 0 as per the datasheet.
EDIT:
Do you really mean atmega32? According to its datasheet it has a TCCR0, but no TCCR0B (http://www.atmel.com/Images/doc2503.pdf). Are you sure you don't mean the Atmega328?
If you mean the ATMega328, then you need to set TCCR0A=0 in order to restore port functionality along with TCCR0B=0 to stop the timer.
I noticed that using the PWM function affected the Arduino delay() function so guessed this timer was being used for that.
However since setting those two CS bits to zero appears to prevent port B from operating in normal digital I/O mode is this not the situation that would exist after a power-up/reset were it not that they are set in init()?
Edit: I'm using the Leonardo board with the ATmega32U4. This has TCCR0A and TCCR0B. I already set TCCR0A to all zeros and this should have restored port functionality except that as above I found that it didn't unless the two ls bits of TCCR0B are set to 1.
The hardware automatically zeros the memory on reset, the registers are at the beginning of the SRAM addressing scheme and get zeroed too.
Its good as it leaves the controller in a known state. Imagine your throttle speed in your car resetting to a random high speed. If the programmers forget to default every variable the device could potentially cause harm.
The init function does quite a lot. Browse to your arduino setup and find the core:
arduino-1.0.5\hardware\arduino\cores\arduino
or the beta arduino-1.5.2\hardware\arduino\avr\cores\arduino
I can see the sense in that. It's just that, as I mentioned in my reply to Tom above, the datasheet implies that setting all the bits of the control register TCCR0A to zero should restore normal port functionality irrespective of the settings in TCCR0B but I found that this isn't the case if these clock select bits are set to zero. That's the discrepancy I've been alluding to.
Specifically, from the simplified schematic, setting the two Compare Output Mode bits in TCCR0A to zero should disconnect the timer output from the port and restore normal operation.
Could you post the code you are using that shows this strange problem. Certainly with any of the other atmegas or attinys I've used this has never happened and the 32u4 should be no different. Either you have a faulty chip or your code is wrong.
I've deleted that code now but I tried both a direct write to port B : PORTB = 0x80/PORTB = 0x00; and digitalWrite(11, HIGH)/digitalWrite(11, LOW); Within loop() I was writing the pin alternately high then low so that I could check the signal with a 'scope on the pin.
in setup() I also tried writing direct to the data direction register : DDBR = 0xFF; and using pinMode(11, OUTPUT);
Nothing worked with the CS bits zero and all worked with CS1 and CS0 set to 1.
EDIT:
I think I've just realised what the problem was. I was using delay(); in the loop and turning off the clock to timer 0 would have stopped that working so my program loop would also have stopped.
Do I feel a pr*t!!