Code Optimierung Stepper mit ADC und Taster Debounce

OP #1564218
Lesenswert?

Hallo erstmal mein Name ist Tom, bin schon länger passiver Leser dieses 
Forums und bin gerade bei meinem ersten Projekt.
Ich steuere mit meinem Atmega8 die L297/298 Kombination an, an der ein 
kleiner Schrittmotor hängt. Das Signal erzeuge ich indem ich mit dem 
Timer Overflowflag ein Bit Toggle. Der Motor wird über ein Poti, welches 
an PC0 hängt über einen ADC in der Drehzahl verändert.Hierzu übergebe 
ich vom ADC einen Wert Für den Timer Reload. Jetzt brauche ich einen 
entprellten Taster mit dem ich die ganze Sache ein und ausschalten kann. 
Die Schalter Entprellung funzt separat, aber nicht in  Kombination mit 
meiner ISR. Es wär echt cool, wenn mir jemand ein paar Tips zur 
Entwurschtellung meines Codes geben könnte. Der Ablauf meines Motor 
Signals in der ISR scheint mir nicht optimal, aber ich hab kein Plan, 
wie ich das anders realisieren kann.

Grüße

Tom
1
/*myheader.h*/
2
#include<avr/io.h>
3
#ifndef F_CPU
4
#define F_CPU 3686400UL     
5
#endif 
6
#include <util/delay.h>
7

8

9
/****************************Define**************************************************/
10
#define BUTTON_PORT PORTD       /* PORTx - Register für Taster Output */
11
#define BUTTON_PIN PIND         /* PINx - Register für Taster Input */
12
#define BUTTON_BIT PD2          /* bit für Taster input/output */
13

14

15
#define DEBOUNCE_TIME 25        /* Debounce Zeit */
16
#define LOCK_INPUT_TIME 250     /* Wartezeit nachdem Taster gedrückt wurde*/
17

18

19
#define LOW 0
20
#define HIGH 1
21
#define INPUT(port,pin)   DDR ## port &= ~(1<<pin)
22
#define OUTPUT(port,pin)  DDR ## port |= (1<<pin)
23
#define CLEAR(port,pin)   PORT ## port &= ~(1<<pin)
24
#define SET(port,pin)     PORT ## port |= (1<<pin)
25
#define TOGGLE(port,pin)  PORT ## port ^= (1<<pin)
26
#define READ(port,pin)   (PIN ## port & (1<<pin)) 
27

28

29

30

31
/*********************Funktions Prototypen*****************************************/
32

33

34
int button_is_pressed();
35
void delay_ms(uint16_t ms);
36
int button_is_pressed();
37
int read_adc(void);
38

39

40

41

42

43

44
/********************Stepper mit ADC.c*****************************/
45

46
#include <avr/interrupt.h>
47
#include <stdint.h>
48
#include "myheader.h"
49

50

51

52

53

54

55
volatile uint8_t reload=0;
56

57

58

59

60

61

62
int main (void)
63
{
64
     
65

66
    while (button_is_pressed(1))
67
        {
68
                
69
                  
70
              read_adc();
71
                 
72
                
73
        }
74
  
75
   
76
   
77
   
78
   
79
}
80

81

82
ISR(ADC_vect)
83
{
84

85
  OUTPUT(B,0);       //PORT B Pin 0 als Ausgang schalten
86
      
87
  TCCR0=(0<<CS02|1<<CS01|0<<CS00);  //Prescaler einstellen 1/8
88
  
89
  SET(B,0);   // PORT B Pin 0 auf 1 setzen
90
  
91
for (;;)
92
  {    
93
  
94
    if ( (bit_is_set (TIFR,0)))  //Abfrage des Timer Flags
95
    {   
96
      
97
      
98
       reload=ADCH;   
99
      reload=reload/2;       // Reloadwert zu groß
100
      TCNT0= reload; 
101
      TOGGLE(B,0);         // Ausgang Togglen
102
      TIFR=0x01;        //Timer Overflow Flag löschen mit 1
103
    
104

105
    }
106
    
107
    
108
  
109
  
110
  }
111
}
112

113
/**************buttondebounce.c***********************/
114

115
#include "myheader.h"
116

117

118
/*delay_ms - Verzögerungsschleife.*/ 
119
  void delay_ms(uint16_t ms) 
120
  {
121
        while ( ms ) 
122
        {
123
                _delay_ms(1);
124
                ms--;
125
        }
126
  }
127

128
/* Funktion um zu checken ob der Taster gedrückt wurde
129
   Gibt eine 1 zurück wenn der Taster gedrückt wurde ansonsten 0*/ 
130
  int button_is_pressed()
131
  {
132
        /* Der Taster ist gedrückt wenn er gegen Masse gezogen wird */
133
        if (bit_is_clear(BUTTON_PIN, BUTTON_BIT))
134
        {
135
                delay_ms(DEBOUNCE_TIME);
136
                
137
          if (bit_is_clear(BUTTON_PIN, BUTTON_BIT)) 
138
          return 1;
139
        }
140
        
141
        return 0;
142
  }
143

144
/*********************read_adc.c******************************/
145
#include <avr/interrupt.h>
146
#include <stdint.h>
147

148

149
int read_adc(void)
150
{
151

152
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Setze ADC prescaler von 128 - 125KHz sample rate @ 3,6864 Mhz
153

154
   ADMUX |= (1 << REFS0); // Setze ADC Vref auf externen Pin AVCC(4,6V)
155
   ADMUX |= (1 << ADLAR); // ADCH wird als erstes Nibble gestellt
156
   // Mux muss nicht eingestellt werden, da Pin 1 default  ist
157

158
   ADCSRA |= (1 << ADFR);  // Setze Free-Running Mode
159
   ADCSRA |= (1 << ADEN);  // Aktiviere ADC
160

161
   ADCSRA |= (1 << ADIE);  // Aktiviere ADC Interrupt
162
   sei();   //  Globalen Interrupt aktivieren
163

164
   ADCSRA |= (1 << ADSC);  // Starte A2D Conversion
165
   
166
  
167

168
   for(;;)  // Loop Forever
169
   {
170
     
171
   }
172

173
return(0);
174
}
#1564267
Lesenswert?

Tom Cee schrieb:
> Ich hab die Module einzeln getestet und etwas den Überblick verloren.

Fang als erstes damit, die überzähligen Leerzeilen rauszuwerfen.
Wenn du mehr als eine Leerzeile hintereinander machst um etwas 
abzusetzen, dann hat es sich der nächste Code-Abschnitt verdient, dass
  * er nur mit 1 Leerzeile eingeleitet wird
  * dafür aber ein Blockkommentar vor dem Block beschreibt, was
    an dieser Stelle im Code, global gesehen, passieren wird.


So was
1
#define TOGGLE(port,pin)  PORT ## port ^= (1<<pin)
2
#define READ(port,pin)   (PIN ## port & (1<<pin)) 
3

4

5

6

7
/*********************Funktions Prototypen*****************************************/
8

9

10
int button_is_pressed();
11
void delay_ms(uint16_t ms);
12
int button_is_pressed();
13
int read_adc(void);
14

15

16

17

18

19

20
/********************Stepper mit ADC.c*****************************/
21

22
#include <avr/interrupt.h>
23
#include <stdint.h>
24
#include "myheader.h"
25

26

27

28

29

30

31
volatile uint8_t reload=0;
32

33

34

35

36

37

38
int main (void)
39
{
40
     
41

42
    while (button_is_pressed(1))
43
        {
44
                
45
                  
46
              read_adc();
47
                 
48
                
49
        }
50
  
51
   
52
   
53
   
54
   
55
}

erhöht keine Übersicht, sindern verringert sie, weil es den Code 
unnötigerweise einfach nur in die Länge zieht und man so auf dem 
Bildschirm weniger Nutzinformation sieht.
1
#define TOGGLE(port,pin)  PORT ## port ^= (1<<pin)
2
#define READ(port,pin)   (PIN ## port & (1<<pin)) 
3

4
/*********************Funktions Prototypen*****************************************/
5
int button_is_pressed();
6
void delay_ms(uint16_t ms);
7
int button_is_pressed();
8
int read_adc(void);
9

10
/********************Stepper mit ADC.c*****************************/
11
#include <avr/interrupt.h>
12
#include <stdint.h>
13
#include "myheader.h"
14

15
volatile uint8_t reload=0;
16

17
int main (void)
18
{
19
  while (button_is_pressed(1))
20
  {
21
    read_adc();
22
  }
23
}

Hmm. Die übliche logische Sequenz in main ist doch eher die
1
int main()
2
{
3
  ... die benutzte Hardware initialisieren
4
  ... das bedeutet zb die DDR richtig setzen
5
  ... Pullups einschalten, falls gebraucht
6
  ... Timer richtig einstellen, etc, etc
7
  ... kurz und gut: die Vorraussetzungen schaffen
8
  ... das der Prozessor richtig konfiguriert ist um
9
  ... überhaupt mit der eigentlichen Arbeit anfangen
10
  ... zu können
11

12
  sei();    // falls Interrupts benutzt werden
13

14
  while( 1 ) {
15

16
    .. Programmlogik
17
    .. zb. Wenn eine Taste gedrückt wird, mach etwas
18

19
  }
20
}

Jetzt vergleich einmal deinen Ansatz für main() mit dem Grundschema und 
versuche da die Entsprechungen zu finden. Du wirst keine finden :-)
Hinweis: Auch wenn deine read_adc() Funktion suggeriert, dass dort der 
ADC ausgelesen wird, so tut sie das eigentlich nicht. Deine 'read_adc' 
ist eigentlich mehr eine Initialisierungsfunktion, die den ADC in den 
Arbeitsmodus schaltet. Initialisierungsfunktion -> hat in der 
Hauptschleife nichts verloren, sondern wird vor die Hauptschleife 
gesetzt. Auch sehe ich nirgends, wo zb die Voraussetzungen für den 
Taster schaffst, oder braucht du keinen Pullup?

Und nimm auch den sei() aus der read_adc raus. Der hat dort drinnen auch 
nichts verloren. Eine derartige wichtige Entscheidung, 'ab jetzt können 
Interrupts auslösen', legt man nicht in eine Funktion die nur die 
Aufgabe hat ein Gerät zu initialisieren. Diese Entscheidung, Interrupts 
"ja bitte" macht man nachdem alles initialisiert ist und bevor die 
while-Hauptschleife loslegt. Das kann aber eine einzelne 
Initialisierungsfunktion nicht für sich entscheiden. Nach dem ADC könnte 
ja zb der Timer drann sein, initialisiert zu werden.

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