Forum: Mikrocontroller und Digitale Elektronik USART Interrupt feuert nicht


von Judge (Gast)


Lesenswert?

Hi ich habe eine Verbindung mit dem AVR und einem Terminal Programm auf 
meinem PC. Bis eben lief es noch wunderbar jetzt feuer das Interrupt 
nicht mehr. Den Code hab ich wieder hergestellt und er funktioniert noch 
immer nicht.

Verbindungen auf dem Steckbrett sind da und Empfangen kann ich noch mit 
dem Terminalprogramm daher ist die Verkabelung auch richtig.

Kerndaten zum Project:
Atmega16a interner RC Oszi

Hier ist der Code:
1
//definitions
2
//define Taster 
3
#define T_DEBOUNCE  100
4
#define TASTER_OK  (PINA & (1 << PINA0))
5
#define TASTER_UP  (PINA & (1 << PINA1))
6
#define TASTER_DOWN  (PINA & (1 << PINA2))
7
8
//led
9
#define LED_STATUS PD3
10
11
//define IIC Connection
12
#define SCK      PC7
13
#define SCA      PC7
14
15
//serial connection
16
#define BAUD 2400
17
#define MYUBRR F_CPU/16/BAUD-1
18
#define RX_PIN PD0
19
#define TX_PIN PD1
20
21
//define general
22
#define F_CPU    1000000
23
24
//libarys
25
#include <avr/io.h>
26
#include <util/delay.h>
27
#include <stdbool.h>
28
#include <avr/interrupt.h>
29
30
//function prototypes
31
//adc
32
void adc_init(void);
33
int adc_read(unsigned char);
34
void adc_change_channal(unsigned char);
35
//uart
36
void USART_Init(unsigned int);
37
void USART_Transmit(unsigned char);
38
void USART_String(char* str);
39
//led
40
void init_io(void);
41
void led_flash(unsigned char);
42
43
int main(void)
44
{  
45
  //init io
46
  init_io();
47
  
48
  sei();
49
  
50
  USART_Init(MYUBRR);
51
  
52
  while(1)
53
  {  
54
    if(TASTER_OK)
55
    {
56
      _delay_ms(T_DEBOUNCE);
57
      if(!TASTER_OK)
58
      {
59
        USART_String("OK");
60
      }
61
    }
62
    led_flash(1);
63
  }
64
    return 0;
65
}
66
67
//functions
68
//adc
69
void adc_init()
70
{
71
  int result;
72
  ADMUX = (1 << REFS1) | (1 << REFS0);
73
  //einstellen des registers
74
  ADCSRA  = (1 << ADSC) | (1 << ADPS2);
75
  //eine wandlung starten
76
  result = adc_read(0);
77
}
78
79
void adc_change_channal(unsigned char channal)
80
{
81
  switch(channal)
82
  {
83
    case(1):
84
      ADMUX &= ~(1 << MUX0);
85
      break;
86
    case(2):
87
      ADMUX |= (1 << MUX0);
88
      break;
89
    default:
90
      ADMUX &= ~(1 << MUX0);
91
      break;
92
  }
93
}
94
95
int adc_read(unsigned char channal)
96
{
97
  int result;
98
  
99
  adc_change_channal(channal);
100
  
101
  //start measuring
102
  ADCSRA |= (1 << ADEN);
103
  while(ADCSRA & (1 << ADSC));
104
  
105
  result = ADCL;
106
  result += (ADCL<<8);
107
108
  return result;
109
}
110
111
//uart
112
void USART_Transmit( unsigned char data )
113
{
114
  /* Wait for empty transmit buffer */
115
  while ( !( UCSRA & (1<<UDRE)) )
116
  ;
117
  /* Put data into buffer, sends the data */
118
  UDR = data;
119
}
120
121
void USART_String(char* str)
122
{
123
  while(*str)
124
  {
125
    USART_Transmit(*str);
126
    str++;
127
  }
128
}
129
130
void USART_Init( unsigned int ubrr)
131
{
132
  //unsigned char flush;
133
  
134
  /* Set baud rate */
135
  UBRRH = (unsigned char)(ubrr>>8);
136
  UBRRL = (unsigned char)ubrr;
137
  
138
  /* Enable receiver and transmitter */
139
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
140
  /* Set frame format: 8data, 1stop bit */
141
  UCSRC = (1<<URSEL)|(3<<UCSZ0);
142
  
143
  if(UCSRB & (1 << RXEN))
144
  {
145
    USART_String("RX enabled\n");
146
  }
147
  
148
  if(UCSRB & (1 << RXCIE))
149
  {
150
    USART_String("RX Interrupt enabled\n");
151
  }
152
  
153
  USART_String("UART Verbindung hergestellt...\n");
154
}
155
156
//gpio
157
void led_flash(unsigned char n)
158
{
159
  unsigned char i;
160
  for(i = 0; i < n; i++)
161
  {
162
    PORTD |= (1 << LED_STATUS);
163
    _delay_ms(200);
164
    PORTD &= ~(1 << LED_STATUS);
165
    _delay_ms(200);
166
  }
167
}
168
169
void init_io(void)
170
{
171
  DDRA = 0x00;
172
  PORTA = 0xff;
173
  
174
  DDRD = 0xff;
175
  DDRD &= ~(1 << RX_PIN);
176
  
177
  PORTD = 0x00;
178
  PORTD |= (1 << RX_PIN);
179
}
180
181
ISR(USART_RXC_vect)
182
{
183
  USART_String("Zeichen empfangen");
184
}

Bitte um eure Hilfe

von Nico (nico123)


Lesenswert?

Der Code sieht gut aus!
Verbinde mal RX und TX von deiner seriellen Verbindung zum PC und schaue 
ob die Daten die Du sendest auch wieder zurück kommen.

von Uwe (Gast)


Lesenswert?

> interner RC Oszi
Der ist abhängig von Betriebsspannung und Teperatur und nicht geeignet 
für UART. Man kann jedoch eine autobaud erkennung einbauen. Der PC 
Sendet ein Bestimmtes Zeichen und der µC weiß bescheid was für ein 
Zeichen es Sein soll. Dann mißt der µC ein paar bit längen und berechnet 
daruas die Baudrate. Bzw paßt die Baudtratenregister an oder verstimmt 
den internen RC-Oszillator.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Uwe schrieb:
>> interner RC Oszi
> Der ist abhängig von Betriebsspannung und Teperatur und nicht geeignet
> für UART.
Aber irgendwas wird der UART trotzdem empfangen...

von Uwe (de0508)


Lesenswert?

Hallo,

wie es aussieht sind die Taster nach Vcc geschaltet.

Das geht nicht gut, wenn da kein Pull-Down Widerstand existiert.

Die UART Init ist nicht unbedingt portabel. Schaue bitte in's Datenblatt 
und rechne mal nach.

Ich mache das so:
1
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00)  // 8 Bit
2
#ifdef URSEL0
3
     | (1<<URSEL0)    // if UCSR0C shared with UBRR0H
4
#endif
5
     ;

Deine ADC Routinen sind falsch, wie willst Du den ADC beschreiben, wenn 
er nicht eingeschaltet wird ?

Also erst in |void adc_init()| aktivieren und dann die Parameter setzen.
1
ADCSRA |= (1 << ADEN);

Was auch noch fehlt ist das Setzten des ADC Prescalewertes,so dass der 
ADC mit <= 125.00kHz läuft!

Das sind die Bits ADPS2 ADPS1 ADPS0 in ADCSRA, bei 1MHz Takt wäre es ein 
Vorteilerwert von 8, das entspricht, als Vektor geschrieben: 
(ADPS2,ADPS1,ADPS0) = (0,1,1).

Und bei 8MHz ? klar 1:64.
(ADPS2,ADPS1,ADPS0) = (1,1,0).

Und was machst Du in |adc_read()|?

*Keine Messung starten !*
1
int adc_read(unsigned char channal)
2
{
3
  int result;
4
  
5
  adc_change_channal(channal);
6
  
7
  //start measuring
8
  ADCSRA |= (1 << ADEN);
9
  while(ADCSRA & (1 << ADSC));
10
  
11
  result = ADCL;
12
  result += (ADCL<<8);
13
14
  return result;
15
}

Im Datenblatt (von Atmel) steht doch genau, wie das geht !

Und man kommt zu solch einen Ablauf bei einer Messung mit blocking.
1
int adc_read(unsigned char channal)
2
{
3
  adc_change_channal(channal);
4
  
5
  //start measuring
6
  ADCSRA |= (1 << ADSC);
7
  while(ADCSRA & (1 << ADSC));
8
  
9
  return ADCW;
10
}

von Judge (Gast)


Lesenswert?

Danke für die Antworten. Die ADC Routinen kommen erst zum Einsatz, wenn 
ich die UART Schnittstelle hinbekommen habe. Sind ausm alten Projekt mit 
einem andern Controller habe sie abgewandelt und noch nicht getestet. 
Kann gut sein das die falsch sind. Danke schonmal für den Hinweis. Die 
USART INIT routine ist aus dem Datenblatt. Habe nur statt 2 Stopbit 1 
gemacht.

von Judge (Gast)


Lesenswert?

Also ich hab jetzt nochmal die Routine aus dem Datenblatt verwendet und 
es funktioniert leider immernoch nicht. Habe das Interrupt enable selbst 
hinzugefügt.

Gibt es eine Methode um zu Prüfen ob die Interrupts global gesetzt sind?
1
void USART_Init(unsigned int ubrr)
2
{
3
  /* Set baud rate */
4
  UBRRH = (unsigned char)(ubrr>>8);
5
  UBRRL = (unsigned char)ubrr;
6
  /* Enable receiver and transmitter */
7
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
8
  /* Set frame format: 8data, 2stop bit */
9
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
10
}

Im weiteren ist mir vorhin aufgefallen als ich den Controller mit einem 
Model kommunizieren lies, das er auch geantwortet hat. Aber nicht wenn 
ich in mein Terminal Programm etwas eingebe. ich benutze das Programm 
AccessPort. Welches könnt Ihr mir empfehlen?

von spess53 (Gast)


Lesenswert?

Hi

>Gibt es eine Methode um zu Prüfen ob die Interrupts global gesetzt sind?

I-Flag in SREG auswerten.

MfG Spess

von Judge (Gast)


Lesenswert?

Aus Verzweiflung habe ich jetzt alles nochmal neu gemacht und nur die 
Routinen aus dem Datenblatt des Atmega16a genommen.
1
#include <avr/io.h>
2
3
#define FOSC 1000000// Clock Speed
4
#define BAUD 2400
5
#define MYUBRR FOSC/16/BAUD-1
6
7
void main( void )
8
{
9
  
10
  USART_Init ( MYUBRR );
11
  
12
  
13
  while(1)
14
  {
15
    USART_Transmit('H');
16
    USART_Transmit('i');
17
    USART_Transmit('!');  
18
  }
19
}
20
21
void USART_Init( unsigned int ubrr)
22
{
23
  /* Set baud rate */
24
  UBRRH = (unsigned char)(ubrr>>8);
25
  UBRRL = (unsigned char)ubrr;
26
  /* Enable receiver and transmitter */
27
  UCSRB = (1<<RXEN)|(1<<TXEN);
28
  /* Set frame format: 8data, 2stop bit */
29
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
30
}
31
32
void USART_Transmit( unsigned char data )
33
{
34
  /* Wait for empty transmit buffer */
35
  while ( !( UCSRA & (1<<UDRE)) )
36
  ;
37
  /* Put data into buffer, sends the data */
38
  UDR = data;
39
}

von Karl H. (kbuchegg)


Lesenswert?

Judge schrieb:
> Aus Verzweiflung habe ich jetzt alles nochmal neu gemacht und nur die
> Routinen aus dem Datenblatt des Atmega16a genommen.

Schön.
Und?
Siehst du auf deinem Terminal was (egal was, selbst wenn es die falschen 
Zeichen sind)

von Judge (Gast)


Lesenswert?

Nein mir wird nichts angezeigt... Habe auch ein anderes ausprobiert. 
Putty aber das startet noch nichtmal.

Ein selbstgemachtes mit C# zeigt nur mist an als noch die baudrate 
zuhoch war.. jetzt wo ich sie angepasst habe kommt nichts mehr.

von Nico (nico123)


Lesenswert?

Nico ... schrieb:
> Der Code sieht gut aus!
> Verbinde mal RX und TX von deiner seriellen Verbindung zum PC und schaue
> ob die Daten die Du sendest auch wieder zurück kommen.

Hast Du das mal getestet?

von Karl H. (kbuchegg)


Lesenswert?

Judge schrieb:
> Nein mir wird nichts angezeigt... Habe auch ein anderes ausprobiert.
> Putty aber das startet noch nichtmal.
>
> Ein selbstgemachtes mit C# zeigt nur mist an als noch die baudrate
> zuhoch war.. jetzt wo ich sie angepasst habe kommt nichts mehr.


Leg erst mal dein selbstgemachtes PC-Programm zur Seite und sieh zu, 
dass du ein Standard-Terminal Programm auf den PC kriegst. Sonst führst 
du einen 2-Frontenkrieg, weil du dich auf nix Konkretes verlassen 
kannst. Bei einem Standard-Terminal-Programm stehen die Chancen schon 
mal sehr gut, dass dieses zumindest soweit erst mal als korrekt 
angesehen werden kann.


Und dann nimmst du erst mal den µC aus seinem Sockel und brückst im 
Sockel den Tx Pin mit dem Rx Pin. Was auch immer du am Terminal an der 
Tastatur tippst, muss auch wieder im Terminal aufscheinen. Gegentest: 
Brücke im Sockel entfernen, dann muss auch das Echo aufhören.

Funktioniert dieser einfache Test nicht, dann hast du ein Hardware 
Problem. Kabel falsch gekreuzt, irgendwo was falsch angeschlossen (zb am 
MAX), Kabelader abgerissen, usw. usw.

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.