Hallo!
Das Thema war zwar schon sehr oft Inhalt, aber ich komme mit meinem
Problem einfach nicht weiter. Da ich hier schon sehr viel hilfreiche
Tipps sammeln konnte, hoffe ich, dass mir vielleicht jemand helfen kann.
Ich versuche gerade, mich ein Bisschen mit einem ATtiny13 zu
beschäftigen und diesem die grundlegendsten Funktionen einer
Software-UART zu programmieren, damit ich diesem zukünftig Befehle
senden kann, um z.B. eine AD-Wandlung zu starten. Das Ergebnis kann dann
am Rechner weiterverarbeitet werden.
Der u-Controller ist über den internen Oszillator auf 9,6 MHz, ohne
Vorverteiler, getaktet.
Das Programm ist aktuell noch sehr simpel und soll auf PORTB-Pin 2 ein
Byte empfangen und dieses auf PORTB-Pin 1 wieder ausgeben.
Einfach, um UART, den u-Controller und Interrupts kennenzulernen.
Das Zeichen zum Testen sende ich mit Putty.
Hier ist das "Lokale Echo", "Local Line Editing" und die Flusskontrolle
abgeschaltet, damit wirklich nur das eingegebene Zeichen gesendet und
das ankommende Zeichen ausgegeben wird (ohne Carriage Return und Line
Feed).
Soweit funktioniert das auch. Allerdings scheint mir, als wird die
Interrupt-Routine zweimal ausgeführt, da ich zwei Zeichen zurück
bekomme.
Einmal das zum u-Controller gesendete Zeichen "a" und einmal 255_DEC,
also LOW auf RX.
Neben dem Quellcode habe ich einen Screenshot vom "Messergebnis" mit dem
OpenLogicSniffer angefügt.
Der Interrupt sollte, wenn ich mich im Datenblatt nicht verlesen habe,
bei steigender Flanke an PORTB-Pin 2 ausgelöst werden und seine Routine
abarbeiten....wie gesagt, passiert dies leider zweimal.
Auf PIN 2 gibt es nach dem Einlesen eines Bytes keine steigende Flanke
mehr. Normalerweise sollte die Interruptroutine in diesem Beispiel kein
zweites Mal aufgerufen werden.
Ich gehe davon aus, dass während die ISR abgearbeitet wird, kein
weiteres Interrupt-Ereignis eingereiht wird. Um dies zu prüfen, habe ich
die Funktionen cli() und sei() am Anfang und Ende von ISR() aufgerufen,
was aber zum selben Ergebnis geführt hatte...
Hat vielleicht jemand von euch eine Idee, wo das Problem liegt?
Vielleicht habe ich etwas übersehen, missverstanden oder einen Fehler im
Code.
main.c
1 | #include <avr/io.h
|
2 | #include <avr/iotn13.h>
|
3 | #include <avr/interrupt.h>
|
4 | #include "uart.h"
|
5 |
|
6 | unsigned char c;
|
7 |
|
8 |
|
9 | ISR( PCINT0_vect ); // Interrupt Service Routine External Interrupt Request
|
10 |
|
11 |
|
12 |
|
13 | int main()
|
14 | {
|
15 | DDRB |= ( 1 << PB1 );
|
16 |
|
17 | PCMSK |= (1<<PCINT2); // PIN Change Mask Register External Interrupt at PINB2
|
18 | MCUCR |= (1<<ISC01) | (1<<ISC00); // MCU General Control Register Rising Edge LOW to HIGH (RS232 Start-Bit)
|
19 | GIMSK |= (1<<PCIE); // General Interrupt MaSK Register External Interrupt
|
20 | sei(); // Enable Interrupt
|
21 |
|
22 |
|
23 | while(1) // Main Routine
|
24 | {
|
25 | // Singe ein Lied
|
26 | }
|
27 |
|
28 | return 0;
|
29 | }
|
30 |
|
31 |
|
32 | ISR( PCINT0_vect )
|
33 | {
|
34 | c = _uart_receive_byte();
|
35 | _uart_send_byte( c );
|
36 | }
|
uart.h
1 | #ifndef _UART_H_
|
2 | #define _UART_H_
|
3 |
|
4 | #include <avr/io.h>
|
5 | #include <avr/iotn13.h>
|
6 | #include <util/delay.h>
|
7 |
|
8 | // Prototypen:
|
9 |
|
10 | int _uart_send_byte(unsigned char c);
|
11 | unsigned char _uart_receive_byte();
|
12 |
|
13 | #endif
|
uart.c
1 | #include "uart.h"
|
2 |
|
3 | //Funktionen:
|
4 |
|
5 | int _uart_send_byte(unsigned char c )
|
6 | {
|
7 | uint8_t i = 0;
|
8 |
|
9 | PORTB |= ( 1 << PB1 ); //START Bit (Set PortPIN HIGH)
|
10 | _delay_us( 104 );
|
11 |
|
12 | for( i = 0; i < 8; i ++) // Choose every bit from char LSB to MSB
|
13 | {
|
14 | if( ((c >> i ) & 0x01) ) // Check if Bit is 1
|
15 | {
|
16 | PORTB &= ~(1<<PB1); // Bit is 1, Clear Bit (Set PortPIN LOW)
|
17 | }
|
18 | else
|
19 | {
|
20 | PORTB |= (1<<PB1); // Bit is 0, Set Bit (Set PortPIN HIGH)
|
21 | }
|
22 | _delay_us( 104 );
|
23 | }
|
24 |
|
25 | PORTB &= ~(1<<PB1); // STOP Bit (Set PortPIN LOW)
|
26 | _delay_us( 104 );
|
27 |
|
28 | return 0;
|
29 | }
|
30 |
|
31 | unsigned char _uart_receive_byte()
|
32 | {
|
33 | unsigned char c=0x00;
|
34 | uint8_t i = 0;
|
35 |
|
36 | _delay_us( 156 ); // Wait 1,5 Bits after rising edge of START-Bit
|
37 |
|
38 | for( i = 0; i < 8; i++ )
|
39 | {
|
40 | if( ((PINB >> PINB2) & 1) )
|
41 | {
|
42 | c &= ~(1<<i);
|
43 | }
|
44 | else
|
45 | {
|
46 | c |= (1<<i);
|
47 | }
|
48 | _delay_us( 104 );
|
49 | }
|
50 |
|
51 | _delay_us( 104 ); // STOP Bit
|
52 |
|
53 | return c;
|
54 | }
|