Forum: Mikrocontroller und Digitale Elektronik ATMega64 bleibt in Unterprogramm hängen


von Daniel (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem:

Mein AtMega64 beliebt beim ausführen eines Unterprogramms vom Typ:
void init_uart(void) hängen.

Ich habe das Programm vorher auf einem AtMega16 laufen lassen ohne 
Probleme. Nun passte ich es an den AtMega64 an, in dem ich die 
UART-Register änderte.
Ich habe auch die Ausführung des Unterprogramms durch das Anbinden einer 
LED getestet. D.H. er führt das Unterprogramm noch aus springt aber 
nicht zurück.
Muss ich was mit dem Stackpointer wegen des großen Flash-speicher 
beachten?

von unsichtbarer WM-Rahul (Gast)


Lesenswert?

>Muss ich was mit dem Stackpointer wegen des großen Flash-speicher
>beachten?
Was haben die beiden miteinander zu tun? Stimmt! Gar nichts!

Ein (grossen) Stück Code zu posten, könnte helfen. Vielleicht sogar das 
konplette Programm...

von Daniel (Gast)


Lesenswert?

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define CONTROL_DIRECTION  DDRA
#define WRITE_CONTROL    PORTA
#define CTRL_DATA      2    // (RS)    1->Data    0->Control
#define WR           3    // (W_R)    0-> zum Schreiben
#define RD              4    // (E)    0-> zum LESEN
#define CE           5    // (CS)    0-> Chip aktivieren
#define Reset           6    // (RESET)  0-> Initialisierung wird 
ausgeführt

#define WRITE_DATA      PORTC
#define READ_DATA      PINC
#define DATA_DIRECTION    DDRC

#define IN        0x00
#define OUT        0xFF

unsigned char recieve_byte;
unsigned char send_byte;

void LCD_INIT(void);
void LCD_READ_DATA(void);
void LCD_WRITE_DATA(unsigned char dat);
void LCD_WRITE_COMMAND(unsigned char cmd);
void INIT_UART(void);
void SEND_UART(void);
void LCD_SET_PAGE(unsigned char site);
void LCD_SET_COLUMN(unsigned char column);


//Interrupts######################################
ISR(USART0_RX_vect)
{
  recieve_byte = UDR0;
  LCD_SET_PAGE(0);
  LCD_SET_COLUMN(0);
  LCD_WRITE_DATA(recieve_byte);
  LCD_SET_PAGE(0);
  LCD_SET_COLUMN(0);
  LCD_READ_DATA();
  SEND_UART();
}
//#################################################
//Hauptprogramm####################################
int main(void)
{

//INIT PORTS
  CONTROL_DIRECTION = OUT;      //PortA als Ausgang
  WRITE_CONTROL     = 0xFF;    //Portzustand -> 0xFF
  DATA_DIRECTION    = OUT;      //Datenbus(PortC) als Ausgang
  WRITE_DATA     = 0xFF;    //Datenbuszustand -> 0xFF
//INIT UART
  INIT_UART();
//UART Kontrolle
  send_byte = 0x00;    //01011010
  SEND_UART();
  sei();

  WRITE_CONTROL &= ~(1<<Reset);    //löscht Reset
  _delay_ms(100);
  WRITE_CONTROL |=  (1<<Reset);    //setzt  Reset
  int b,page;
  LCD_INIT();

  for(page=0;page<16;page++)
  {
    LCD_SET_PAGE(page);
    LCD_SET_COLUMN(0);

    for(b=0;b<300;b++)
    {
      LCD_WRITE_DATA(0x00);
      _delay_ms(1);
    }
    _delay_ms(100);
    LCD_SET_PAGE(page);
    LCD_SET_COLUMN(0);

    LCD_WRITE_DATA(0x00);
    _delay_ms(1);
    LCD_WRITE_DATA(0x82);
  }
  _delay_ms(10000);
  PORTC=send_byte;
  SEND_UART();
  int c;
  do
  {
    if(c>0x3F)c=0;
    LCD_WRITE_COMMAND(0x81);                 // Contrast set
    LCD_WRITE_COMMAND(c);         // 0x00-0x3F ->2F ist gut
    _delay_ms(200);
    c++;
  }
  while(1);
}

void LCD_INIT(void)   //S6B0741

{
  LCD_WRITE_COMMAND(0xE2);                 // Reset

  LCD_WRITE_COMMAND(0xAE);                 // display off

  LCD_WRITE_COMMAND(0xAB);                 // Osc on

  LCD_WRITE_COMMAND(0x67);                 // DC_DC

  LCD_WRITE_COMMAND(0x26);                 // Resistor ratio

  LCD_WRITE_COMMAND(0x81);                 // Contrast set
  LCD_WRITE_COMMAND(0x2F);         // 0x00-0x3F ->2F ist gut

  LCD_WRITE_COMMAND(0x55);                 // LCD bias 1/10

  LCD_WRITE_COMMAND(0x2f);                 // power cntrl

  LCD_WRITE_COMMAND(0xA1);                 // A0 SEG0 -> SEG127 || A1 
SEG127 -> 0

  LCD_WRITE_COMMAND(0xC0);                 // SHL

  LCD_WRITE_COMMAND(0x44);                 // Start Com
  LCD_WRITE_COMMAND(0x00);                 // value

  LCD_WRITE_COMMAND(0x40);                 // Start Line
  LCD_WRITE_COMMAND(0x00);                 // value

  LCD_WRITE_COMMAND(0xB0);                 // page adress

  LCD_WRITE_COMMAND(0x17);                 // Col Adr high
  LCD_WRITE_COMMAND(0x0F);                 // Col adress low

  LCD_WRITE_COMMAND(0xA6);                 // Displ Mode reverse

  LCD_WRITE_COMMAND(0xA2);                 // Icon

  LCD_WRITE_COMMAND(0xE1);                 // release Power save mode

  LCD_WRITE_COMMAND(0xE4);                 // release n-line inversion

  LCD_WRITE_COMMAND(0x93);                 // 15PWM  4FRC

  LCD_WRITE_COMMAND(0x8F);                 //Grauwerte
  LCD_WRITE_COMMAND(0x00);
  LCD_WRITE_COMMAND(0x89);
  LCD_WRITE_COMMAND(0x00);

  LCD_WRITE_COMMAND(0x8a);
  LCD_WRITE_COMMAND(0x77);
  LCD_WRITE_COMMAND(0x8b);
  LCD_WRITE_COMMAND(0x77);

  LCD_WRITE_COMMAND(0x8c);
  LCD_WRITE_COMMAND(0xAA);
  LCD_WRITE_COMMAND(0x8d);
  LCD_WRITE_COMMAND(0xaa);

  LCD_WRITE_COMMAND(0x8e);
  LCD_WRITE_COMMAND(0xff);
  LCD_WRITE_COMMAND(0x8f);
  LCD_WRITE_COMMAND(0xff);

  LCD_WRITE_COMMAND(0x4f);                 //n-line inversion
  LCD_WRITE_COMMAND(0x05);

  LCD_WRITE_COMMAND(0xAF);                 // display on
}


void LCD_WRITE_DATA(unsigned char dat)          // Write data to the 
controller
{
  DATA_DIRECTION    = OUT;
  WRITE_CONTROL |= (1<<CTRL_DATA);    //RS=1    ->Display-Daten  1->Data 
0->Control
  WRITE_CONTROL &= ~(1<<CE);      //CS=0;    ->Bausteinfreigabe
  WRITE_CONTROL &= ~(1<<WR);      //WR=0;    ->Schreiben

  WRITE_DATA = dat;

  WRITE_CONTROL |= (1<<WR);      //Daten werden in Displayspeicher 
übernommen
  WRITE_CONTROL |= (1<<CE);      //CS=1;    ->Baustein sperren
}

void LCD_WRITE_COMMAND(unsigned char cmd)       // Write commands to the 
controller
{
  DATA_DIRECTION    = OUT;
  WRITE_CONTROL &= ~(1<<CTRL_DATA);    //RS=0    ->Control-Daten 
1->Data    0->Control
  WRITE_CONTROL &= ~(1<<CE);      //CS=0    ->Bausteinfreigabe
  WRITE_CONTROL &= ~(1<<WR);      //WR=0;    ->Schreiben

  WRITE_DATA = cmd;

  WRITE_CONTROL |= (1<<WR);      //Daten werden in Displayspeicher 
übernommen
  WRITE_CONTROL |= (1<<CE);      //CS=1;    ->Baustein sperren
  WRITE_CONTROL |= (1<<CTRL_DATA);    //RS=1    ->Display-Daten  1->Data 
0->Control
}

void LCD_READ_DATA(void)
{
  DATA_DIRECTION    = IN;
  WRITE_CONTROL |= (1<<CTRL_DATA);    //RS=0    ->Control-Daten  1->Data 
0->Control
  WRITE_CONTROL &= ~(1<<CE);      //CS=0    ->Bausteinfreigabe
  WRITE_CONTROL &= ~(1<<RD);      //WR=0;    ->Schreiben
  WRITE_CONTROL |= (1<<RD);      //Dummy


  WRITE_CONTROL &= ~(1<<RD);      //WR=0;    ->Schreiben

  send_byte = READ_DATA;

  WRITE_CONTROL |= (1<<RD);      //Daten werden in Displayspeicher 
übernommen
  WRITE_CONTROL |= (1<<CE);      //CS=1;    ->Baustein sperren
}


void LCD_SET_PAGE(unsigned char site)
{
  site = site + 0xB0;
  LCD_WRITE_COMMAND(site);
}

void LCD_SET_COLUMN(unsigned char column)
{
  unsigned char column_msb = 0x10;
  unsigned char column_lsb = 0x00;
  if(bit_is_set(column,6)) column_msb = column_msb + 4;
  if(bit_is_set(column,5)) column_msb = column_msb + 2;
  if(bit_is_set(column,4)) column_msb = column_msb + 1;
  if(bit_is_set(column,3)) column_msb = column_lsb + 8;
  if(bit_is_set(column,2)) column_msb = column_lsb + 4;
  if(bit_is_set(column,1)) column_msb = column_lsb + 2;
  if(bit_is_set(column,0)) column_msb = column_lsb + 1;
  LCD_WRITE_COMMAND(column_msb);
  LCD_WRITE_COMMAND(column_lsb);
}


void SEND_UART(void)
{
  loop_until_bit_is_set(UCSR0A,UDRE0);
  UDR0 = send_byte;
}

void INIT_UART(void)
{            //Bei 1MHz U2X=0->4800    U2X=1->9600
  UBRR0L = 12;         //Bei 8MHz U2X=0->19,2KB    U2X=1->38,4KB
  UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
  UCSR0A = (1<<U2X0);
}

von Daniel (Gast)


Lesenswert?

Also führt den letzten Befehl im UP void INIT_UART(void) noch aus(letzte 
Zeile) springt aber nicht zurück.

>>Muss ich was mit dem Stackpointer wegen des großen Flash-speicher
>>beachten?
>Was haben die beiden miteinander zu tun? Stimmt! Gar nichts!

Speichert der Stackpointer keine Adresse vom Programmspeicher für den 
Rücksprunges aus einem UP?

von Daniel (Gast)


Lesenswert?

Applikation:
Ich steuere damit eine grafischen Controller vom Typ S6B0741 mit einenm 
Display von 128x128 an.

von Daniel (Gast)


Lesenswert?

Lasse ich die Unterprogramme
  INIT_UART();
  SEND_UART();
aus bleibt der AtMega64 im UP _delay_ms(100),
hängen. Das UP sei() wir noch ausgeführt.
Was könnte das sein da vorher das Programm auf einem AtMega16 ohne 
Fehler ausgeführt wurde?

von johnny.m (Gast)


Lesenswert?

Mit welcher Taktfrequenz läuft der µC? Die _delay_xx-Funktionen aus der 
util.h können nur eine begrenzte Verzögerungszeit. Für die 
_delay_ms()-Funktion gilt: Maximale Verzögerungszeit = 262.14 ms / F_CPU 
in MHz. _delay_ms(100) geht mit Taktfrequenzen über 2,6 MHz nicht 
mehr...

von Daniel (Gast)


Lesenswert?

2Mhz ist mein Takt.
Ich habe meinen Fehler gefunden. -> DER µC WAR DEFEKT.
Obwohl er noch von meiner Seite aus jungfräulich war.

Ich glaube ich muss meinen Arbeitsplatz ESD/EGB entsprechend 
einrichten;)

Danke trotzdem.

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.