PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zählvariable läuft über



Mithrandir
24.08.2015, 23:26
Hallo Roboternetz-Forum!

Ich habe ein kleines Problem. Ich will mit dem ATmega328p eine kleine Messschaltung aufbauen, für welche ich eine Zeitmessung brauche. In diesem Fall habe ich den Timer 1 so eingestellt, dass er akke 10us einen Overflow-Interrupt verursacht. Die Variable, die ich in der Timer-ISR raufzählen lasse, habe ich zum testen mal auf einem I2C LCD Display ausgegeben. Das Problem hierbei: die Variable hat schon nach dem Wert (2^16)/2 einen Überlauf. Die ist aber als 'unsigned long int' deklariert, also eigendlich als 32-bit. Aber egal, was ich probiere, der Überlauf kommt immer viel zu früh, was mache ich hier falsch?

Hoffe, Ihr könnt mir helfen!



#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <avr/interrupt.h>

#include "lcd.h" // Library for I2C LCD Display

#define F_CPU 16000000UL
#define TIMER1_PRELOAD -20

extern void lcd_backlight(char on); // not in lcd.h

unsigned long int timer1_cnt = 0;
char buffer_timer1_cnt[20]; // to buffer a variable for "itoa"

int main (void) {

// Initalize 16-bit Timer 1 Overflow-Interrupt

TCCR1A = 0x00;
TCCR1B = (0 << CS12) | (1 << CS11) | (0 << CS10); // set prescaler to 8 --> Timer = 8 / 16MHz = 0.5us --> preload = -20
TCNT1 = TIMER1_PRELOAD;

TIMSK1 = (1<<TOIE1); // enable timer 1 overflow interrupt

sei(); // (set enable interrupt) enable all interrupts

lcd_init(LCD_ON_DISPLAY);

lcd_backlight(1);

while(1) {

lcd_clrscr();

lcd_gotoxy(0, 0); // first parameter = column, second parameter = line

itoa(timer1_cnt, buffer_timer1_cnt, 10); // convert integer to string
lcd_puts(buffer_timer1_cnt); // write a string to I2C-LCD Display

_delay_ms(10);

} // while (1)
} // int main (void)

ISR (TIMER1_OVF_vect) { // 0.01ms clk

TCNT1 = TIMER1_PRELOAD; // preload timer cnt register

timer1_cnt++;

} // ISR (TIMER1_OVF_vect)

sternst
24.08.2015, 23:59
Aber egal, was ich probiere, der Überlauf kommt immer viel zu früh, was mache ich hier falsch?Die falsche Funktion zum Umwandeln des Variableninhalts in einen String zu benutzen, und dir so einen Überlauf vorgaukeln zu lassen, der in Wirklichkeit gar nicht da ist.

Mithrandir
25.08.2015, 20:07
Ok, danke für die Antwort!
Da mit char hab ich echt übersehen, das war ein Fehler.
Aber nachdem ich es umgeändert hatte, bestand das Poblem immer noch. Hier (https://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F ) hab ich dann gelesen, dass man statt itoa auch sprintf nehmen könnte, das hat mein Problem dann letztendlich gelöst, nun geht es.

askazo
27.08.2015, 07:46
Genau das war es doch, was sternst meinte ^^ - eben das itoa hier ungeeignet ist.
itoa() erwartet als ersten Parameter ein int (16 Bit / -32768 - +32767). Bei größeren Zahlen bekommst Du daher einen Überlauf.
Auf die Lösung mit printf() bist Du ja schon selber gekommen :)
Gruß,
askazo