Displayausgabe langsam trotz 16Mhz

Gast #1661745
Lesenswert?

Hallo Leute...

Ich habe testweise ein Programm geschrieben welches mir die Zeit anzeigt 
wie lange eine Taste gedrückt ist. Hintergrund ist, ich möchte die 
Durchflussmenge einer Pumpe messen. Drücke ich den Starttaster rennt die 
Pumpe und mein Timer los. Lasse ich die Taste los stoppt der Timer und 
die Zeit wird im Display angezeigt.
Die Pumpe wird über nen Zweiten Timer im FastPWM-Modus angesteuert.

Was ich aber nicht verstehe, ich kann dem LCD zusehen wie es Zeichen für 
Zeichen schreibt. Ist also extremst lahm das ganze. Mein Controller 
läuft mit 16Mhz und ist ein ATmega32.

Bevor die Displayausgabe erfolgt, wird der Timer für die Zeitmessung 
angehalten, der PWM Timer läuft zu dieser Zeit aber noch.
Mir ist aufgefallen, wenn ich den PWM-Timer erst garnicht initialisieren 
und dann meine Zeit messe, erfolgt die Ausgabe minimal schneller. Aber 
das kann doch eig. garnicht damit zusammenhängen oder? Der Timer läuft 
ja hardwareseitig?

Hat da jemand eine Idee zu?
Achso... Programm in C geschrieben.

Danke schonmal.
Gast #1661765
Lesenswert?

Rush. schrieb:
> Ich habe testweise ein Programm geschrieben

Hallo Rush.

wenn du den Inhalt von diesem Programm für dich
behältst, kann dir hier niemand wirklich helfen.
Als lüfte dieses Geheimnis für uns alle.

A.L.U.
Gast #1661771
Lesenswert?

Ist ja gut ist ja gut :-D
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "lcd-routines.h"
4
#include <stdlib.h>
5

6
extern void lcd_data(unsigned char temp1);
7
extern void lcd_command(unsigned char temp1);
8
extern void lcd_enable(void);
9
extern void lcd_init(void);
10
extern void lcd_home(void);
11
extern void lcd_clear(void);
12
extern void set_cursor(uint8_t x, uint8_t y);
13
extern void lcd_string(char *data);
14

15
volatile int i=0;
16
volatile float ms=0;
17

18
void init_io(void)
19
{
20
  DDRD = 0b00010010;      //PD4 Ausgang
21
  PORTD &=~ (1<<PB1);
22
  DDRB = 0;
23
  PORTB = 255;
24
  
25
}
26

27
void init_pwm(void)
28
{
29
/*  TCCR1B-Registeraufbau   ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
30
  
31
  CS12 CS11 CS10 Description
32
   0    0    0    No clock source (Timer/Counter stopped).
33
   0    0    1    clkI/O/1 (No prescaling)
34
   0    1    0    clkI/O/8 (From prescaler)
35
   0    1    1    clkI/O/64 (From prescaler)
36
   1    0    0    clkI/O/256 (From prescaler)
37
   1    0    1    clkI/O/1024 (From prescaler)
38

39
  TCCR1A-Registeraufbau   COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
40

41
   COM1A1/COM1B1 COM1A0/COM1B0 Description
42
         0             0        Normal port operation, OC1A/OC1B disconnected.
43
         0             1        WGM13:0 = 15: Toggle OC1A on Compare Match, OC1B disconnected (normal port operation).
44
                                For all other WGM13:0 settings, normal port operation, OC1A/OC1B disconnected.
45
         1             0        Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM, (non-inverting mode)
46
         1             1        Set OC1A/OC1B on compare match, clear OC1A/OC1B at BOTTOM, (inverting mode)
47
  */
48
 
49
  TCCR1A |= (1<<COM1B1) | (1<<COM1B0) | (1<<WGM11) | (1<<WGM10);  // 10 Bit FastPWM - clear at bottom, set on compare match  invertiert
50
  TCCR1B |= (1<<WGM12) | (1<<CS11) | (1<<CS10);
51
}
52

53
void init_timer0(void)
54
{
55
  OCR0 = 63;                  // ((16000000Hz/256)/1000Hz) = 62,5 für 1ms
56
  TIMSK = (1<<OCIE0);              // enable interrupts on compare match
57
}
58

59
void activate_timer0(void)
60
{
61
  TCCR0 = (1<<WGM01) | (1<<CS02);  //prescaler 256; CTC-Mode
62
  sei();
63
}
64

65
void deactivate_timer0(void)
66
{
67
  cli();
68
  TCCR0 = (0<<CS02) | (0<<CS01) | (0<<CS00);  //prescaler 1024; CTC-Mode
69
}
70

71
void rst_timer0(void)
72
{
73
  ms = 0;
74
  i = 0;
75
}
76

77
void ShowTime(void)
78
{
79
  unsigned char milliseconds[6];
80
  lcd_clear();
81
  set_cursor(0,0);
82
  ms = ms / 1000;
83
  dtostrf(ms, 3,3, milliseconds);
84
  lcd_string(milliseconds);
85
}
86

87
ISR(TIMER0_COMP_vect)
88
{
89
  cli();
90
  if (i < 50)
91
    {
92
    i++;
93
  }
94
  else
95
  {
96
     ms++;
97
  }
98
  sei();
99
}
100

101
int main(void)
102
{
103
  init_io();
104
  init_pwm();
105
  lcd_init();
106
  init_timer0();
107
  lcd_clear();
108
  set_cursor(0,0);
109
  sei();
110

111
  while (1)
112
  {
113
    if ( !(PINB & (1<<PINB0)) )
114
  {
115
    activate_timer0();          // Timer aktivieren
116
    while (i < 50) {}              // warten bis Taster vollständig gedrückt - Prellen unterdrücken
117
      OCR1B = 1023;              // DC 1,0    13,8 V
118
    while ( !(PINB & (1<<PINB0)) ) {}
119
    deactivate_timer0();
120
    OCR1B = 0;
121
    ShowTime();
122
      rst_timer0();
123
  }
124

125
  while ( !(PINB & (1<<PINB2)) )
126
  {
127
    activate_timer0();          // Timer aktivieren
128
    while (i < 50) {}              // warten bis Taster vollständig gedrückt - Prellen unterdrücken
129
    OCR1B = 819;              // DC ~0,8   11,03 V
130
    while ( !(PINB & (1<<PINB0)) ) {}
131
    deactivate_timer0();
132
    ShowTime();
133
      rst_timer0();
134
  }
135

136
  while ( !(PINB & (1<<PINB4)) )
137
  {
138
    activate_timer0();          // Timer aktivieren
139
    while (i < 50) {}              // warten bis Taster vollständig gedrückt - Prellen unterdrücken
140
    OCR1B = 615;              // DC ~0,6   8,29 V
141
    while ( !(PINB & (1<<PINB0)) ) {}
142
    deactivate_timer0();
143
    ShowTime();
144
      rst_timer0();
145
  }
146

147
  while ( !(PINB & (1<<PINB6)) )
148
  {
149
    activate_timer0();          // Timer aktivieren
150
    while (i < 50) {}              // warten bis Taster vollständig gedrückt - Prellen unterdrücken
151
    OCR1B = 411;              // DC ~0,4   5,54 V
152
    while ( !(PINB & (1<<PINB0)) ) {}
153
    deactivate_timer0();
154
    ShowTime();
155
      rst_timer0();
156
  }
157

158
  while ( !(PINB & (1<<PINB1)) )
159
  {
160
    activate_timer0();          // Timer aktivieren
161
    while (i < 50) {}              // warten bis Taster vollständig gedrückt - Prellen unterdrücken
162
    OCR1B = 207;              // DC ~0,2   2,79 V
163
    while ( !(PINB & (1<<PINB0)) ) {}
164
    deactivate_timer0();
165
    ShowTime();
166
      rst_timer0();
167
  }
168

169
  OCR1B = 0;
170
  }
171
  return 0;
172
}
Gast #1661787
Lesenswert?

Rush. schrieb:
> ISR(TIMER0_COMP_vect)
> {
>   cli();
>   if (i < 50)
>     {
>     i++;
>   }
>   else
>   {
>      ms++;
>   }
>   sei();
> }

unnötig in der ISR cli/sei zu verwenden. evtl kostest das ewige 
ein/ausgeschalte cpu-zeit.
Gast #1661793
Lesenswert?

vergesst das sei/cli. Ohne hatte ich das selbe Problem, deshalb hab ich 
es testweise mit reingeschrieben.

@Gleicher Tag
Was meinst du mit blockierend?

Klär mich mal bitte auf, stehe sogesehen noch im Anfangsstadium der 
uC-Programmierung.
Gast #1661802
Lesenswert?

Hi

>vergesst das sei/cli. Ohne hatte ich das selbe Problem, deshalb hab ich
>es testweise mit reingeschrieben.

Du schaltest aber bei einem

>void deactivate_timerXY(void)

auch alle Interrupts ab. Ist das gewollt?

MfG Spess
Gast #1661808
Lesenswert?

@spess53
Ja das ist gewollt mit den Interrupts. Benutze ja nur einen einzigen zum 
Zählen der Millisekunden. Und den brauche ich ja nicht mehr wenn der 
Taster losgelassen wurde.

@Joe
Ne, der Takt ist auf externen Quarz eingestellt.
Gast #1661810
Lesenswert?

@ rush. ist das display nur lahm wenn du deine  starttaste drückst?

wenn das so ist blockiert evtl deine entrellschleife?.
dann vielleicht den tasterzusatnd über die ISR mit abwicklen? bin auch 
erst neu dabei, von daher ne vermutung?

(hab mal zum test mehrer tasten  über die timer ISR "mit" abgefragt. 
klappt wunderbar, inkl timerausgabe LCD)
#1661826
Lesenswert?

Als Anfaenger schreibt man ein Programm gewoehnlich blockierend. Das 
bedeutet, das Programm steht immer an einer definierten Stelle und 
wartet auf genau ein Ereignis, und tut waehrend dieser (Warte-)Zeit 
nichts.
Der Zeitablauf ist genau vorgegeben.

Als Fortgeschrittener schreibt man nicht mehr blockierend. Man reagiert 
auf ein Ereignis wenn es auftritt, und wartet nicht mehr. Der Zeitablauf 
ist nicht mehr genau vorgegeben. Falls ein Ablauf eingehalten werden 
muss, so bedient man sich einer Statusmaschine.

Toent etwas theoretisch. ja.
Gast #1661847
Lesenswert?

Die Taktfrequenz kann entweder in der lcd-routines.h eingetragen werden 
ober aber im Avr-Studio unter den Projektoptionen. Dort stehen die 16Mhz 
drin. Dieser Eintrag bezieht sich ja auf das komplette Projekt. Schreibe 
ich es zusätzlich in die lcd-routines.h kommt erstens ne warnmeldung vom 
compiler "F_CPU redefined in...." und zweitens ändert es an meinem 
Problem trotzdem nichts.
Gast #1661863
Lesenswert?

So, eben einfach mal das hier geschrieben:
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3

4
extern void lcd_data(unsigned char temp1);
5
extern void lcd_command(unsigned char temp1);
6
extern void lcd_enable(void);
7
extern void lcd_init(void);
8
extern void lcd_home(void);
9
extern void lcd_clear(void);
10
extern void set_cursor(uint8_t x, uint8_t y);
11
extern void lcd_string(char *data);
12
extern void lcd_led(uint8_t a);
13

14

15

16
int main(void)
17
{
18
lcd_init();
19

20
lcd_string("alsdjadsf");
21
}

und es ist immer noch so lahm.
Einen anderen Port habe ich eben auch mal versucht, das selbe :-(
Gast #1661868
Lesenswert?

Rush. schrieb:
> extern void lcd_data(unsigned char temp1);
> extern void lcd_command(unsigned char temp1);
> extern void lcd_enable(void);
> extern void lcd_init(void);
> extern void lcd_home(void);
> extern void lcd_clear(void);
> extern void set_cursor(uint8_t x, uint8_t y);
> extern void lcd_string(char *data);
> extern void lcd_led(uint8_t a);

ich weiss eigentlich garnicht warum das alles da rein muss...

wenn ich lcd routines verlinke brauch ich garnichts davon
Gast #1661884
Lesenswert?

Hab den Takt mal auf den default von 1Mhz gestellt und die 
Projektoptionen angepasst. Das selbe!

@swen

Gute Frage ob ich das brauche oder nicht. In früheren Verisonen vom 
avr-gcc hat er mir immer ne Fehlermeldung ausgespuckt. Ein Freund hat 
mir dann geraten das extern immer mit reinzunehmen damit der Compiler 
von vorn herein weiss das die Funktionen eben extern liegen.
Habs jetzt rausgenommen und das LCD geht trotzdem, aber langsam eben :-(
Gast #1661886
Lesenswert?

hat das lcd jemals "schnell" angezeigt? nich das hier der "wurm liegt". 
evtl haste ja noch nen zweiten controller zum probieren. nur um das 
unvorstellbare auszuschließen. weil dann wäre ich auch mit meinem latein 
am ende
Gast #1661896
Lesenswert?

Ja das hat die ganze Zeit normal funktioniert.
Aber ich werds nochmal auf einem anderen Controller probieren. Hab nur 
gerade keinen anderen parat.
Aber werde dann meine Erkenntnisse posten.
Danke schonmal für eure Bemühungen.
#1661945
Lesenswert?

@ Rush. (Gast)

Kleiner Tip: Netiquette. Lange Quelltexte gehören in den Anhang. Und 
es wäre sinnvoll, den AVR-Typ zu nennen.

Wenn dein AVR so schnarchlangsam ist, kann es sein dass er mit dem 
Watchdogtimer mit 128 kHz läuft, das geht bei einigen AVRs. Oder du hast 
das define F_CPU in Makefile oder den Projektoptionen im AVR-Studio 
falsch eingestellt. Hast du jeweils neu compiliert und auch neu 
programmiert?

Zum Thema nichtblockierende Programmierung siehe Multitasking.

MfG
Falk
Gast #1661969
Lesenswert?

@ Falk

Falk Brunner schrieb:
> Kleiner Tip: Netiquette. Lange Quelltexte gehören in den Anhang. Und
> es wäre sinnvoll, den AVR-Typ zu nennen.

Wenn du schon von Netiquette sprichst solltes du dich selber dran halten 
und wenigstens das erste Posting überfliegen:

Rush. schrieb:
> Mein Controller
> läuft mit 16Mhz und ist ein ATmega32.

Wie wenn ATmega32 nichts aussagen würde...
#1661976
Lesenswert?

@  Michael (Gast)

>Wie wenn ATmega32 nichts aussagen würde...

Das hab ich dann wohl übersehen. Entschuldigung.

@Rush

Ob die Takteinstellung passt kann man leicht mit folgendem Programm 
prüfen.

1
#include <avr/io.h>
2
#define F_CPU 16000000
3
#include <util/delay.h>
4

5
int main(void) {
6
    int i;
7
    
8
    DDRA = 1;    // ein Port mit ner LED dran     
9

10
    while (1) {
11
        for (i=0; i<1000; i++) _delay_ms(1);
12
        PORTA ^= 1; 
13
    }
14
}

Du musst natürlich das Programm an deine Pinbelegung anpasssen. Wenn die 
LED im Sekundentakt blinkt ist deine Oszillatoreinstellung OK.

MFG
Falk
Gast #1662037
Lesenswert?

@Michael

Das Timing meines Programms passt da ich ja wie schon am Anfang 
geschrieben die Dauer des gedrückten Tasters messe und diese auch 
korrekt am display angezeigt wird.

Im Anhang meine Fuses und die Optionen aus dem AVR-Studio als 
Screenshot.

@ Falk Brunner

Ich habe den Watchdog doch im Code nirgends initialisiert, also läuft er 
doch garnicht oder?
Angehängte Dateien:
#1662080
Lesenswert?

@  Rush. (Gast)

>Im Anhang meine Fuses und die Optionen aus dem AVR-Studio als
>Screenshot.

Das passt alles.

>Ich habe den Watchdog doch im Code nirgends initialisiert, also läuft er
>doch garnicht oder?

Das ist was anderes. Bei einigen AVRs kann man den Watchdogoszillator 
als Taktquelle auswählen, aber nicht beim Mega32.

MfG
Falk
Gast #1662125
Lesenswert?

Da haben wirs ja schon;)

// erzeugt den Enable-Puls
void lcd_enable(void)
{
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers 
einfügen
   // Beitrag "Re: Bitte helft mir. Schon wieder AtMega16"
   LCD_PORT |= (1<<LCD_EN);
    _delay_ms(90);                   // kurze Pause
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers 
verlängern
   // Beitrag "LCD -> Probleme mit Optimierungsgrad"
   LCD_PORT &= ~(1<<LCD_EN);
}


90ms für Enable ist schon etwas viel.
Gast #1662140
Lesenswert?

}

// erzeugt den Enable-Puls
void lcd_enable(void)
{
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers 
einfügen
   // Beitrag "Re: Bitte helft mir. Schon wieder AtMega16"
   LCD_PORT |= (1<<LCD_EN);
    _delay_us(1);                   // kurze Pause
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers 
verlängern
   // Beitrag "LCD -> Probleme mit Optimierungsgrad"
   LCD_PORT &= ~(1<<LCD_EN);
}

bei ihr isses 1us!

check ma!
Gast #1662149
Lesenswert?

Jup 1us tuts bei mir auch. Ich kann mich grob erinnern dass ich mit dem 
Wert mal rumgespielt hatte weil ich mal ein LCD hatte wo es mit 1us 
nicht lief.

So gehts einem wenn man die libs von projekt zu projekt kopiert ;-) 
Demnächst weiss ich bescheid....

Und ja, in dieser Community gehts vorwärts. Hier schreiben die leute 
schneller zurück als Freunde aus dem ICQ :-D

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