www.mikrocontroller.net

Forum: Compiler & IDEs UART mit AT90CAN32


Autor: Nick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe ein kleines Problem mit meinem AVR.
Ich habe zwei serielle Schnittstellen, an der 0er ist ein MAX232 zum 
Terminal am PC, mit dem Programm empfange ich auch was auf dem PC.
An der 1er ist ein K-Line Treiber und sobald ich dir Funktion 
putchar1(c);  aufrufte steht der AVR und es passiert nichts mehr.
Ich denke es liegt an der ISR zum Empang eines Zeichens?
Da bei der K-Line ja ein Zeichen, sofort nach dem es geschrieben wird, 
wieder im Eingangsbuffer landen sollte. (Eindraht Schnittstelle)
Hoffe jemand hier kann  mir Helfen.
THX
#include <avr/interrupt.h>
#include <avr/iocan32.h>
//#include <avr/ioc.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL     /* Quarz mit 16 Mhz  */
#include <avr/delay.h>      /* definiert _delay_ms() ab avr-libc Version 1.2.0 */


#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART1 Receiver buffer
#define RX_BUFFER_SIZE1 8
char rx_buffer1[RX_BUFFER_SIZE1];
unsigned char rx_wr_index1,rx_rd_index1,rx_counter1;
// This flag is set on USART1 Receiver buffer overflow
// bit rx_buffer_overflow1;
char rx_buffer_overflow1;                      //Kläre BIT 


// USART1 Receiver interrupt service routine used for K-Line receiving
ISR(USART1_RXC_vect)
{
char status,data;
status=UCSR1A;
data=UDR1;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer1[rx_wr_index1]=data;
   if (++rx_wr_index1 == RX_BUFFER_SIZE1) rx_wr_index1=0;
   if (++rx_counter1 == RX_BUFFER_SIZE1)
      {
      rx_counter1=0;
      rx_buffer_overflow1=1;
      };
   };  
}

ISR (TIMER1_OVF_vect)
  {
TCNT1H=0x1e;
TCNT1L=0x7c;
if ( PINE & (1<<PINE7) ) {
   PORTE &= ~(1 << 7);  
  }
  else {
    PORTE |= (1 << 7);    
  }
}

// Get a character from the USART1 Receiver buffer
char getchar1(void)
{
char data;
while (rx_counter1==0);
data=rx_buffer1[rx_rd_index1];
if (++rx_rd_index1 == RX_BUFFER_SIZE1) rx_rd_index1=0;
cli();
--rx_counter1;
sei();
return data;
}

// FUNCTION Prototypes::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void seriell_int(void);
void putchar1(char c);
void putchar0(char c);
void timer_init(void);

void putchar1(char c)
{
while ((UCSR1A & DATA_REGISTER_EMPTY)==0)
{
  // Toggle pin;
}
UDR1=c;
}

void putchar0(char c)
{
while ((UCSR0A & DATA_REGISTER_EMPTY)==0);
UDR0=c;
}

void seriell_int(void)
{
// USART0 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART0 Receiver: On
// USART0 Transmitter: On
// USART0 Mode: Asynchronous
// USART0 Baud rate: 19200
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x33;
// USART1 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART1 Receiver: On
// USART1 Transmitter: On
// USART1 Mode: Asynchronous
// USART1 Baud rate: 19200
UCSR1A=0x00;
UCSR1B=0x98;
UCSR1C=0x06;
UBRR1H=0x00;
UBRR1L=0x33;
}

void timer_init(void)
{

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// OC1C output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x04;
TCNT1H=0x1e;
TCNT1L=0x7c;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
OCR1CH=0x00;
OCR1CL=0x00;
TIMSK1=0x01;
}

// PORTA |= (1 << 2);    /* setzt Bit 2 an PortA auf 1 */
// PORTA &= ~(1 << 2);   /* loescht Bit 2 an PortA */

// MAIN :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// 
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
int main (void)
{  
char c;
c = 0x51;

  CLKPR = 0x80;      //Change System CLK-Prescaler to 1
  CLKPR = 0x00;      //Change System CLK-Prescaler to 1
  PORTE = 0xFF;
  DDRE = 0xE0;
  seriell_int();
  timer_init();
  sei();    
  while (1)
  {
      putchar0(c);   
      putchar1(c);  
    _delay_ms(200);
  }
  //never goes here!
  return 0;      
}


  

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, zu Deinem eigentlichen Problem habe ich beim Überfliegen Deines 
Codes nichts auffälliges gefunden. Nur drei "Kleinigkeiten":

1.: _delay_ms() geht nur bis 262,4ms/F_CPU[MHz]. _delay_ms(200) geht 
also bei 16 MHz schon mal nicht mehr.

2.: Ein Bit toggelt man nicht mit einer if-else-Abfrage sondern mit 
einer Exklusiv-ODER-Verknüpfung. Das if-else, das in Deiner 
Timer1-Overflow-Routine steht, ist ein Einzeiler:
PORTE ^= 1 << PORTE7;

3.: Was Du da mit dem Timer machst (Overflow-Interrupt und Nachladen) 
macht man i.d.R. nicht. Dafür gibt es den CTC-Modus. Da braucht nichts 
nachgeladen zu werden. Außerdem kannst Du das ganze auch ohne Interrupt 
machen, vorausgesetzt Dein Layout lässt es zu, dass die LED an einen 
Compare-Ausgang des Timers angeschlossen werden kann. Dann kann die 
Hardware die LED selber toggeln, ohne dass Du im Programm noch irgendwas 
anderes machen musst als ein einziges Mal den Timer zu starten...

Autor: Nick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die Tips.
Das mit Delay hab ich schon mal wo gelesen, ist aber nicht so wichtig in 
dem Fall ist nur das was passiert.

Pin Toggle werd ich gleich Heute mal probieren danach hab ich schon 
gesucht nur nichts gefunden, bin Anfänger in C.

An der Hardware will ich  nichts ändern, ich wollte nur sehen das die 
LED blinkt, um zu sehen ob meine Syntax für die ISR beim UART stimmt und 
darum hab ich das mal für den Timer gemacht.

Sonst keiner einen Tipp was an der ISR zum empfangen nicht stimmt?
Müssen noch IRQ Flags gelöscht werden?

Werd mal versuchen in der ISR eine LED zu toggeln um zu sehen wie weit 
das programm läuft, wenn nicht werd ich wohl warten müssen bis ich 
meinen Debugger habe.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Müssen noch IRQ Flags gelöscht werden?
Das Interrupt-Flag "RXC1" wird beim Lesezugriff auf UDR1 automatisch 
gelöscht.

Was mir noch aufgefallen ist: Dein Empfangs-Buffer ist nicht volatile. 
Das bedeutet, dass der Compiler eventuell Zugriffe wegoptimiert, was 
dazu führen kann, dass Dein Hauptprogramm (wenn Du den Buffer da mal 
auslesen und weiterverarbeiten möchtest) eventuell von empfangenen 
Zeichen gar nichts mitbekommt. Variablen, die sowohl in einer ISR als 
auch im Programm verwendet werden, sollten volatile deklariert werden.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, den CTC-Modus kannst Du natürlich auch verwenden, ohne die LED 
an den entsprechenden Pin zu hängen. Musst dann nur wie oben in der ISR 
toggeln. Allerdings dann nicht in der Overflow-ISR, sondern mit einem 
Compare-Interrupt.

Autor: Nick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
CTC ist mir schon klar ist aber nicht wichtig im Moment kommt eh wieder 
raus.
Volatile werde ich machen, wusste ich so nicht, das dürfte aber auch 
nicht der grund sein warum sich das Programm aufhängt.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übrigens: Es ist immer sehr hilfreich, alle Programmteile, die gar nicht 
benutzt werden, rauszuschmeißen und wirklich nur ein Minimalprogramm zu 
testen (und hier zu posten). Die Funktion "getchar1()" wird z.B. nie 
aufgerufen. Also weg damit. Außerdem wäre es sinnvoll, die 
(augenscheinlich vom CVAVR Code Generation Wizard stammenden) 
Initialisierungen durch lesbarere (in der Art "<I/O-REGISTER> = (1 << 
BIT1) | (1 << BIT2)...") zu ersetzen. Der Wizard ist zwar ne bequeme 
Sache, um sich ein Programmgerüst schnell und ohne großartiges 
Datenblatt-Wälzen zu erstellen, die Notation erschwert die Fehlersuche 
aber ungemein, weil sich da der Hilfswillige erst mal im Datenblatt 
kundig machen muss, um zu wissen, ob da alles so weit stimmt...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> das dürfte aber auch nicht der grund sein warum sich das Programm aufhängt.
Richtig, weil Du den Buffer im Programm ja (noch) nicht liest.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> #include <avr/iocan32.h>
Das macht man übrigens auch nicht. Es wird grundsätzlich nur die 
"avr/io.h" eingebunden. Den Controllertyp stellt man im Makefile (oder 
im AVRStudio unter "Configuration Options") ein. Beim Compilieren wird 
dann automatisch die korrekte ioXXXX.h eingebunden.

Aber zu Deinem eigentlichen Problem habe ich immer noch keine 
Auffälligkeiten gefunden...

Autor: Nick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich danke euch für die Hilfe und die Anstösse ;-)
als Anfänger werd ich wohl noch das ein oder ander mal kommen müssen.


Der Fehler ist eigentlich einfach:
ISR(USART1_RXC_vect)
ist falsch
und sollte jetzt
ISR(USART1_RX_vect)
dann klappts auch mit dem Empfangen


gefunden hier:
http://www.nongnu.org/avr-libc/user-manual/group__...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.