C programm

Gast #339511
Lesenswert?

Hallo leute,
ich brauche eure Hilfe.
ich habe ein C-code für ATtiny45 geschrieben, dies code hat dies
funktionalität:
AD-Wandler wird intialisiert und gibt den Messwert wiederzurück.
in ein Feld wird das Ergebniss gespeichert.
mein Ziel ist so:wird AD-Wandler gelesen, und in erste Element
gespeichet, dann wartet einger zeit wirdi erhöht und messt wieder.
mein Problem: wenn ich ein Breackpoint setze  krige ich schon die
gewünschte Messungen( d.h. unterschiedliche werte werden im Feld
gespeichert), abet wenn ich das Programm laufen lasse(ohne
Breack-point), wird im Feld die gleiche wert gespeichert.
ich habe das 20 mal durchgelesen, aber finde die lösung nicht.
hier das code

/**************main.c*************************/

#include <iot45v.h>
#include "adc.h"
#include "timer.h"
//void int_timer0(void);
//#pragma interrupt_handler int_timer0:iv_TIMER0_OVF

//int Ergebnis;
//void get_sensor(void);
unsigned int digital_wert,i;
unsigned int test[20];


void main()
{

  Adc_Init();
  DDRB=0x17;
  PORTB=0x00;
  //while(1)


   for(i=0; i<=20; i++)
   {
        test[i]= umsetzen_Spannung();
        wait_10ms(2);
    PORTB=0x17;
    wait_10ms(2);
    PORTB=0x00;
    //PORTB=0x17;
  }


  //PORTB=0x17;
    while(1);

}

/******************Timer.c***************************/
#include "timer.h"
#include <iot45v.h>
#pragma interrupt_handler int_timer0:iv_TIMER0_OVF

unsigned int count=0;
void wait_10ms(unsigned char time)
{
  TCNT0 = 173;
  SREG |= (1<<7);       //SREG:Bit 7 – I: Global Interrupt Enable
  TIMSK = (1<<TOIE0);//Timer0 Int. Enable
  TCCR0B = (1<<CS02)|(1<<CS00);
  while(count<time)  {};
  count=0;
}

void int_timer0(void)
{
  //PORTB=0x17;
  count++;
  TCNT0 = 173;
  TCCR0B = (1<<CS02)|(1<<CS00);
}


void get_sensor(void)
{
 //Adc_Init();
 //umsetzen_Spannung();
 }

/******************adc.c*******************************/

#include "adc.h"
#include <iot45v.h>

unsigned int Ergebnis;

void Adc_Init(void)
   {
     ADCSRA = 0x80;           //Durch das setzen von Bit ADEN schaltet
Der AD-Umsetzer ein
   ADMUX = 0x03;           //wählt der Kanal(ADC3) und setzt die
Rferenzspannung auf 5v
  }

unsigned int umsetzen_Spannung(void)
  {
    ADCSRA = 0xC3;                  //AD-Umsetzer Starten und Prescaler
auswählen
  while ( ADCSRA & (1<<ADSC));      //Warte-Schleife bis Ende der
Umsetzung
  Ergebnis=(ADCL+ADCH*256);
  return Ergebnis;       // Im ADCL sind die ersten 8 bits des
Ergebnisses
                         // Im ADCH sind die restlichen 2 Bits
gespeichert
  }



Danke euch
#339513
Lesenswert?

Wenn du ein Array erzeugst:

unsigned int test[20];


dann hat dieses Array 20 Elemente. Dies sind die Elemente

0, 1, 2, 3, ..., 17, 18, 19

Zähl sie mit den Figern ab: sind genau 20

Dann aber machst du:

   for(i=0; i<=20; i++)
   {
        test[i]= umsetzen_Spannung();

Hier wird i irgendwann den Wert 20 kriegen. Das heist aber
auch du weist einem test[20] einen Wert zu. Das Array hat
aber keine Element test[20]. Das höchste zulässige ist
test[19]! Das heist aber auch, dein Program versucht in
einen Speicherbereich zu schreiben, der irgendwo liegt.
Spätestens jetzt ist Funktionalität deines Programmes völlig
undefiniert, alles mögliche kann passieren.

for-Schleifen, die über Arrays laufen, schauen eigentlich
immer so aus:

   for( i = 0; i < 20; i++ )

Beachte: 'Kleiner', nicht 'Kleiner gleich'.

Profis machen das übrigens anders. Die stört nämlich, dass da
im Code, die Zahl 20 explizit vorkommt. Ein Profi schreibt
das ganze zb. so

  for( i = 0; i < sizeof(test)/sizeof(*test); i++ ) {
    test[i] = unsetzen_Spannung();
    ...

oder er macht folgendes:

unsigned char test[20];
#define NR_TEST  (sizeof(test)/sizeof(*test))

....


   for( i = 0; i < NR_TEST; i++ ) {
     test[i] =
     ...

ist aber im Grunde dasselbe, nur besser lesbar. Das Prinzip
ist aber immer das Gleiche: Der Compiler soll die Anzahl
aus der eigentlichen Array-Dekleration ausrechnen anstatt
sich darauf zu verlassen, dass der Programmierer schon an allen
Stellen die richtigen Zahlen benutzt.

Weiter hab ich mir im Übrigen dein Pgm noch nicht angesehen.
Gast #339514
Lesenswert?

oder
#define NR_TEST  20 // Beschreibung /Grenzen?
unsigned char test[NR_TEST];


....


   for( i = 0; i < NR_TEST; i++ ) {
     test[i] =
     ...

hat den Vorteil das man das #define in eine zentrale
Konfigurationsdatei legen kann.
Gast #339515
Lesenswert?

Hallo,
das war nicht das problem,mit 20 war nur falsche eingetippt, die for
Schleife läuft von 0 bis 19 ist schon Klar.
ich habe auch den count als Volatile deklariert ich kriege das gleiche
Ergebnis
Gast #339517
Lesenswert?

als Rferenzspannung 5v, um das zu testen das geht alles so.
auf mein Plattine befindet sich ein drucksensor, ich ändere den druck,
und klar wird am AD-Wandler eine Spannung, die umgewandelt wird.
ich arbeite mit AVR studio dann lese ich die ausgegebene werte.
#339520
Lesenswert?

Worauf ich hinaus will:
Wenn sich der ADC Input nur langsam ändert, dann wirst
du das in deinem Pgm nicht feststellen können, da
das Pgm gerade mal knapp 1 Sekunde den ADC misst.

Setzt du einen Breakpoint in die Schleife, dann sieht
die Sache anders aus, da du ja als Benutzer sehr
viel länger brauchst um das Pgm weiterlaufen zu lassen.

Daher kann es sein, dass mit dem Breakpoint in der Schleife
du verschiedene Werte siehst. Gibst du den Breakpoint weg,
dann sieht alles gleich aus, weil das Pgm einfach zu schnell
ist um irgendwelche Änderungen messen zu können.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren