Timer on atmega328p - c

So we had a task in school that every 10ms a variable (millisekunden)
schould increase by 10. We were using the CTC Mode, i set the OCR0A to 157, the
prescaler was 1024. The variable (millisekunden) increases every 10ms for 10, and
when it reaches 1000 , we schould print it out, and repeat that every 1000.
I always get an error : avrdude: verification error, first mismatch at byte 0x0000
0x00 != 0x0c
avrdude: verification error; content mismatch
Can anyone check out my code if it is even correct programmed? Im using atmega328p
it has 16MHz. So i calculated 1/ 16 MHz * 1024(prescaler) * OCRA(157) and we get 10milli
seconds.
#include "Arduino.h"
unsigned long int t_ref;
volatile unsigned long int millisekunden; // milli seconds timer
unsigned long int last_msg;
char buffer[64];
unsigned int c;
void setup() {
// Timer 0
TCCR0A |= (1 << WGM01); // CTC Modus
TCCR0B |= (1 << CS02) | (1 << CS00); // Prescaler 1024
OCR0A = 155;
// Compare Interrupt
TIMSK0 |= (1 << OCIE0A);
Serial.begin(9600);
}
void loop() {
if (millisekunden - last_msg >= 1000) {
sprintf(buffer, "t=[%lu] PINB=[%2.2x]", millisekunden,PINB);
Serial.println(buffer);
last_msg = millisekunden;
}
}
// Timer-Interrupt-Routine
ISR(TIMER0_COMPA_vect) {
millisekunden = millisekunden + 10;
}
datasheet from µC : https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

Related

Controlling Timer0 in ATmega328p

I'm trying to create a blocking delay for the ATmega328p for my arduino uno R3. but I'm running into problems with my function.
I am not sure if it has something to do with my clock source. I set it as 8 MHz at the top of my script, but the problem persists.
#define F_CPU 8000000UL
Here's a snip of my delay function, it's configured for a 10 ms delay at 8 MHz and uses a delayTime counter to create a longer delay
/*
* Function to instantiate timer operations
*/
void makeDelay(int delayTime){
// Call the timer for delayTime successively
// resulting in delay of (configured delay) * timerDelay
while(delayTime > 0){
/* Set the TCNT reg for 10ms # 8 MHz */
TCNT0 = 0xB2;
// Define the mode and prescaler values
TCCR0A = 0x00; // Normal mode
TCCR0B = 0x05; // prescaler = 1024
// loop until overflow
while( (TIFR0 & (1 << TOV0) == 0) );
// Stop the timer
TCCR0B = 0;
// clear the overflow
TIFR0 = 0x01;
// decrement the counter
delayTime--;
}
}
Any advice would be appreciated.
In your program this waiting condition is wrong:
(TIFR0 & (1 << TOV0) == 0)
Operator == has higher precedence than &. (1 << TOV0) == 0 is evaluated first and it is always false. Thus TIFR0 & 0 is always false too.
Rewrite the condition as
((TIFR0 & (1 << TOV0)) == 0)
or
((TIFR0 & _BV(TOV0)) == 0)
You can use following formula to calculate TCCNT0 register value for milliseconds:
Nticks = 256 - ms*F_CPU/1000/prescaler
As Timer0 is used by Arduino runtime library, you should disable it at first.
Entire sketch may be like this:
#define MS2TICKS(ms) (256 - (ms)*(F_CPU/1000)/1024)
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
TCCR0B = 0; // Stop timer
TIMSK0 = 0; // Disable timer interrupts
TCCR0A = 0; // Normal mode
TIFR0 = ~0; // Clear all interrupt flags
}
void my_delay()
{
TCNT0 = MS2TICKS(10);
TCCR0B = 0x05; // Enable timer with prescaler 1024
while ((TIFR0 & _BV(TOV0)) == 0);
TCCR0B = 0; // Stop Timer0
TIFR0 = _BV(TOV0); // Clear overflow flag
}
void loop()
{
digitalWrite(LED_BUILTIN, HIGH);
my_delay();
digitalWrite(LED_BUILTIN, LOW);
my_delay();
}
It generates 10 ms pulses with 10 ms pauses on LED output.

Creating a 10 second delay using ISR in TIMER1 of atmega328p

I'm trying to create a 10 second delay using TIMER1(16 bit) in atmega328p, I don't know if the delay has been created or not because it takes longer duration than 10 seconds and expected output( which is to create pwm waves) is not obtained. Here I have created a 1second delay and looped it 10 times, TIMER0 is used for creating pwm waves.
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "interrupt.h"
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
struct {
volatile unsigned int BIT: 1;
}
FLAG_TIMER;
void timer_configuration() //16 bit timer
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 0xC2F8;
TCCR1B |= ((1 << CS10) | (1 << CS12));
TCCR1B &= ~(1 << CS11); //101
sei(); // Global interrupt
}
void timer_on()
{
TIMSK1 |= (1 << TOIE1);
}
void pwm_configuration() //TIMER0 - 8 bit
{
TCCR0A |= ((1<<WGM00) | (1<<WGM01)); //setting it to fast PWM mode
TCCR0A |= (1<<COM0A1);
TCCR0A &= ~(1<<COM0A0);
TCNT0 = 0x00;
TCCR0B |= ((1<<CS00) | (1<<CS02)); //Prescaler setting 1024
TCCR0B &= ~(1<<CS01);
sei();
}
ISR(TIMER1_OVF_vect)
{
static unsigned int counter;
counter++;
if(counter >= 10)
{
FLAG_TIMER.BIT=1;
counter = 0;
TCNT1 = 0xC2F8;
TIMSK &= ~(1<< TOIE1);
}
else
{
FLAG_TIMER.BIT=0;
}
}
int main(void)
{
SET_BIT(DDRD,PD6); //CRO
timer_configuration();
pwm_configuration();
while(1)
{
timer_on();
if(FLAG_TIMER.BIT == 1)
{
OCR0A = 128; //50% dutycycle
}
}
You set the counter to 49912 on initialisation and increment your count when it overflows, but it will then start from 0, so if 15624 counts = 1 second, then your counter will increment to 10 after 15624 + 9 x 216 counts or about 38.75 seconds.
Move the TCNT1 = 0xC2F8; line in the ISR:
ISR(TIMER1_OVF_vect)
{
static unsigned int counter;
TCNT1 = 0xC2F8;
counter++;
if(counter >= 10)
{
FLAG_TIMER.BIT=1;
counter = 0;
TIMSK &= ~(1<< TOIE1);
}
else
{
FLAG_TIMER.BIT=0;
}
}
I am not familiar with ATmega, but I cannot believe that is an appropriate way to use the timer. Normally you'd up-count to a compare value with auto reset to zero, or down-count from an auto reload value to zero and let the hardware reload the counter.

blinking a led using timer 1 overflow interrupt in atmega328p

I'm trying to blink a led using ISR for 3seconds, here atmega328p is used. I'm trying to create a 1second delay in isr using TIMER1(16 BIT) and then loop that for 3seconds. LED is connected to PD7, I don't know why it is not blinking, can anyone point out the mistake. I'm using simulIDE, here is the circuit,timer_circuit
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 0xC2F8; // decimal value is 49912
TCCR1B |= ((1 << CS10) | (1 << CS12));
TCCR1B &= ~(1 << CS11); //1024 prescaler
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
TIMSK1 |= TOIE1;
if(count>=3)
{
SET_BIT(PORTD,PD7);
count=0;
}
}
;
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
}
This code never turn off the LED ... once the bit is set your code never clear it ... try to toggle the bit instead of set it
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
...
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
TCNT1 = 0xC2F8; // reset counter
}
update
use volatile access modifier before count variable to tell the compiler that you will Chang it from ISR to make sure that count variable will not delete in optimization
when you set TCCR1B you have to set other bits to zero to operate in normal mode
Recalculate value TCNT1 for 8 MHz which is internal default frequency
full code
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
volatile unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 64754; // over flow after 1 sec calculated at 8 MHZ
TCCR1B = ((1 << CS10) | (1 << CS12)); //1024 prescaler
TIMSK1 |= 1<<TOIE1; // Enable timer1 overflow interrupt
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
}
}
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
TCNT1 = 64754; // reset to over flow after 1 sec calculated at 8 MHZ
}

Setting a flag does not work in my timer Interrupt (while the Interrupt is working)

I used to write my codes in ICCAVR and I had no problem there, but not for some reason I should migrate to AtmelStudio.
in the following code, the LED is flashing in the interrupt, but when I only set a flag in the interrupt and want to flash the LED in polling (using the flag) it wouldn't work:
#include<avr/io.h>
#include<avr/interrupt.h>
#define LED PA1
ISR (TIMER1_OVF_vect) // Timer1 ISR
{
//PORTA ^= (1 << LED);
TCNT1 = 63974; // for 1 sec at 16 MHz
PORTA ^= (1 << LED);
}
int main()
{
DDRA = (0x01 << LED); //Configure the PORTD4 as output
TCNT1 = 63974; // for 1 sec at 16 MHz
TCCR1A = 0x00;
TCCR1B = (1<<CS10) | (1<<CS12);; // Timer mode with 1024 prescler
TIMSK = (1 << TOIE1) ; // Enable timer1 overflow interrupt(TOIE1)
sei(); // Enable global interrupts by setting global interrupt enable bit in SREG
while(1)
{
}
}
while this change would make it not to flash:
#include<avr/io.h>
#include<avr/interrupt.h>
#define LED PA1
unsigned int counter=0;
unsigned char flag=0;
ISR (TIMER1_OVF_vect) // Timer1 ISR
{
//PORTA ^= (1 << LED);
TCNT1 = 63974; // for 1 sec at 16 MHz
counter++;
if(counter>=10)
{
flag=1;
counter=0;
}
}
int main()
{
DDRA = (0x01 << LED); //Configure the PORTD4 as output
TCNT1 = 63974; // for 1 sec at 16 MHz
TCCR1A = 0x00;
TCCR1B = (1<<CS10) | (1<<CS12);; // Timer mode with 1024 prescler
TIMSK = (1 << TOIE1) ; // Enable timer1 overflow interrupt(TOIE1)
sei(); // Enable global interrupts by setting global interrupt enable bit in SREG
while(1)
{
if(flag)
{
flag=0;
PORTA ^= (1 << LED);
}
}
}
could anyone please help me?
Compiler saw that flag set to 0 at start of program and can't know that the variable can be changed by interrupt handler (the code never called directly in program).
So it optimized out flag check in while loop.
Use volatile qualifier for variables that accessed from different code streams (main code and interrupt handler, different threads in multi-threaded environment).
volatile unsigned char flag = 0;

How can I use ADXL345 in timer interrupt with Arduino mega

I want to use ADXL345 in timer interrupt with Arduino mega.
But it can't not work.
Here is my code :
#include <Wire.h>
#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37
int ADXAddress = 0xA7>>1;
int reading = 0;
int val = 0;
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
double Xg,Yg,Zg;
unsigned long t1, t2;
void setup()
{
Serial.begin(9600);
Wire.begin(); //初始化I2C
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.write(Register_2D);
Wire.write(8);
Wire.endTransmission();
delay(500);
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 2500; // compare match register //250 = 1ms//500=2ms
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS10) + (1 << CS11); // 64 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
}
void loop()
{
Serial.println(Z_out);
delay(500);
}
ISR(TIMER1_COMPA_vect){
Wire.beginTransmission(ADXAddress);
Wire.write(Register_Z0);
Wire.write(Register_Z1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
Z0 = Wire.read();
Z1 = Wire.read();
Z1 = Z1<<8;
Z_out = Z0+Z1;
}
}
ISR() function executes every 1 millisecond, but the codes in ISR() only take 650 microseconds.
I don't know why it couldn't work.
If I do all things in the loop(), it can work normally.
Can any one help me?
Thanks in advance,
You shouldn'y handle I2C communications in the ISR. Try using the timer interrupt to change the value of a flag. Check that flag in the main loop and read the value.
You cannot use the Wire library inside an ISR, as interrupts have been disabled. The Wire library uses interrupts.

Resources