- LiTime Speicher und Akkus         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Timerprobleme

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.01.2006
    Ort
    Gratkorn
    Alter
    34
    Beiträge
    207

    Timerprobleme

    Anzeige

    Powerstation Test
    Hallo an alle

    Ich hab ein Programm geschrieben, das alle ~5 Sekunden einen Wert über A2D einließt (Timergesteuert). Wenn dieser Wert unter 614 ist, wird dieser im Eeprom abgelegt und ein Zähler um 1 erhöht. Doeser wird auch im Eeprim abgelegt. Erst wenn der Wieder einmal über 614 war, kann der Wert und der Zähler um eins erhöht werden. Das ganze hab ich für 2 A2D Kanäle gemacht. Weiters hab ich eine Unterfunktion zum Auslesen der Wert aus dem Eeprom. (FUnktionsaufruf wenn PD7 gedrückt ist).

    Nur leider funktioniert es nicht wie sollte. Bei jeder MEssungen kommen zusätzlich Zeichen aufs Display die eigentlich nicht dort hingehören. Ich weiß aber nicht warum

    Sobald ein falsches Zeichen aus der main (messfunktion) am Display ist, werden bei der lesefunktion auch falsche Zeichen Dargestellt.

    Das Abspeichern im Eeprom funktioniert auch nicht.

    Hie nun mal der Code:

    Code:
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/eeprom.h>
    #include <avr/signal.h>	
    #include <avr/interrupt.h>	
    #include "avrlibdefs.h"
    #include "avrlibtypes.h"
    
    #include "a2d.h"
    #include "lcd.h"
    
    volatile uint16_t zelle[1];
    volatile uint16_t counter =0;
    
    int lcd_maske(void);
    int lcd_put_f(uint16_t adc);
    int timer_init (void);
    
    int timer_init(void)
    {
    	TIMSK = (1<<TOIE0);
    	TCNT0 = 0;
    	TCCR0 = (1<<CS02);
    
    	return(0);
    }
    
    int lcd_maske (void)
    {
    	lcd_init(LCD_DISP_ON);
    	lcd_home();
    	lcd_clrscr();
    	lcd_puts("   Unterspannungsanzeige");
    	lcd_gotoxy(0,1);
    	lcd_puts("Zelle 1:");
    	lcd_gotoxy(0,2);
    	lcd_puts("Zelle 2:");
    	return(0);
    }
    
    
    int lcd_put_f (uint16_t adc) //Zum anzeigen der Spannungen am Display
    {
    	float ganzzahl,komma;
    	uint8_t  int_ganzzahl, int_komma;
    
    	ganzzahl = (adc/1024.0) * 5;
    	komma = (ganzzahl -  (int) ganzzahl)*100;
    
    	int_ganzzahl = (int)ganzzahl;
    	int_komma = komma;
    	
    	lcd_put_d(int_ganzzahl);
    	lcd_putc('.');
    	lcd_put_d(int_komma);
    	return(0);
    }
    
    SIGNAL (SIG_OVERFLOW0)
    {
    	counter++;
    	
    	if(counter == 600) //5s
    	{
    		counter=0;
    		zelle[0] = a2dConvert10bit(0);
    		zelle[1] = a2dConvert10bit(1);
    		PORTD ^= (1<<0);
    	}
    }
    
    int lesen (void)
    {
    	cli();
    	lcd_clrscr();
    	lcd_home();
    	lcd_puts("Auslesen der Werte");
    	lcd_gotoxy(0,1);
    	lcd_puts("Niedrigster Wert    Anzahl\n");
    	lcd_puts("Zelle 1:\n");
    	lcd_puts("Zelle 2:");
    
    	lcd_gotoxy(9,2);
    	lcd_put_f(eeprom_read_word((uint16_t*) 2));
    
    	lcd_gotoxy(9,3);
    	lcd_put_f(eeprom_read_word((uint16_t*) 4));
    
    	lcd_gotoxy(20,2);
    	lcd_put_d(eeprom_read_byte((uint8_t*)0));
    
    	lcd_gotoxy(20,3);
    	lcd_put_d(eeprom_read_byte((uint8_t*)1));
    
    	loop_until_bit_is_set(PIND, PD7);
    
    	lcd_clrscr();
    	lcd_home();
    	lcd_maske();
    	sei();
    	return(0);
    }
    
    int main (void)
    {
    	uint8_t i, istpositiv[1], zaehler[1];
    	
    	istpositiv[0] = 1;
    	istpositiv[1] = 1;
    		
    	DDRC &=~ ((1<<PC0) | (1<<PC1));
    	PORTC &=~ ((1<<PC0) | (1<<PC1));
    	DDRD |= (1<<0);
    	
    	a2dInit();
    	a2dSetPrescaler(ADC_PRESCALE_DIV32);
    	a2dSetReference(ADC_REFERENCE_AVCC);
    	lcd_maske();
    	timer_init();
    	sei();
    		
    	while(1)
    	{
    	if(bit_is_clear(PIND, PD7) == 1)
    		lesen();
    		
    	for(i=0; i <2; i++)
    	{
    			
    		if(zelle[i] > 614)
    			istpositiv[i] = 1;
    				
    			if(istpositiv[i] == 1)
    			{
    				if(zelle[i] < 614)
    				{
    				zaehler[i]++;
    				cli();
    				eeprom_write_byte((uint8_t*)i, zaehler[i]);
    				eeprom_write_word((uint16_t*)(i*2)+2, zelle[i]);
    				sei();
    				istpositiv[i] =0;
    				}
    			}
    	}		
    			
    	lcd_gotoxy(9,1);
    	lcd_put_f(a2dConvert10bit(0));
    	lcd_putc('V');
    	lcd_gotoxy(9,2);
    	lcd_put_f(a2dConvert10bit(1));
    	lcd_putc('V');
    	}
    return(0);
    }
    Als Prozessor verwende ich einen Mega8

    Danke im Voraus

    Gruß Robert

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Das Abtesten (auch Lesen und Schreiben) mehrbytiger Werte musst du atomar machen, wenn das Ding in einer ISER geändert wird. Schau mal ins Wiki bei GCC oder den Fallstricken bei C-Programmierung, da hab ich das erklärt.
    Disclaimer: none. Sue me.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.01.2006
    Ort
    Gratkorn
    Alter
    34
    Beiträge
    207
    Hallo

    Ganz gena versteh ich das noch nicht. Währen dem Lesen/Schreiben von Daten in den EEprom darf kein Interrup auftreten, oder??

    Also wenn ich in der ISR vor dem Einlesen der beiden A2D Werte die Interrupts außschalte und danach wieder einschalte, geht das trotzdem nicht. Sobald ich die Funktion Lesen aufrufe, schalte ich ich die Interrupts aus. Beim Verlassen schalte ich sie wieder ein.

    Vor EEprom Aktionen, schalte ich sie ja immer aus.

    Danke im Voraus

    Gruß Robert

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    if(zelle[i] > 614)

    Das ist ein Befehl, der auf AVR nicht in eine einzige Instruktion umgesetzt werden kann. Wird der Wert gegen 614 verglichen, was durch die Sequenz cp und cpc geschieht und taucht dazwischen ne IRQ auf, die bedient wird und ändert die den Wert, dann hat ein Byte den alten Wert und ein Byte cshon den den neuen Wert. Insgesamt ist der Wert korupt, so daß die Bedingung x>614 auch erfüllt sein kann, wenn x<= 614 ist bzw falsch sein kann, wenn x>614 ist.

    https://www.roboternetz.de/wissen/in...-atomarer_Code
    Disclaimer: none. Sue me.

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.01.2006
    Ort
    Gratkorn
    Alter
    34
    Beiträge
    207
    Hallo Georg - Johan

    Das verstehe ich einmal. Das die Avrs nur mit 8 Bit Werten in "einem" rechnen können. Ich hab jetzt vor hedem Wert der größer als 8 Bit ist die Interrupts ausgeschaltet. Jedoch funktioniert es immer noch nicht

    Bei jeder Messung (if(counter = 610)) werden am Display falsche Zeichen angezeigt. Wenn ich nan in die lEsen Funktion umschalte hab ich wieder flasche Zeichen. Da hilft nur ein Reset. Die Werte werden auch nicht Richtig in den EEprom geschrieben bzw nicht Richtig ausgelesen.

    Kann es sein das hier irgendwo der Fehler steckt. Das die Adressierung der EEprom Zellen nicht stimmt?

    Hier nun mal der Code:

    Code:
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/eeprom.h>
    #include <avr/signal.h>	
    #include <avr/interrupt.h>	
    #include "avrlibdefs.h"
    #include "avrlibtypes.h"
    
    #include "a2d.h"
    #include "lcd.h"
    
    volatile uint16_t zelle[1];
    volatile uint16_t counter =0;
    
    int lcd_maske(void);
    int lcd_put_f(uint16_t adc);
    int timer_init (void);
    
    int timer_init(void)
    {
    	TIMSK = (1<<TOIE0);
    	TCNT0 = 0;
    	TCCR0 = (1<<CS02);
    
    	return(0);
    }
    
    int lcd_maske (void)
    {
    	lcd_init(LCD_DISP_ON);
    	lcd_home();
    	lcd_clrscr();
    	lcd_puts("   Unterspannungsanzeige");
    	lcd_gotoxy(0,1);
    	lcd_puts("Zelle 1:");
    	lcd_gotoxy(0,2);
    	lcd_puts("Zelle 2:");
    	return(0);
    }
    
    
    int lcd_put_f (uint16_t adc) //Zum anzeigen der Spannungen am Display
    {
    	float ganzzahl,komma;
    	uint8_t  int_ganzzahl, int_komma;
    	
    	cli();
    	ganzzahl = (adc/1024.0) * 5;
    	komma = (ganzzahl -  (int) ganzzahl)*100;
    	sei();
    	
    	int_ganzzahl = (int)ganzzahl;
    	int_komma = komma;
    	
    	lcd_put_d(int_ganzzahl);
    	lcd_putc('.');
    	lcd_put_d(int_komma);
    	return(0);
    }
    
    SIGNAL (SIG_OVERFLOW0)
    {
    	counter++;
    	
    	if(counter == 600) //5s
    	{
    		counter=0;
    		cli();
    		zelle[0] = a2dConvert10bit(0);
    		zelle[1] = a2dConvert10bit(1);
    		PORTD ^= (1<<0);
    		sei();
    	}
    }
    
    int lesen (void)
    {
    	cli();
    	lcd_clrscr();
    	lcd_home();
    	lcd_puts("Auslesen der Werte");
    	lcd_gotoxy(0,1);
    	lcd_puts("Niedrigster Wert    Anzahl\n");
    	lcd_puts("Zelle 1:\n");
    	lcd_puts("Zelle 2:");
    
    	lcd_gotoxy(9,2);
    	lcd_put_f(eeprom_read_word((uint16_t*) 2));
    
    	lcd_gotoxy(9,3);
    	lcd_put_f(eeprom_read_word((uint16_t*) 4));
    
    	lcd_gotoxy(20,2);
    	lcd_put_d(eeprom_read_byte((uint8_t*)0));
    
    	lcd_gotoxy(20,3);
    	lcd_put_d(eeprom_read_byte((uint8_t*)1));
    
    	loop_until_bit_is_set(PIND, PD7);
    
    	lcd_clrscr();
    	lcd_home();
    	lcd_maske();
    	sei();
    	return(0);
    }
    
    int main (void)
    {
    	uint8_t i, istpositiv[1], zaehler[1];
    	
    	istpositiv[0] = 1;
    	istpositiv[1] = 1;
    		
    	DDRC &=~ ((1<<PC0) | (1<<PC1));
    	PORTC &=~ ((1<<PC0) | (1<<PC1));
    	DDRD |= (1<<0);
    	
    	a2dInit();
    	a2dSetPrescaler(ADC_PRESCALE_DIV32);
    	a2dSetReference(ADC_REFERENCE_AVCC);
    	lcd_maske();
    	timer_init();
    	sei();
    		
    	while(1)
    	{
    	if(bit_is_clear(PIND, PD7) == 1)
    		lesen();
    		
    	for(i=0; i <2; i++)
    	{
    		cli();	
    		if(zelle[i] > 614)
    		sei();
    			istpositiv[i] = 1;
    				
    			if(istpositiv[i] == 1)
    			{
    				cli();
    				if(zelle[i] < 614)
    				{
    				sei();
    				zaehler[i]++;
    				cli();
    				eeprom_write_byte((uint8_t*)i, zaehler[i]);
    				eeprom_write_word((uint16_t*)(i*2)+2, zelle[i]);
    				sei();
    				istpositiv[i] =0;
    				}
    			}
    	}		
    			
    	lcd_gotoxy(9,1);
    	lcd_put_f(a2dConvert10bit(0));
    	lcd_putc('V');
    	lcd_gotoxy(9,2);
    	lcd_put_f(a2dConvert10bit(1));
    	lcd_putc('V');
    	}
    	return(0);
    }
    Ich hoffe mir kann jemand helfen

    Gruß Robert

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    49
    Beiträge
    1.562
    wenn ich SprinterSB richtig verstanden habe geht es bei dem Interupt problem nur um variablen die so woll in einer Interrupt routine ab gefragt / geändert werden als auch im Haupt Programm. Nich immer wenn eine grössere Variable auf tausch muß man die Interupts abschalten.

    Aber das Problem gibt es nicht nur beim AVR sonder so was Ähnliches hatte ich auch schon mal bei einer Funktion unter windows die eindeutige Zaehler in eine Multithread Programm erzeugen sollte.

    mir ist überhaupt nicht klar wie das Funktionieren soll auf den wert in zelle wir ja nie zu gegriffen. oder ? auf die Funktion lcd_put_f auch nicht.
    Ich geben zu so satel fest bin ich in AVR C noch nicht aber hier fehlt doch die Hälfte. Was mir auch fehlt ist das warten bis der AD wandler fertig ist aber das kann ja sein das das deine Includes machen. das habe ich bei mir alles selbst geschrieben.

    Gruß
    P: Meine Tochter (06.11.07) und https://www.carnine.de
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Zitat Zitat von Razer
    Hier nun mal der Code:

    Code:
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/eeprom.h>
    #include <avr/signal.h>	
    #include <avr/interrupt.h>	
    #include "avrlibdefs.h"
    #include "avrlibtypes.h"
    
    #include "a2d.h"
    #include "lcd.h"
    
    !!! Du greifst auf zelle[0] und zelle[1] zu, definierst zelle[] aber nur zu Länge1, das crasht!!! Es muss mindestens Länge 2 haben!
    volatile uint16_t zelle[1];
    
    volatile uint16_t counter =0;
    
    int lcd_maske(void);
    int lcd_put_f(uint16_t adc);
    int timer_init (void);
    
    int timer_init(void)
    {
    	TIMSK = (1<<TOIE0);
    	TCNT0 = 0;
    	TCCR0 = (1<<CS02);
    
    	return(0);
    }
    
    int lcd_maske (void)
    {
    	lcd_init(LCD_DISP_ON);
    	lcd_home();
    	lcd_clrscr();
    	lcd_puts("   Unterspannungsanzeige");
    	lcd_gotoxy(0,1);
    	lcd_puts("Zelle 1:");
    	lcd_gotoxy(0,2);
    	lcd_puts("Zelle 2:");
    	return(0);
    }
    
    
    int lcd_put_f (uint16_t adc) //Zum anzeigen der Spannungen am Display
    {
    	float ganzzahl,komma;
    	uint8_t  int_ganzzahl, int_komma;
    	
    	cli();
    	ganzzahl = (adc/1024.0) * 5;
    	komma = (ganzzahl -  (int) ganzzahl)*100;
    	sei();
    	
    	int_ganzzahl = (int)ganzzahl;
    	int_komma = komma;
    	
    	lcd_put_d(int_ganzzahl);
    	lcd_putc('.');
    	lcd_put_d(int_komma);
    	return(0);
    }
    
    SIGNAL (SIG_OVERFLOW0)
    {
    	counter++;
    	
    	if(counter == 600) //5s
    	{
    		counter=0;
    		cli();
    		zelle[0] = a2dConvert10bit(0);
    		zelle[1] = a2dConvert10bit(1);
    		PORTD ^= (1<<0);
    		sei();
    	}
    }
    
    int lesen (void)
    {
    	cli();
    	lcd_clrscr();
    .	lcd_home();
    	lcd_puts("Auslesen der Werte");
    	lcd_gotoxy(0,1);
    	lcd_puts("Niedrigster Wert    Anzahl\n");
    	lcd_puts("Zelle 1:\n");
    	lcd_puts("Zelle 2:");
    
    	lcd_gotoxy(9,2);
    	lcd_put_f(eeprom_read_word((uint16_t*) 2));
    
    	lcd_gotoxy(9,3);
    	lcd_put_f(eeprom_read_word((uint16_t*) 4));
    
    	lcd_gotoxy(20,2);
    	lcd_put_d(eeprom_read_byte((uint8_t*)0));
    
    	lcd_gotoxy(20,3);
    	lcd_put_d(eeprom_read_byte((uint8_t*)1));
    
    	loop_until_bit_is_set(PIND, PD7);
    
    	lcd_clrscr();
    	lcd_home();
    	lcd_maske();
    	sei();
    	return(0);
    }
    
    int main (void)
    {
    	uint8_t i, istpositiv[1], zaehler[1];
    	
    	istpositiv[0] = 1;
    	istpositiv[1] = 1;
    		
    	DDRC &=~ ((1<<PC0) | (1<<PC1));
    	PORTC &=~ ((1<<PC0) | (1<<PC1));
    	DDRD |= (1<<0);
    	
    	a2dInit();
    	a2dSetPrescaler(ADC_PRESCALE_DIV32);
    	a2dSetReference(ADC_REFERENCE_AVCC);
    	lcd_maske();
    	timer_init();
    	sei();
    		
    	while(1)
    	{
    		if(bit_is_clear(PIND, PD7) == 1)
    			lesen();
    		
    		for(i=0; i <2; i++)
    		{
    			cli();	
    			if(zelle[i] > 614)
    			sei();
    			istpositiv[i] = 1;
    				
    			if(istpositiv[i] == 1)
    			{
    				cli();
    				if(zelle[i] < 614)
    				{
    					sei();
    					zaehler[i]++;
    					cli();
    					eeprom_write_byte((uint8_t*)i, zaehler[i]);
    					eeprom_write_word((uint16_t*)(i*2)+2, zelle[i]);
    					sei();
    					istpositiv[i] =0;
    				}
    			}
    			sei(); !!! IRQs müssen auch wieder eingeschaltet werden, wenn if(...) falsch ist.
    		}		
    			
    		lcd_gotoxy(9,1);
    		lcd_put_f(a2dConvert10bit(0));
    		lcd_putc('V');
    		lcd_gotoxy(9,2);
    		lcd_put_f(a2dConvert10bit(1));
    		lcd_putc('V');
    	}
    	return(0);
    }
    Ich hoffe mir kann jemand helfen

    Gruß Robert
    Die Änderungen hab ich mit !!! gekennzeichnet.
    Disclaimer: none. Sue me.

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.01.2006
    Ort
    Gratkorn
    Alter
    34
    Beiträge
    207
    Hallo an alle

    @Number Five:

    Der Wert in zelle wird in den Eeprom geschrieben oder auch ausgelesen (Lesefunktion). Die Funktion lcd_put_f wird sehr wohl angewendet. Genau schauen...

    Danke SprinterB Da mit der Arraygröße hab ich mich vertan . Jedoch funktioniert der Zähler für den Eeprom noch nicht Richtig. Der EEprom hat doch nach einem Flash den Wert 255 (0xFF). Jedoch stimmt der Wert beim nächsten Zählerzugriff nicht und es steht ein falscher Wert. Ab hier zählt nun der Zähler im um 1 aufwärts.

    Was ist da los?? Wann wird der EEprom gelöscht?? Nur wenn ich das explizit im AVRDUDE mach???

    Weiters versteh ich noch nicht das Auslesen. Das Auslesen der WORDs funktioniert nur mit den Adressen 4,6. Ich dacht die Adressen sind 2,4.

    Warum??

    Hier nun der Code

    Code:
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/eeprom.h>
    #include <avr/signal.h>   
    #include <avr/interrupt.h>   
    #include "avrlibdefs.h"
    #include "avrlibtypes.h"
    
    #include "a2d.h"
    #include "lcd.h"
    
    volatile uint16_t zelle[2];
    volatile uint16_t counter =0;
    
    int lcd_maske(void);
    int lcd_put_f(uint16_t adc);
    int timer_init (void);
    
    int timer_init(void)
    {
       TIMSK = (1<<TOIE0);
       TCNT0 = 0;
       TCCR0 = (1<<CS02);
    
       return(0);
    }
    
    int lcd_maske (void)
    {
       lcd_init(LCD_DISP_ON);
       lcd_home();
       lcd_clrscr();
       lcd_puts("   Unterspannungsanzeige");
       lcd_gotoxy(0,1);
       lcd_puts("Zelle 1:");
       lcd_gotoxy(0,2);
       lcd_puts("Zelle 2:");
       return(0);
    }
    
    
    int lcd_put_f (uint16_t adc) //Zum anzeigen der Spannungen am Display
    {
       float ganzzahl,komma;
       uint8_t  int_ganzzahl, int_komma;
       
       cli();
       ganzzahl = (adc/1024.0) * 5;
       komma = (ganzzahl -  (int) ganzzahl)*100;
       sei();
       
       int_ganzzahl = (int)ganzzahl;
       int_komma = komma;
       
       lcd_put_d(int_ganzzahl);
       lcd_putc('.');
       lcd_put_d(int_komma);
       return(0);
    }
    
    SIGNAL (SIG_OVERFLOW0)
    {
       counter++;
       
       if(counter == 600) //5s
       {
          counter=0;
          cli();
          zelle[0] = a2dConvert10bit(0);
          zelle[1] = a2dConvert10bit(1);
          PORTD ^= (1<<0);
          sei();
       }
    }
    
    int lesen (void)
    {
       cli();
       lcd_clrscr();
       lcd_home();
       lcd_puts("Auslesen der Werte");
       lcd_gotoxy(0,1);
       lcd_puts("Niedrigster Wert    Anzahl\n");
       lcd_puts("Zelle 1:\n");
       lcd_puts("Zelle 2:");
    
       lcd_gotoxy(9,2);
       lcd_put_f(eeprom_read_word((uint16_t*) 4));
    
       lcd_gotoxy(9,3);
       lcd_put_f(eeprom_read_word((uint16_t*) 6));
    
       lcd_gotoxy(20,2);
       lcd_put_d(eeprom_read_byte((uint8_t*)0));
    
       lcd_gotoxy(20,3);
       lcd_put_d(eeprom_read_byte((uint8_t*)1));
    
       loop_until_bit_is_set(PIND, PD7);
    
       lcd_clrscr();
       lcd_home();
       lcd_maske();
       sei();
       return(0);
    }
    
    int main (void)
    {
       uint8_t i, istpositiv[2], zaehler[2];
       
       istpositiv[0] = 1;
       istpositiv[1] = 1;
          
       DDRC &=~ ((1<<PC0) | (1<<PC1));
       PORTC &=~ ((1<<PC0) | (1<<PC1));
       DDRD |= (1<<0);
       
       a2dInit();
       a2dSetPrescaler(ADC_PRESCALE_DIV32);
       a2dSetReference(ADC_REFERENCE_AVCC);
       lcd_maske();
       timer_init();
       sei();
          
       while(1)
       {
          if(bit_is_clear(PIND, PD7) == 1)
             lesen();
          
          for(i=0; i <2; i++)
          {
             cli();   
             if(zelle[i] > 614)
    		 {
             sei();
             istpositiv[i] = 1;
    		 }
    		sei();
             if(istpositiv[i] == 1)
             {
                cli();
                if(zelle[i] < 614)
                {
                   sei();
                   zaehler[i]++;
                   cli();
                   eeprom_write_byte((uint8_t*)i, zaehler[i]);
                   eeprom_write_word((uint16_t*)(i*2)+2, zelle[i]);
                   sei();
                   istpositiv[i] =0;
                }
             }
             sei(); 
          }      
             
          lcd_gotoxy(9,1);
          lcd_put_f(a2dConvert10bit(0));
          lcd_putc('V');
          lcd_gotoxy(9,2);
          lcd_put_f(a2dConvert10bit(1));
          lcd_putc('V');
       }
       return(0);
    }
    Danke im Voraus

    Gruß Robert

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Da ist noch ein Schnatzer:

    (uint16_t*)(i*2)+2

    Du castest den int i*2 nach uint16_t*. Auf diesen Pointer addierst du 2, was nach der Semantik von C ist +2*sizeof(uint16_t), also den Pointer um 2 Einheiten worauf er zeigt, weiterzählen.

    Was du wahrscheinlich meinst ist

    (uint16_t*)((i*2)+2)

    Erst die Addition als Skalar, und danach erst den Cast?
    Disclaimer: none. Sue me.

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.01.2006
    Ort
    Gratkorn
    Alter
    34
    Beiträge
    207
    Hallo Georg-Johann

    Danke Ich dachte der Term wird als ganzes gesehen.

    Es funktioniert nun eigentlich schon fast. Jedoch hab ich noch ein Problem. Das Auslesen oder das Abspeichern der 16Bit Werte funktioniert noch nicht ganz Richtig. Nach einem Reset ist das Flag für das Abspeichern auf 1 gesetzt. Es soll ein Abspeichern erfolgen wenn der ADC Wert unter 614 ist. Jedoch funktioniert das nicht

    Code:
    /*=================================================================
    Programmtitel: Unterspannungsaanzeige
    Autor: Robert Schilling
    Datum: 2.3.2006
    Hardware: LCD an PORTB
    		Led an PortD0
    		Poti an PC0, PC1
    		Schalter an PD7
    		
    Programmbeschreibung:
    Die beiden Potis simulieren 2 Lipo Zellen.
    Sobald der Spannungswert unter 3V Wird ein Zähler um 
    1 erhöht und der Wert in den EEprom geschrieben.
    Es wenn der Wert wieder über 3V steigt wird die 
    nächste Unterspannung "gewertet" und in den EEprom geschrieben.
    Die Messungen sind Timergesteuert (8bit Timer0). Sie 
    lösen einen Overflow Interrupt aus. Sobald 600 Interrupts (~5sek)
    werden die Zellen gemessen.
    
    ====================================================================*/
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/eeprom.h>
    #include <avr/signal.h>   
    #include <avr/interrupt.h>   
    #include "avrlibdefs.h"
    #include "avrlibtypes.h"
    
    #include "a2d.h"
    #include "lcd.h"
    
    volatile uint16_t zelle[2];	//Varibale die von der Interruptroutine 
    volatile uint16_t counter =0; //und auch von anderen Funktionen gelesen werden können
    
    int lcd_maske(void);		//LCD Maske
    int lcd_put_f(uint16_t adc);	//Funktion zum Anzeigen des Spannungswertes
    int timer_init (void);		//Initialisieren des Timers
    
    int timer_init(void) //Initialisieren des Timers
    {
       TCCR0 = (1<<CS02);	//Freq = F_CPU/256
       TCNT0 = 0;			//Counter = 0
       TIMSK = (1<<TOIE0);   //Enable Overflow Interrupts
       return(0);
    }
    
    int lcd_maske (void)	//Aufbau der LCD Maske
    {
       lcd_init(LCD_DISP_ON);	//LCD initialisiern
       lcd_home();				//lcd home
       lcd_clrscr();			//Clear Screen
       lcd_puts("   Unterspannungsanzeige");
       lcd_gotoxy(0,1);
       lcd_puts("Zelle 1:");
       lcd_gotoxy(0,2);
       lcd_puts("Zelle 2:");
       return(0);
    }
    
    
    int lcd_put_f (uint16_t adc) //Zum anzeigen der Spannungen am Display
    {							//ADC Wert wird in eine Spannung umgerechnet
       float ganzzahl,komma;
       uint8_t  int_ganzzahl, int_komma;
       
       cli();						//Disable Interrupts
       ganzzahl = (adc/1024.0) * 5;
       komma = (ganzzahl -  (int) ganzzahl)*100;
       sei();						//Enable Interrupts
       
       int_ganzzahl = (int)ganzzahl;
       int_komma = komma;
       
       lcd_put_d(int_ganzzahl);
       lcd_putc('.');
       lcd_put_d(int_komma);
       lcd_putc('V');
       return(0);
    }
    
    SIGNAL (SIG_OVERFLOW0) //Overflow Routine
    {
       counter++;			// bei jedem Overflow counter++
       
       if(counter == 600) //Wenn counter = 600 (~5sek)
       {
          counter=0;
          cli();			//Disable Interrupts
          zelle[0] = a2dConvert10bit(0); //Messen der Werte
          zelle[1] = a2dConvert10bit(1);
    	  sei();			//Enable Interrupts
          PORTD ^= (1<<0);	//Led umschalten
    
       }
    }
    
    int lesen (void)		//Lesefunktion zum Auslesen der Werte
    {
       cli();			//Disable Interrupts
       lcd_clrscr();
       lcd_home();
       lcd_puts("Auslesen der Werte");
       lcd_gotoxy(0,1);
       lcd_puts("Niedrigster Wert    Anzahl\n");
       lcd_puts("Zelle 1:\n");
       lcd_puts("Zelle 2:");
    
       lcd_gotoxy(9,2);
       lcd_put_f(eeprom_read_word((uint16_t*) 2)); //Wert von Zelle 1 auslesen
    
       lcd_gotoxy(9,3);
       lcd_put_f(eeprom_read_word((uint16_t*) 4)); //Wert von Zelle 2 auslesen
    
       lcd_gotoxy(20,2);
       lcd_put_d(eeprom_read_byte((uint8_t*)0));	//Anzahl der Unterspannungen vo Zelle1
    
       lcd_gotoxy(20,3);
       lcd_put_d(eeprom_read_byte((uint8_t*)1));	//Anzahl der Unterspannungen von Zelle2
    
       loop_until_bit_is_set(PIND, PD7); //warten bis Schalter an PD7 wieder ausgeschalten ist.
    
       lcd_clrscr();
       lcd_home();
       lcd_maske();
       sei();			//Enable Interrupts
       return(0);
    }
    
    int main (void) //Mainfunktion
    {
       uint8_t i, istpositiv[2], zaehler[2];
       
       istpositiv[0] = 1; //Flag ob positiv 
       istpositiv[1] = 1;
       zaehler[0] = eeprom_read_byte((uint8_t*) 0); //Zähler aus dem EEprom auslesen
       zaehler[1] = eeprom_read_byte((uint8_t*) 1); //Zähler aus dem EEprom auslesen
       
       if(zaehler[0] == 255) //Wenn Zähler =255 = 0xFF (nach dem Flashen)
    		zaehler[0] = 0; //Zähler = 0;
    	
        if(zaehler[1] == 255) 
    		zaehler[1] = 0;
    		
       DDRC &=~ ((1<<PC0) | (1<<PC1));	//PC0, PC1 Eingänge
       PORTC &=~ ((1<<PC0) | (1<<PC1));	//disabke pullups
       DDRD &=~ (1<<7);					//PD7 Eingang (schalter)
       PORTD &=~ (1<<7);					//Disable pullups		
       DDRD |= (1<<0);		//PD0 Ausgang
       PORTD &=~ (1<<0);
       
       a2dInit();			//A2D initialisiern
       a2dSetPrescaler(ADC_PRESCALE_DIV32); //Prescaler = 32
       a2dSetReference(ADC_REFERENCE_AVCC); //Refernzspannung = Versorgungsspanung
       lcd_maske();
       timer_init(); //Timer initialisieren
       sei();
          
       while(1)
       {
    	cli();
          if(bit_is_clear(PIND, PD7) == 1) //PD7 auf high geschalten ist
             lesen();			//Funktion lesen aufrufen (Auslesen der Werte)
        sei();
    	
          for(i=0; i <2; i++) //Auswerten der Messungen
          {
            if(zelle[i] > 614) //wenn Zelle > 3V
    		 {
             istpositiv[i] = 1; //Flag setzen 
    		 }
    	
             if(istpositiv[i] == 1) //Wenn Flag gesetzt
             {
                if(zelle[i] < 614) //Wenn zelle i < 3V
                {
                   zaehler[i]++;	//Zähler um eins erhöhen
                   cli();			//Disable Interrups
                   eeprom_write_byte((uint8_t*)i, zaehler[i]);	//wert des Zählers in den EEprim schreiben
                   eeprom_write_word((uint16_t*)((i*2)+2), zelle[i]);	//Wert der Spannung in EEProm schreiben
                   sei();			//Enable Interrupts
                   istpositiv[i] =0;	//Flag löschen
                }
             }
          }      
             
          lcd_gotoxy(9,1);
          lcd_put_f(a2dConvert10bit(0)); //Spannungswert anzeigen
          lcd_gotoxy(9,2);
          lcd_put_f(a2dConvert10bit(1));	//Spannungswert anzeigen
       }
       return(0);
    }

    Beim Auslesen wird immer 0.0V dargestellt. Bis ich den Wert ändere. Warum?

    Danke im Voraus

    Gruß Robert[/code]

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus