atmega2650 toggling OC1C (led on arduino mega) - timer

I am trying to toggle an LED with a 1024 prescaler, CTC mode 4.
The LED comes on after a second and stays on.
What am I doing wrong?
#include "Arduino.h"
void setup() {
//PORTB ^= (0 << PB7);
DDRB = (1 << PB7);
TCNT1 = 0;
OCR1C = 100;
TCCR1A = 0; // thought maybe arduino was setting other bits?
TCCR1B = 0; //
TCCR1A = (0 << COM1C1) | (1 << COM1C0) | (0 << WGM11) | (0 << WGM10);
TCCR1B = (0 << WGM13) | (1 << WGM12) | (1 << CS12) | (0 << CS11) | (1 << CS10);
}
void loop() {}
UPDATE
#include "Arduino.h"
void setup() {
//PORTB ^= (0 << PB7);
DDRB = (1 << PB7);
TCNT1 = 0;
TCCR1A = 0; //
TCCR1B = 0; //
OCR1A = 100; // OCR1A is the CTC mode 4 top
TCCR1A = (0 << COM1C1) | (1 << COM1C0) | (0 << WGM11) | (0 << WGM10);
TCCR1B = (0 << WGM13) | (1 << WGM12) | (1 << CS12) | (0 << CS11) | (1 << CS10);
}
void loop() {}
Set OCR1A after clearing the TCCR1A and TCCR1B
As Mike said OCR1A is top for mode 4

Related

register manipulation avr microcontroller

I'm just starting out. Have a little patience for my questions.
I came across a listing of a program where the following statement appears:
DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2));
My guess:
considering that at startup the microcontroller has by default the DDRB bits all set to 0, I get:
DDRB & = ~ ((1 << 0) | (1 << 0) | (1 << 0)); ===>> DDRB & = ~ ((1) | (1) | (1));
which is different from the author's cooment. Where am I wrong?
2 # question: recital
volatile uint8_t portbhistory = 0xFF;
changedbits = PINB ^ portbhistory;
the second statement is not equal to:
changedbits = ~ PINB;
what changes? thanks to those who want to answer me.
No it is DDRB & = ~ ((1 << 0) | (1 << 1) | (1 << 2));
DDB0, DDB1, DDB2 are bit numbers defined in header file.
#define DDB0 0
#define DDB1 1
/* ... actual values may be different */
Statement:
DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2));
zeroes DDB0, DDB1 & DDB2 bits.
DDRB |= (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
sets DDB0, DDB1 & DDB2 bits.
DDRB ^= (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
toggles DDB0, DDB1 & DDB2 bits (sets their value to the opposite one).

Atmega2560 PWM on PB7

I am trying to get PWM output from PB7 pin with timer0 on Atmega2560 with no luck. It should generate tone for the connected repro.My PWM settings are:
DDRB = 0b11100000;
PORTB = 0b00000000;
OCR0A = 0x04;
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (0 << CS01) | (0 << CS00);
and then I have this function, which should generate the sound:
void SoundOutput(unsigned int uintTone)
{
if (uintTone != 0)
{
LED_2(1);
OCR0A = uintTone;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);
}
else
{
TCCR0B &= ~((1 << CS02) | (1 << CS01) | (1 << CS00));
}
}
but nothing happens when i call it with tone parameter. Can you please help me?
Based on your comments, you are using ~12MHz clock as the input to your timer, and from your code, you are using 8 bit timer 0 in CTC mode with OCR0A as your top. You have OC0A set to toggle on a compare match.
According to the 2560 datasheet, the frequency of your timer is given by:
F_CLK/(2*(1 + OCR0A)) | F_CLK ~= 12MHz
This is an 8 bit timer, so that means that your minimum frequency that your PWM can generate is given by:
12e6/(2*(1 + 255)) ~= 20KHz
You simply aren't going to be able to generate an audible tone with that configuration unless you slow down the clock you are using for your timer or use a timer that can count higher.
1) Use a 16 bit counter (i.e. timer1). That will give you a min frequency of ~90Hz and a max frequency of ~6MHz, which should give you plenty of range to generate tones:
/* WGM BITS = 0100: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 111: External clock source on rising edge */
TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << WGM01) | (0 << WGM00);
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS02) | (1 << CS01) | (1 << CS00);
2) Use the internal clock source as the timer clock instead of an external source. Unless you changed fuse bits or you are changing it in the code somewhere, the clock will be 1MHz. Prescaling the clock by 8 gives you a frequency range of ~250Hz - ~60KHz.
/* WGM BITS = 010: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 010: Prescale the internal clock by 8 */
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (0 << CS00);

C - atmega328p - I don't understand what is wrong

i do not unterstand why my code isnt working(doISR). What its supposed to do:
-there is a running light(6 LEDs) and 3 Buttons. I need to press the button at the right time(Button 1, if LED 1 or 2 is on....etc). if its correct: increase the speed, if not: reset.
i bet its a blunder, but i dont get it :)
void wait(void) {
while (!(TIFR1 & (1 << OCF1A))) // wait
;
TIFR1 |= (1 << OCF1A); // delete Interrupt flag
}
volatile bool ISRhasHappend = false;
ISR(PCINT0_vect) {
ISRhasHappend = true;
}
int main(void) {
OCR1A = 3125 - 1; //2 seconds
TCCR1B |= (1 << WGM12); //turn on CTC mode
TCCR1B |= (1 << CS12) | (1 << CS10); //Prescalemode 101 -> 1024 Takt
DDRB = (1 << PCINT5);
DDRC = 0x3f;
PCICR = 0x3f; //Pin Change Interrupt Control Register
PCMSK0 = (1 << PCINT0) | (1 << PCINT2) | (1 << PCINT4);
sei();
doRunningLight();
if (ISRhasHappend == true) {
doISR();
}
}
void doISR() {
//while timee >0
for(int x=3125;x>0;x=x-250){
//if LEDs 0+1 on, and button0 pressed ...etc
if ((PORTC & (0b00000011)) && (PINB & (1 << PINB0)) || (PORTC &
(0b00001100)) && (PINB & (1 << PINB2)) || (PORTC & (0b00110000)) &&
(PINB & (1 << PINB4))) {
//All led lights up
PORTC |= 0x3f;
wait();
//reduce timer if catched the light
OCR1A = x;
}
else {
//turn signal
for (int y = 1; y < 5; y++) {
PORTB ^= (1 << PCINT5);
wait();
}
//back to 3124 if failed
OCR1A = 3125 - 1;
}
}
ISRhasHappend = false;
}
void doRunningLight(){
while(1) {
for (int i = 0; i<6; i++){
PORTC |= (1<<i);
wait();
PORTC &= ~(1<<i);
}
}
}
The function doRunningLight() never returns, so the code that you wrote after it to check ISRhasHappend and call doIsr will never run. You will need to think of a different way to handle your events, probably without using blocking delay loops.
I would also question whether you actually need a pin-change interrupt. Button presses are slow enough that your microcontroller should be able to detect them by reading the pin in the main loop.

16-bit Timer PWM LED Dimmer

I am new to AVR C Programming, I am testing a simple PWM using 16-bit timer on Atmega328p Counter/Timers which is suppose to act as a dimmer to an LED.
My Code:
#define F_CPU 16000000UL
void initTimer();
int x = 1;
int n = 1000;
int main(void)
{
initTimer();
DDRB |= (1 << PB1)| (1 << PB2);
while(1)
{
x++;
if(x > 65) {
x = 1;
}
}
}
void initTimer() {
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
// used for TOP, makes for 50 Hz PWM
ICR1 = 40000;
OCR1A = n * x;
}
ISR(TIMER1_OVF_vect)
{
OCR1A = n * x;
}
Problem is that it doesn't display the dimming effect, the brightness of the LED stays constant as to whatever value I set for OCR1A (PB1) output pin initially, its suppose to change value as the interrupt happen but its just not doing this, this is suppose to be simple test what am I doing wrong?
Update:
As advice I enable the interrupts using the TIMSK1 register and SEI(), however still the same issue the LED brightness stays constant as to whatever the original value of OCR1A that was specified in the initTimer().
int main(void)
{
initTimer();
DDRB |= (1 << PB1)| (1 << PB2);
while(1)
{
x++;
if(x > 65) {
x = 1;
}
}
}
void initTimer() {
ICR1 = 40000;
OCR1A = n * x;
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TIMSK1 |= (1 << ICIE1);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
sei();
}
ISR (TIMER1_COMPA_vect)
{
OCR1A = n * x;
}
Although I tried an alternative approach and that gives me the dimming affect:
int main(void)
{
initTimer();
DDRB |= (1 << PB1)| (1 << PB2);
while(1)
{
_delay_ms(20);
OCR1A = n * 4;
_delay_ms(20);
OCR1A = n * 8;
_delay_ms(20);
OCR1A = n * 15;
_delay_ms(20);
OCR1A = n * 25;
_delay_ms(20);
OCR1A = n * 1;
}
}
void initTimer() {
ICR1 = 40000;
OCR1A = n * x;
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
}
So it seems the problem is with the interrupts since PWM affect works but its just not working with the interrupt handler.
The first thing that jumps out at me is x and n should be volatile. You also should enable the interrupt in TIMSK0 register. Also enable interrupts by calling sei.
If I were you, I'd start with some know good sample code. The page I mentioned has a example that fires an interrupt every 4ms. Take that code and toggle the led on and off.
Another problem is you are changing x without regard to whether or not the isr was called. So in effect you will get a random x each time in the isr. This code is simple enough it might get stuck in a simple pattern. Instead move the setting of x to your isr.
Here is a good intro to avr timers: https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
ICR1 = 40000;
OCR1A = n * x;
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
This is wrong, you need to configure TCCR1A and TCCR1B before initializing ICR1 and OCR1A. See this answer for more details.

Set OCR register in interrupt?

On ATmega 32u4 I've got two timers. One is for measuring ticks between interrupts and second which counts 1/60 of number of ticks. I'm not sure I'm allowed what I'm doing and if that is correct. If you could tell me what is wrong I would greatfull.
void setup(){
EIMSK |= (1 << INT2); //INT2 enable
EICRA |= (1 << ISC21) | (1 << ISC20); //INT2 RISING EDGE
DDRD &= ~(1 << PD2); //PD0 (INT0)(3) as input
PORTD &= ~(1 << PD2); //PD0 pulldown
TCCR1B |= (1 << CS11); //prescaler 8
//TIMER3 - 1/60
TCCR3A |= (1 << WGM32); //CTC Mode
TCCR3B |= (1 << CS31); //prescaler 8
TIMSK3 |= (1 << OCIE3A); //compate interrupt enable
sei();
}
ISR(INT2_vect) {
TCNT3 = 0;
OCR3A = TCNT1 / 60;
TCNT1 = 0;
degree = 30;
}
ISR(TIMER3_COMPA_vect) {
Color * currentColor = &bColor;
if (degree == 0)
degree = 59;
else degree--;
if (degree == time.second)
currentColor = &sColor;
else if (degree == time.minute)
currentColor = &mColor;
else if (degree % 5 == 0 && degree / 5 == time.hour)
currentColor = &hColor;
//set pwm
RedReg = currentColor->Red;
GreenReg = currentColor->Green;
BlueReg = currentColor->Blue;
}

Resources