Forum: Compiler & IDEs UART mit AT90CAN32


von Nick (Gast)


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
1
#include <avr/interrupt.h>
2
#include <avr/iocan32.h>
3
//#include <avr/ioc.h>
4
#include <avr/interrupt.h>
5
#define F_CPU 16000000UL     /* Quarz mit 16 Mhz  */
6
#include <avr/delay.h>      /* definiert _delay_ms() ab avr-libc Version 1.2.0 */
7
8
9
#define RXB8 1
10
#define TXB8 0
11
#define UPE 2
12
#define OVR 3
13
#define FE 4
14
#define UDRE 5
15
#define RXC 7
16
17
#define FRAMING_ERROR (1<<FE)
18
#define PARITY_ERROR (1<<UPE)
19
#define DATA_OVERRUN (1<<OVR)
20
#define DATA_REGISTER_EMPTY (1<<UDRE)
21
#define RX_COMPLETE (1<<RXC)
22
23
// USART1 Receiver buffer
24
#define RX_BUFFER_SIZE1 8
25
char rx_buffer1[RX_BUFFER_SIZE1];
26
unsigned char rx_wr_index1,rx_rd_index1,rx_counter1;
27
// This flag is set on USART1 Receiver buffer overflow
28
// bit rx_buffer_overflow1;
29
char rx_buffer_overflow1;                      //Kläre BIT 
30
31
32
// USART1 Receiver interrupt service routine used for K-Line receiving
33
ISR(USART1_RXC_vect)
34
{
35
char status,data;
36
status=UCSR1A;
37
data=UDR1;
38
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
39
   {
40
   rx_buffer1[rx_wr_index1]=data;
41
   if (++rx_wr_index1 == RX_BUFFER_SIZE1) rx_wr_index1=0;
42
   if (++rx_counter1 == RX_BUFFER_SIZE1)
43
      {
44
      rx_counter1=0;
45
      rx_buffer_overflow1=1;
46
      };
47
   };  
48
}
49
50
ISR (TIMER1_OVF_vect)
51
  {
52
TCNT1H=0x1e;
53
TCNT1L=0x7c;
54
if ( PINE & (1<<PINE7) ) {
55
   PORTE &= ~(1 << 7);  
56
  }
57
  else {
58
    PORTE |= (1 << 7);    
59
  }
60
}
61
62
// Get a character from the USART1 Receiver buffer
63
char getchar1(void)
64
{
65
char data;
66
while (rx_counter1==0);
67
data=rx_buffer1[rx_rd_index1];
68
if (++rx_rd_index1 == RX_BUFFER_SIZE1) rx_rd_index1=0;
69
cli();
70
--rx_counter1;
71
sei();
72
return data;
73
}
74
75
// FUNCTION Prototypes::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
76
void seriell_int(void);
77
void putchar1(char c);
78
void putchar0(char c);
79
void timer_init(void);
80
81
void putchar1(char c)
82
{
83
while ((UCSR1A & DATA_REGISTER_EMPTY)==0)
84
{
85
  // Toggle pin;
86
}
87
UDR1=c;
88
}
89
90
void putchar0(char c)
91
{
92
while ((UCSR0A & DATA_REGISTER_EMPTY)==0);
93
UDR0=c;
94
}
95
96
void seriell_int(void)
97
{
98
// USART0 initialization
99
// Communication Parameters: 8 Data, 1 Stop, No Parity
100
// USART0 Receiver: On
101
// USART0 Transmitter: On
102
// USART0 Mode: Asynchronous
103
// USART0 Baud rate: 19200
104
UCSR0A=0x00;
105
UCSR0B=0x98;
106
UCSR0C=0x06;
107
UBRR0H=0x00;
108
UBRR0L=0x33;
109
// USART1 initialization
110
// Communication Parameters: 8 Data, 1 Stop, No Parity
111
// USART1 Receiver: On
112
// USART1 Transmitter: On
113
// USART1 Mode: Asynchronous
114
// USART1 Baud rate: 19200
115
UCSR1A=0x00;
116
UCSR1B=0x98;
117
UCSR1C=0x06;
118
UBRR1H=0x00;
119
UBRR1L=0x33;
120
}
121
122
void timer_init(void)
123
{
124
125
// Timer/Counter 1 initialization
126
// Clock source: System Clock
127
// Clock value: 62,500 kHz
128
// Mode: Normal top=FFFFh
129
// OC1A output: Discon.
130
// OC1B output: Discon.
131
// OC1C output: Discon.
132
// Noise Canceler: Off
133
// Input Capture on Falling Edge
134
TCCR1A=0x00;
135
TCCR1B=0x04;
136
TCNT1H=0x1e;
137
TCNT1L=0x7c;
138
ICR1H=0x00;
139
ICR1L=0x00;
140
OCR1AH=0x00;
141
OCR1AL=0x00;
142
OCR1BH=0x00;
143
OCR1BL=0x00;
144
OCR1CH=0x00;
145
OCR1CL=0x00;
146
TIMSK1=0x01;
147
}
148
149
// PORTA |= (1 << 2);    /* setzt Bit 2 an PortA auf 1 */
150
// PORTA &= ~(1 << 2);   /* loescht Bit 2 an PortA */
151
152
// MAIN :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
153
// 
154
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
155
int main (void)
156
{  
157
char c;
158
c = 0x51;
159
160
  CLKPR = 0x80;      //Change System CLK-Prescaler to 1
161
  CLKPR = 0x00;      //Change System CLK-Prescaler to 1
162
  PORTE = 0xFF;
163
  DDRE = 0xE0;
164
  seriell_int();
165
  timer_init();
166
  sei();    
167
  while (1)
168
  {
169
      putchar0(c);   
170
      putchar1(c);  
171
    _delay_ms(200);
172
  }
173
  //never goes here!
174
  return 0;      
175
}

  

von johnny.m (Gast)


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:
1
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...

von Nick (Gast)


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.

von johnny.m (Gast)


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.

von johnny.m (Gast)


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.

von Nick (Gast)


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.

von johnny.m (Gast)


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...

von johnny.m (Gast)


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.

von johnny.m (Gast)


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...

von Nick (Gast)


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__avr__interrupts.html

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.