Forum: Mikrocontroller und Digitale Elektronik Problem mit ATMega16


von daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
der AtMega16 gibt am Port C folgendes Bitmuster 00101100 aus. Versteh 
nicht warum. In meinem Program wird am PortC ueberhaupt nix gemacht.

Controller laeuft auf 8 MHz interner RC.
1
#include <avr/io.h>
2
#include <d:\projekt\lcdtest\T6963.h>
3
4
char string[10] = "Test";
5
unsigned char LCD_CMD;          // Command-Byte
6
unsigned char LCD_STATUS;       // Status-Byte
7
unsigned char LCD_DATA;         // Daten-Byte
8
char state;
9
10
int main()
11
{
12
  DDRD |= 0x08;
13
  state = 0;
14
  while (1)
15
  {
16
  PORTD = 0x08;
17
  LCD_CTRL_DDR |= 0x0F;
18
        DATA_DIR_IN();          // Port A als Eingang
19
        LCD_CD_H();             // Commando High
20
        LCD_RD_L();             // Read Low
21
        LCD_CE_L();             // Chip Enable Low
22
        LCD_STATUS = LCD_READ;  // Status lesen
23
        LCD_CE_H();             // Chip Enable High
24
        LCD_RD_H();             // Read High
25
        LCD_STATUS &= (0x03);   // Bits ausmaskieren
26
27
  }
28
  return 0;
29
}
30
31
t6963.h:
32
33
#define LCD_CTRL  PORTB              // Steuerport LCD
34
#define LCD_CTRL_DDR   DDRB          // Data Direction of Control Port
35
36
#define LCD_WR_H()     LCD_CTRL |=  _BV(LCD_WR)  // = 1
37
#define LCD_WR_L()      LCD_CTRL &= ~_BV(LCD_WR)  // = 0
38
#define LCD_RD_H()     LCD_CTRL |=  _BV(LCD_RD)
39
#define LCD_RD_L()      LCD_CTRL &= ~_BV(LCD_RD)
40
#define LCD_CE_H()     LCD_CTRL |=  _BV(LCD_CE)
41
#define LCD_CE_L()      LCD_CTRL &= ~_BV(LCD_CE)
42
#define LCD_CD_H()     LCD_CTRL |=  _BV(LCD_CD)
43
#define LCD_CD_L()      LCD_CTRL &= ~_BV(LCD_CD)
44
#define LCD_RST_H()     LCD_CTRL |=  _BV(LCD_RST)
45
#define LCD_RST_L()      LCD_CTRL &= ~_BV(LCD_RST)
an PD3 haengt eine LED die auch leuchtet. muesste heissen der macht 
schon was. nur was?

ausserdem habe ich eine externe Beschaltung der Pins um beim Tasterdruck 
einen positiven Pegel zu erzeugen. siehe Schematic.
Vielleicht kann mir jemand sagen wo das Problem liegen koennte, 
vielleicht hat auch der Controller ein Schuss weg.

Vielen Dank
Daniel

von Uwe .. (uwegw)


Lesenswert?

JTAG abschalten!

von mehrfacher STK500-Besitzer (Gast)


Lesenswert?

Guck mal nach der JTAG-Fuse!

von daniel (Gast)


Lesenswert?

daran kanns wohl liegen :)
die war noch an, wusste aber auch nicht ob es noetig ist die 
auszuschalten. Vielen Dank fuer die schnellen Antworten.
steh nun bei der testung mit den eingaengen, funzt aber auch nicht so 
richtig. Moechte die als Tristate Hi-Z verwenden.
1
int main()
2
{
3
  DDRD |= 0x08; // LED PD3 output
4
  PORTD = 0x0B; // PD0..PD1 input tristate PD3, PD3 on - LED an
5
  state = 0;
6
  while (1)
7
       {
8
.
9
. selbe wie oben
10
.
11
        if ((PORTD & 0x01)== 0x01) PORTD = 0x08;
12
  if ((PORTD & 0x02)== 0x02) PORTD = 0x00;
13
  }
14
  return 0;
15
}
die Tasten generieren VCC über 100 Ohm zum Portpin vom Pin mit 10k gegen 
Masse. Entprellt muessen die nicht sein, geht ja nur um an oder aus.
LED will aber nicht ausgehen.
Weiss da jemand Rat?

Vielen Dank
Daniel

von Karl H. (kbuchegg)


Lesenswert?

> die Tasten generieren VCC über 100 Ohm zum Portpin vom Pin mit 10k gegen
> Masse.

Hä?
Kannst du das mal aufmalen?

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger wrote:
>> die Tasten generieren VCC über 100 Ohm zum Portpin vom Pin mit 10k gegen
>> Masse.
>
> Hä?
> Kannst du das mal aufmalen?

Seh gerade, dass du im Eröffnungsposting einen Schaltplan
hast.

Wenn du die Widerstände drinnen lässt, solltest du die
internen Pull Up Widerstände nicht einschalten. Der interne
Pullup bildet sonst mit dem externen 10k Widerstand einen
Spannungsteiler, so dass dein Pin niemals auf GND runterfallen
kann.

Einfacher wäre es aber, wenn du die externen Widerstände
einfach rausschmeist, du brauchst sie nicht.

Einen Taster kann man ganz einfach so anschliessen:



    PD0 o-------------+
                      |
                    \
                     \
                      |
          ------------+-------o  GND

Den internen Pullup an diesem Pin aktivieren. Fertig.
Die Taster sind dann allerdings low-aktiv. Im nicht gedrückten
Zustand kriegst du eine 1, wird der Taster gedrückt kriegst
du eine 0

von daniel (Gast)


Lesenswert?

Der Pullup duerfte aber nicht aktiv sein, wenn DDRD0:1 = 0 und PORTD0:1 
= 0. Somit waeren laut Datenblatt S. 52 die Pins im Tristate Hi - Z 
Mode.
Werds mal probieren. Muesste doch dann endlich die LED ausgehen bei PD2 
= 1 laut programm.

naja ich mache mir sorgen wegen den Stoereinkoplungen dachte mir 
vielleicht ist so eine Beschaltung besser. Ich weiss das man low aktive 
Taste über Pull-Up leichter verwenden kann. Aber ich habe so leitungen 
von 30 cm und weiss nicht wie das mit Störeinkopplungen sein wird.


vielen Dank
DAniel

von Karl H. (kbuchegg)


Lesenswert?

daniel wrote:
> Der Pullup duerfte aber nicht aktiv sein, wenn DDRD0:1 = 0 und PORTD0:1
> = 0. Somit waeren laut Datenblatt S. 52 die Pins im Tristate Hi - Z
> Mode.

Moment.

Du setzt

  DDRD |= 0x08;

also  00001000
also PD0 und PD1 auf Eingang

  PORTD = 0x0B;

0x0B ist binär  00001011

Doch. Die Pullups an PD0 und PD1 sind aktiv

von daniel (Gast)


Lesenswert?

funktioniert aber trotzdem nicht, naja sicher mein Fehler :)

hier das funktioniert wunderschoen. Klassischer Polling Loop ohne Timer. 
:)
1
void Init()
2
{
3
  // Port definitions
4
  SFIOR |= 0x00;  // PullUps on
5
  PORTD = 0x03; // Tristate PD0..PD1
6
  DDRD = 0x08;  // Output PD3
7
  PORTD = 0x08;
8
  DDRA = 0xFF;
9
10
  // Timer Init
11
  
12
13
  // Variable Inits
14
  cntr = 65535;
15
}
16
17
18
int main()
19
{
20
  Init();
21
  while (1)
22
  {
23
  while (cntr) cntr--;
24
  cntr = 65535;
25
  PORTA ^= _BV(PA3);
26
  if (Taste1) {
27
  PORTD = 0x00; State = 0;}
28
  if (Taste2) 
29
  {
30
  State = 1; PORTD = 0x08;
31
  }
32
  }
33
  return 0;
34
}

von Karl H. (kbuchegg)


Lesenswert?

daniel wrote:

> naja ich mache mir sorgen wegen den Stoereinkoplungen

Brauchst du nicht.
Der Eingang ist ja niemals offen. Er ist entweder über den Taster
direkt mit GND verbunden oder über den internen Pullup mit Vcc.
Ergo: Du hast immer ein definiertes Potential, egal ob der Taster
geöffnet oder geschlossen ist.

Was anderes wäre es, wenn du den Pullup wegschaltest. Dann wäre
der Eingang bei nicht gedrücktem Taster tatsächlich offen und
du müsstest dir Sorgen um Störungen machen.

> vielleicht ist so eine Beschaltung besser. Ich weiss das man low aktive
> Taste über Pull-Up leichter verwenden kann. Aber ich habe so leitungen
> von 30 cm und weiss nicht wie das mit Störeinkopplungen sein wird.

30 cm sind kein Problem.
Einfach Taster drann, internen Pullup ein und loslegen.

von Karl H. (kbuchegg)


Lesenswert?

> 1)   PORTD = 0x03; // Tristate PD0..PD1
> 2)   DDRD = 0x08;  // Output PD3
> 3)   PORTD = 0x08;

In Zeile 1) schaltest du die Pullups ein.
In 2) schaltest du den einen Portpin auf Ausgang
in Zeile 3) schaltest du die Pullups wieder aus.


Jede Zuweisung an PORTB muss berücksichtigen, dass die
Bits 0 und 1 auf 1 sein muessen.

Du kannst Probleme vermeiden, indem du das Setzen eines
Bits an einem Port so machst:

   PORTB |= 0x08;

und demenstprechend ein einzelnes Bit löschen:

   PORTB &= ~0x08;

oder noch besser (da klarer wird, welches Bit ein oder
ausgeschaltet wird:

  PORTB |= ( 1 << PB3 );   // setze PB3
  PORTB &= ~( 1 << PB3 );  // lösche PB3

von daniel (Gast)


Lesenswert?

trickreich :) so geht aber :)
1
int main()
2
{
3
  PORTD = 0x03;   // Tristate aktiv
4
  DDRD  = 0x08;   // output
5
  PORTD = 0x08;   // output aktiv, tristate aktiv
6
  PORTA = 0xFF;   // tristate aktiv
7
  DDRA = 0x00;    // output
8
  PORTA = 0x00;   // tristate aktiv
9
  state = 0;
10
  while (1)
11
  {
12
      LCD_STATUS = 0;
13
      LCD_CTRL_DDR |= 0x0F;
14
        DATA_DIR_IN();          // Port A als Eingang
15
        LCD_CD_H();             // Commando High
16
        LCD_RD_L();             // Read Low
17
        LCD_CE_L();             // Chip Enable Low
18
        LCD_STATUS = LCD_READ;  // Status lesen
19
        LCD_CE_H();             // Chip Enable High
20
        LCD_RD_H();             // Read High
21
        LCD_STATUS &= (0x03);   // Bits ausmaskieren
22
      if ((PORTD & 0x01)== 0x01) PORTD = 0x08;
23
      if ((PORTD & 0x02)== 0x02) PORTD = 0x00;
24
      if (LCD_STATUS == 3) PORTD = 0x08;
25
  }
26
  return 0;
27
}

Vielen dank, kann nun endlich loslegen mit hoeherem wo die Grundlagen 
geklaert sind ;)
Daniel

von daniel (Gast)


Lesenswert?

Vielen Dank fuer die Tips, hatte den Post noch nicht endeckt.
Du machst das echt super hier Karl Heinz Buchegger! Dickes Lob von mir. 
Hatte hier schon einige Threads und du hast mir immer gute Tips gegeben.
Danke :)

Daniel

von Karl H. (kbuchegg)


Lesenswert?

??Verwirrt??
Inzwischen weiss ich nicht mehr, welches Programm denn
nun gilt und welches Probleme macht.

Also:
Gehen wir mal von der Situation aus:
Taster sind ohne irgendwelche Widerstände direkt an
den Prozessorpins am Port D angeschlossen.
Taster D0
Taster D0
Led    D3   (Led ist über Widerstand nach Vcc geschaltet.

Dann folgendes Proramm:
1
#include <avr/io.h>
2
3
int main()
4
{
5
  DDRD  = 0x08;    // PD3 auf Ausgang, alles andere auf Eingang
6
  PORTD = 0x0B;    // PD3 auf 1, Pullup an PD0 und PD1 ein
7
8
  while( 1 ) {
9
10
    if( ( PIND & 0x01 ) == 0x01 ) {    // PD0 gedrückt?
11
      PORTD &= ~( 1 << PD3 );          // Led ein (PD3 auf 0)
12
    }
13
14
    if( ( PIND & 0x02 ) == 0x02 ) {    // PD1 gedrückt?
15
      PORTD |= ( 1 << PD3 );           // Led aus (PD3 auf 1)
16
    }
17
  }
18
}

von Karl H. (kbuchegg)


Lesenswert?

Hast du die externen Widerstände noch drann?

von daniel (Gast)


Lesenswert?

und noch ein Fehler entdeckt, natuerlich werden die Tasten ja nie 
eingelesen kann man druecken wie man will. die Info steht am im PIND 
nicht im PORTD?!
nur so zur Info, fuer die die verstehen wollen was man alles fuer 
Fehlerchen machen kann.
Daniel

von daniel (Gast)


Lesenswert?

ja die sind noch dran, hab hier keine Loetkolben. aber geht ja auch mit 
wenn ich das mit dem Pull Up beachte.

von daniel (Gast)


Lesenswert?

naja das sind alles die Vorbetrachtungen zur Ansteuerung eines 
Grafikdisplay (T6963), aber da muss das mit den In/Outs erstmal 
knallhart sitzen. Deswegen die fielen verschiedenen Programme.
Es sind zwei Programmchen, bei dem einem wirken nur beide Taste und die 
LED.
Bei dem anderen wird das Statuswort am PINA des Displays abgefragt,die 
Comands werden am PORTB0..3 gesendet. Die LED leuchtet dauerhaft, ist 
das Statuswort korrekt soll die LED ausgehen.Taster wirken nur zur 
kontroller und  steuerung der LED auf AN/AUS. Leiderns geht die LED nie 
aus, das Statuswort (0x03)kommt nie an. Aber das hat sicher andere 
Ursachen, wichtiger erst mal das mit den Input Outputs verstehen.
Prog1
1
void Init()
2
{
3
  // Port definitions
4
  SFIOR |= 0x00;  // PullUps on
5
  PORTD = 0x03; // Tristate PD0..PD1
6
  DDRD = 0x08;  // Output PD3
7
  PORTD = 0x08;
8
  DDRA = 0xFF;
9
10
  // Timer Init
11
  
12
13
  // Variable Inits
14
  cntr = 65535;
15
}
16
17
18
int main()
19
{
20
  Init();
21
  while (1)
22
  {
23
  while (cntr) cntr--;
24
  cntr = 65535;
25
  // PORTA ^= _BV(PA3);
26
  if (Taste1) 
27
    {
28
      PORTD = 0x00; State = 0;
29
    }
30
  if (Taste2) 
31
    {
32
      State = 1; PORTD = 0x08;
33
    }
34
  }
35
  return 0;
36
}

Prog2
1
//PORTA ist der Datenport
2
#define DATA_DIR_IN()  DDRA =0x00;
3
#define DATA_DIR_OUT() DDRA =0xFF;
4
#define LCD_READ   PINA              // read PINC, ! NOT ! PORTC
5
#define LCD_WRITE  PORTA            //PORTB=(a); // write to data port
6
7
#define LCD_WR    1                // LCD_WRITE
8
#define LCD_RD    2                // LCD_READ
9
#define LCD_CE    3                // LCD_CS
10
#define LCD_CD    0                // LCD_COMMAND/DATA
11
#define LCD_RST  4                // LCD_RESET
12
13
#define LCD_CTRL  PORTB              // Steuerport LCD
14
#define LCD_CTRL_DDR   DDRB          // Data Direction of Control Port
15
16
#define LCD_WR_H()     LCD_CTRL |=  _BV(LCD_WR)  // = 1
17
#define LCD_WR_L()      LCD_CTRL &= ~_BV(LCD_WR)  // = 0
18
#define LCD_RD_H()     LCD_CTRL |=  _BV(LCD_RD)
19
#define LCD_RD_L()      LCD_CTRL &= ~_BV(LCD_RD)
20
#define LCD_CE_H()     LCD_CTRL |=  _BV(LCD_CE)
21
#define LCD_CE_L()      LCD_CTRL &= ~_BV(LCD_CE)
22
#define LCD_CD_H()     LCD_CTRL |=  _BV(LCD_CD)
23
#define LCD_CD_L()      LCD_CTRL &= ~_BV(LCD_CD)
24
#define LCD_RST_H()     LCD_CTRL |=  _BV(LCD_RST)
25
#define LCD_RST_L()      LCD_CTRL &= ~_BV(LCD_RST)
26
int main()
27
{
28
  PORTD = 0x03;   // Tristate aktiv
29
  DDRD  = 0x08;   // output
30
  PORTD = 0x08;   // output aktiv, tristate aktiv
31
  PORTA = 0xFF;   // tristate aktiv
32
  DDRA = 0x00;    // output
33
  PORTA = 0x00;   // tristate aktiv
34
  LCD_CTRL |= (1 << PB0 && 1<< PB1 && 1<< PB2 && 1<<PB3); 
35
  cntr = 10000;
36
  while (1)
37
  {
38
      while (cntr) cntr--;
39
      cntr = 10000;
40
      LCD_STATUS = 0;
41
      LCD_CTRL_DDR |= 0x0F;
42
        DATA_DIR_IN();          // Port A als Eingang
43
        LCD_CD_H();             // Commando High
44
        LCD_RD_L();             // Read Low
45
        LCD_CE_L();             // Chip Enable Low
46
        LCD_STATUS = LCD_READ;  // Status lesen
47
        LCD_CE_H();             // Chip Enable High
48
        LCD_RD_H();             // Read High
49
        LCD_STATUS &= (0x03);   // Bits ausmaskieren
50
      if ((PIND & 0x01)== 0x01) PORTD = 0x08;
51
      if ((PIND & 0x02)== 0x02) PORTD = 0x00;
52
      if (LCD_STATUS == 3) PORTD = 0x08;
53
  }
54
  return 0;
55
}

der Code wird langsam unuebersichtlich.  :)
daniel

von Karl H. (kbuchegg)


Lesenswert?

daniel wrote:
> ja die sind noch dran, hab hier keine Loetkolben. aber geht ja auch mit
> wenn ich das mit dem Pull Up beachte.

Ja, klar.

:-)
Wenn du keine externen Widerstände hättest, wäre das hier

if ((PORTD & 0x01)== 0x01) PORTD = 0x08;

ein Problem, weil du dadurch ja die Pullups abschalten würdest.
Da du aber externe Pulldown Widerstände benutzt, ist das ok.

Du solltest dir aber trotzdem angewöhnen, immer nur das Bit an
einem Port zu beeinflussen, das du haben möchtest.
Irgendwann hast du nämlich an einem Port mehrere Ausgänge in
Benutzung, (zb. 2 LEDs) und dann wird so eine einfache
Zuweisung fatal.

von daniel (Gast)


Lesenswert?

Fehlerkorrektur
Prog1 Zusatz
1
#define Taste1    (PIND & 0x01)
2
#define  Taste2    (PIND & 0x02)

Prog2 Korrektur
1
if (LCD_STATUS == 3) PORTD = 0x08; --> if (LCD_STATUS == 3) PORTD = 0x00; // LED aus

daniel

von daniel (Gast)


Lesenswert?

Sas mit den bitgerechten Zuweisung hab ich mir jetzt angewoehnt, bei 
groesseren Programmen hat man dann wirklich grosse Probleme wenn man es 
nicht so macht.
So die In/Outs funktionieren :) jetzt muss ich das nur noch mit dem 
Timing der LCD loesen. aber dafuer vielleicht ein neuer Thread.
Ich weiss es gibt schon fertige Funktionen, aber die benutzen alle den 
Resetpin noch zusaetzlich, leiderns hab ich fuer diesen keine freien Pin 
mehr und das LCD und der uC teilen sich einen gemeinsamen reset.

daniel

von Lötlackl (Gast)


Lesenswert?

Hi,

geht, wie weiter oben schon erwähnt, noch, hmmm, eleganter.
1
#define Taste1    (PIND & 1<<PD0)
2
#define  Taste2    (PIND & 1<<PD1)
Naja, gibt's noch mehrere Varianten (statt 1<<PD0 _BV(PD0) usw.) ist 
aber Geschmackssache.

mfg Lötlackl

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.