Forum: Mikrocontroller und Digitale Elektronik Zweiter Timer zerschießt LCD Display


von Sepp M. (atmegneuling)


Lesenswert?

Hallo Forumsgemeinde,


Ich bin ein AVR Greenhorn, dass mit C und einem ATmega8 zur Zeit am 
experimentieren ist.

Mein Problem sieht zur Zeit wie folgt aus:

Ich arbeite mich in die Region der Timer vor.

Timer1 bekomme ich ohne weitere Probleme initialisiert und zum laufen. 
Mein Programm überprüfe ich mit einem LCD Display.

Ich habe in meinem Programm mehrere Taster mit eingebaut. Die 
Eingangspins, wo die Taster angeschlossen sind, sind auf Eingang 
geschaltet mit aktivierten Pullups. Der zweite Kontakt der Taster auf 
GND.

Ich frage sie dann wie folgt ab
1
if (bit_is_clear(PINC,5)) 
2
{
3
  Tue was;
4
}

Das Problem ist nun, dass die Taster in einem etwas größeren Programm 
absolut nicht auf Tasterdruck, mehr auf Zufall reagieren.

Aus diesem Grund wollte ich die Taster über Timer laufen lassen, sodass 
sie innerhalb von ca. 10-50 ms, also direkt auf Tastendruck reagieren

Wenn ich allerdings Timer 0 oder Timer 2 initialisiere, habe ich keine 
Anzeige mehr auf meinem LCD Display.
1
SIGNAL(SIG_SIG_OVERFLOW2)
2
{
3
TCNT2 = 244;    // Auf 1 ms
4
countTimer2++;
5
}
6
.
7
.
8
.
9
TCCR2 |= (1<<CS22);    // Prescaler von 64
10
TCNT2  = 244;      // Vorladen
11
TIMSK |= (1<<TOIE2);    // Interrupts aktivieren und damit Timer starten
12
sei();

Warum läuft dann mein LCD Display nicht mehr???
1
// LCD control cmmands 
2
#define LCD_CLEAR    0x01  // Display löschen
3
#define LCD_HOME    0x02  // Home Zeiger
4
#define LCD_ON      0x0C  // Zeiger auf On
5
#define LCD_OFF      0x08  // Display auf off
6
#define POS_01      0x80  // Zeile 1
7
#define POS_02      0xC0  // Zeile 2
8
// Definitionen der Ports
9
#define  LCDPORT      PORTD
10
#define  LCDDDR      DDRD
11
#define LCD_PIN_RS    0
12
#define LCD_PIN_E    3
13
#define LCD_PIN_D4    4
14
#define LCD_PIN_D5    5
15
#define LCD_PIN_D6    6
16
#define LCD_PIN_D7    7
17
18
#define  COMMAND      0
19
#define DATA      1
20
21
void toggle_enable_pin(void)
22
{
23
  sbi(LCDPORT, LCD_PIN_E); cbi(LCDPORT, LCD_PIN_E);  
24
}
25
26
void lcd_send(unsigned char type, unsigned char c)
27
{
28
  unsigned char sic_c;  
29
  
30
  // High nibble senden
31
  sic_c = c;                  // c Original speichern
32
  sic_c &= ~0x0f;                // Bit 0-3 setzen
33
  if (type==DATA) sic_c |= (1<<LCD_PIN_RS);  // RS auf 1 setzen
34
  LCDPORT = sic_c; toggle_enable_pin();    // High nibble senden
35
  
36
  // Low nibble senden
37
  sic_c = c;                  // c Original speichern
38
  sic_c = sic_c<<4;              // Nibbles austauschen
39
  sic_c &= ~0x0f;                // Bit 0-3 setzen
40
  if (type==DATA) sic_c |= (1<<LCD_PIN_RS);  // RS auf 1 setze
41
  LCDPORT = sic_c; toggle_enable_pin();    // Low nibble senden
42
  _delay_ms(5);                // Auf LCD Controller warten
43
}
44
45
// Curser setzen 
46
void lcd_set_cursor(uint8_t line, uint8_t col)
47
{ uint8_t i;
48
  switch (line) 
49
  { case 1: i=0x80+0x00+col; break;    // 1. Zeile
50
    case 2: i=0x80+0x40+col; break;    // 2. Zeile
51
    default: return;                   
52
  }
53
  lcd_send(COMMAND, i);
54
}
55
56
// String in LCD schreiben
57
void lcd_write(char *data)
58
{    while(*data) {lcd_send(DATA, *data); data++;}
59
}
60
61
// Initialisieren des LCD Controller
62
void lcd_init()
63
{
64
  // Ports setzen
65
  LCDPORT = 0x00;  LCDDDR  = 0xFF;
66
  _delay_ms(50); // Auf LCD warten
67
68
  // 4-bit Modus 
69
  sbi(LCDPORT, LCD_PIN_D5); cbi(LCDPORT, LCD_PIN_D4);
70
71
  // 4-Bit Modus starten 
72
  sbi(PORTD, LCD_PIN_E); cbi(PORTD, LCD_PIN_E); _delay_ms(5); 
73
74
  // 2 Zeilen, 4-Bit Modus
75
  lcd_send(COMMAND, 0x28);
76
  lcd_send(COMMAND, LCD_OFF);  lcd_send(COMMAND, LCD_CLEAR);
77
  lcd_send(COMMAND, 0x06);  lcd_send(COMMAND, LCD_ON);
78
}
Eine andere Möglichkeit, die ich mir überlegt habe ist, einen Pin 
abzufragen und sobald eine steigende Flanke an diesem Pin erfasst wird, 
dass daraufhin ein Interrupt ausgelöst wird und ich darauf dann 
reagieren kann.

Ich hoffe ihr könnt mir in Sachen zweiter Timer, sodass mein LCD Display 
noch läuft und das Tasterproblem ein wenig weiterhelfen.

Vielen Dank schon mal im vorraus

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Die Timer startest du aber erst nach der LCD-Initialisierung ?
LCD und Taster teilen sich den gleichen Port ?
Was macht die Interrupt-Routine von Timer 0 ?

von Sepp M. (atmegneuling)


Lesenswert?

Nein, darauf habe ich nicht geachtet!!! Darf ich Timer erst nach dem LCD 
Display initialisieren???

Nein, das LCD Display ist an Port D und die Taster an Port C

Die sieht wie bei Timer 2 aus, oder was meinst du??

von Thomas E. (thomase)


Lesenswert?

> SIGNAL(SIG_SIG_OVERFLOW2)
Den Vektor gibt es nicht. Deswegen führt das Programm beim Auftreten des 
ersten Interrupts einen (Software-)Reset aus.

1. heisst der Vektor SIG_OVERFLOW2
2. hat der Compiler dir mitgeteilt, daß er deinen Vektor nicht kennt
3. sind Warnings nicht zum ignorieren da
4. ist diese Bezeichnung obsolet. Sondern man benutzt 
ISR(TIMER2_OVF_vect)

mfg.

: Bearbeitet durch User
von Sepp M. (atmegneuling)


Lesenswert?

Nee der Compiler hat nicht gemeckert, noch nicht mal ein Warning 
ausgegeben....

.....ich versuche das ganze jetzt mal mit ISR und dann erstatte ich 
Bericht

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Mal nebenbei: Es ehrt dich ja, das du das Rad neu erfinden möchtest, 
aber ist es wirklich sinnvoll, auf das gesammelte Wissen, das z.B. in 
Peter Fleurys LCD Library eingebaut ist, zu verzichten und stattdessen 
das alles neu zu erfinden (mit dem Potential auf alle möglichen 
Seiteneffekte)?

http://homepage.hispeed.ch/peterfleury/avr-software.html#libs

Auch die Tastenabfrage ist nach PeDas Entprellroutinen eigentlich 
erschlagen:
http://www.mikrocontroller.net/articles/Entprellung

Gerade als Anfänger ist es hilfreich, anderen über die Schulter zu 
schauen.

von Sepp M. (atmegneuling)


Lesenswert?

Gleicher Bild,

mit ISR (Timer.....) zeigt das Display nur die erste Reihe komplett 
schwarz an

von Sepp M. (atmegneuling)


Lesenswert?

Danke schön, ich schaue es mir gleich mal an....


Naja, das Rad vielleicht nicht wieder neu erfinden, aber man sollte das 
auch verstehen was man macht und das bekommt man durch nur kopieren 
nicht hin .....

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Sepp Mayer schrieb:
1
> void toggle_enable_pin(void)
2
> {
3
>   sbi(LCDPORT, LCD_PIN_E); cbi(LCDPORT, LCD_PIN_E);
4
> }
Das ist sehr fehlerträchtig. Wenn du dir mal das Datenblatt des HD44780 
anschaust, siehst du, das die Enable Zykluszeit 1000ns ist, d.h. 1µs. Du 
erwähnst nirgends den Takt deines MC, aber wenn der z.B. 8 MHz ist, dann 
erzeugst du mit der o.a. Routine gerade mal einen Puls von ca. 0,125 µs. 
Das kriegt das LCD natürlich nicht mit.

Sepp Mayer schrieb:
> aber man sollte das
> auch verstehen was man macht und das bekommt man durch nur kopieren
> nicht hin

Ja, aber dann doch gleich richtig. Du kopierst ja nicht nur, du kannst 
es dir ja auch anschauen, verstehen, adaptieren - vllt. sogar 
verbessern. Die Routinen sind tausendfach bewährt und zumindest Peter 
Fleurys Lib ist soweit ich sie schon gequält habe, einfach wasserdicht.

: Bearbeitet durch User
von Sepp M. (atmegneuling)


Lesenswert?

Ja ich betreibe ihn mit 8 MHz.....allerdings funktioniert das Ganze mit 
Timer1 ohne Probleme....

....sobald ich einen anderen Timer initialisiere gibt das LCD nur 
schwarz aus in der ersten Zeile

von Sean G. (atmega318)


Lesenswert?

Ich habe mir deinen Code jetzt nicht ganz durchgelesen, aber vielleicht 
hilft dir das trotzdem:
Ich hatte ein ähnliches Problem, bei dem ein Display nicht mehr 
funktionierte, sobald ich Timer / andere Interruptquellen benutzte. Die 
Lösung war dann ein atomares Ausführen des Display Codes, welche 
verhindert, dass ein Interrupt die Ausgabefolge zum Display zerschiesst.
Also versuche doch einfach mal mit einem

cli();
*display-update-code
sei();

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.