UART bei atmega8

Gast #1527571
Lesenswert?

Hallo,

ich möchte UART an einem atmega8 nutzen. Der folgende Code soll dabei 
alle einkommenen Zeichen zurücksenden. Ich nutze ein fertiges Board von 
"myavr", Quarz ist, ~3,68 MHz.

Leider funktioniert das ganze nicht und finde keinen Fehler im 
Quellcode:



1
#include  <avr\io.h>    // AVR Register und Konstantendefinitionen
2
#include   <util\delay.h>  // Bibliothek mit Warteroutinen
3
#include <stdint.h>
4
#define   F_CPU 3686400  // Taktfrequenz des myAVR-Boards
5

6

7
// Define baud rate
8

9
#define USART_BAUD 9600ul
10

11
#define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1)
12

13

14
void USART_vInit(void)
15

16
{
17

18
// Set baud rate
19

20
UBRRH = (uint8_t)(USART_UBBR_VALUE>>8);
21

22
UBRRL = (uint8_t)USART_UBBR_VALUE;
23

24

25
// Set frame format to 8 data bits, no parity, 1 stop bit
26

27
UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
28

29

30
// Enable receiver and transmitter
31

32
UCSRB = (1<<RXEN)|(1<<TXEN);
33

34
}
35

36

37
void USART_vSendByte(uint8_t u8Data)
38

39
{
40

41
// Wait if a byte is being transmitted
42

43
while((UCSRA&(1<<UDRE)) == 0);
44

45
// Transmit data
46

47
UDR = u8Data;
48

49
}
50

51

52
uint8_t USART_vReceiveByte()
53

54
{
55

56
// Wait until a byte has been received
57

58
while((UCSRA&(1<<RXC)) == 0);
59

60
// Return received data
61

62
return UDR;
63

64
}
65

66

67
int main(void)
68

69
{
70

71
uint8_t u8Data;
72

73

74
// Initialise USART
75

76
USART_vInit();
77

78

79
// Send string
80

81
USART_vSendByte('A');
82

83
// Repeat indefinitely
84

85
for(;;)
86

87
{
88

89
// Echo received characters
90

91
u8Data  = USART_vReceiveByte();
92

93
USART_vSendByte(u8Data);
94

95
}
96

97
}
#1527676
Lesenswert?

Stefan B. schrieb:
> Was meint dein Datenblatt deines Atmega8 zu dem Bit URSEL in dieser
> Initialisierungsequenz?

• Bit 7 – URSEL: Register Select
This bit selects between accessing the UCSRC or the UBRRH Register. It 
is read as one whenreading UCSRC. The URSEL must be one when writing the 
UCSRC.
Gast #1527685
Lesenswert?

Tim schrieb:
> Und was kann ich jetzt mit der Information anfangen vor der Hintergrund,
> dass das Bit URSEL in meinem Code nicht vorkommt?

IM DATENBLATT NACHLESEN, WAS DAS BIT URSEL MACHT!!!!!!!!!!!!!!!!! HASTES 
JETZT?
#1527694
Lesenswert?

Hallo Tim,

das habe ich im Datenblatt auf Seite 152 gefunden:

The UBRRH Register shares the same I/O location as the UCSRC Register. 
Therefore some special consideration must be taken when accessing this 
I/O location.
When doing a write access of this I/O location, the high bit of the 
value written, the USART Register. Select (URSEL) bit, controls which 
one of the two registers that will be written. If URSEL is zero during a 
write operation, the UBRRH value will be updated. If URSEL is one, the 
UCSRC setting will be updated.
The following code examples show how to access the two registers.
1
/* Set UBRRH to 2 */
2
UBRRH = 0x02;
3
...
4
/* Set the USBS and the UCSZ1 bit to one, and */
5
/* the remaining bits to zero. */
6
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ1);
7
...

Sprich wenn du in dein UCSRC Register schreiben willst, musst du erst 
das Bit URSEL auf 1 setzen. Sonst schreibst du in UBRRH (und veränderst 
dadurch deine Baudrate -> da bin ich mir jetzt nicht so sicher, als 
lyncht mich nicht sofort.)
Gast #1527701
Lesenswert?

Ist es also so richtig?
1
#include  <avr\io.h>    // AVR Register und Konstantendefinitionen
2
#include   <util\delay.h>  // Bibliothek mit Warteroutinen
3
#include <stdint.h>
4
#define   F_CPU 3686400  // Taktfrequenz des myAVR-Boards
5

6

7
// Define baud rate
8

9
#define USART_BAUD 9600ul
10

11
#define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1)
12

13

14
void USART_vInit(void)
15

16
{
17

18
// Set baud rate
19

20
UBRRH = (uint8_t)(USART_UBBR_VALUE>>8);
21

22
UBRRL = (uint8_t)USART_UBBR_VALUE;
23

24

25
// Set frame format to 8 data bits, no parity, 1 stop bit
26

27

28

29

30

31
//Hier die Änderung:
32

33

34
UBRRH = 0x02;
35

36
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ1);
37

38

39
//Änderungende
40

41

42

43

44

45

46
// Enable receiver and transmitter
47

48
UCSRB = (1<<RXEN)|(1<<TXEN);
49

50
}
51

52

53
void USART_vSendByte(uint8_t u8Data)
54

55
{
56

57
// Wait if a byte is being transmitted
58

59
while((UCSRA&(1<<UDRE)) == 0);
60

61
// Transmit data
62

63
UDR = u8Data;
64

65
}
66

67

68
uint8_t USART_vReceiveByte()
69

70
{
71

72
// Wait until a byte has been received
73

74
while((UCSRA&(1<<RXC)) == 0);
75

76
// Return received data
77

78
return UDR;
79

80
}
81

82

83
int main(void)
84

85
{
86

87
uint8_t u8Data;
88

89

90
// Initialise USART
91

92
USART_vInit();
93

94

95
// Send string
96

97
USART_vSendByte('A');
98

99
// Repeat indefinitely
100

101
for(;;)
102

103
{
104

105
// Echo received characters
106

107
u8Data  = USART_vReceiveByte();
108

109
USART_vSendByte(u8Data);
110

111
}
112

113
}
Gast #1527764
Lesenswert?

Mit solchen Fragen 1 Min. später ohne jegliche Initiative selbst im 
Datenblatt zu lesen machst du dich nicht beliebt.

// Set frame format to 8 data bits, no parity, 1 stop bit
UCSRC = (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);

Over and out.
Gast #1528093
Lesenswert?

Danke, leider funktioniert es weiterhin nicht:
1
#include  <avr\io.h>    // AVR Register und Konstantendefinitionen
2
#include   <util\delay.h>  // Bibliothek mit Warteroutinen
3
#include <stdint.h>
4
#define   F_CPU 3686400  // Taktfrequenz des myAVR-Boards
5

6

7
// Define baud rate
8

9
#define USART_BAUD 9600ul
10

11
#define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1)
12

13

14
void USART_vInit(void)
15

16
{
17

18
// Set baud rate
19

20
UBRRH = (uint8_t)(USART_UBBR_VALUE>>8);
21

22
UBRRL = (uint8_t)USART_UBBR_VALUE;
23

24

25
// Set frame format to 8 data bits, no parity, 1 stop bit
26

27

28

29

30

31
//Hier die Änderung:
32

33
UCSRC = (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
34

35
//Änderungende
36

37

38

39

40

41

42
// Enable receiver and transmitter
43

44
UCSRB = (1<<RXEN)|(1<<TXEN);
45

46
}
47

48

49
void USART_vSendByte(uint8_t u8Data)
50

51
{
52

53
// Wait if a byte is being transmitted
54

55
while((UCSRA&(1<<UDRE)) == 0);
56

57
// Transmit data
58

59
UDR = u8Data;
60

61
}
62

63

64
uint8_t USART_vReceiveByte()
65

66
{
67

68
// Wait until a byte has been received
69

70
while((UCSRA&(1<<RXC)) == 0);
71

72
// Return received data
73

74
return UDR;
75

76
}
77

78

79
int main(void)
80

81
{
82

83
uint8_t u8Data;
84

85

86
// Initialise USART
87

88
USART_vInit();
89

90

91
// Send string
92

93
USART_vSendByte('A');
94

95
// Repeat indefinitely
96

97
for(;;)
98

99
{
100

101
// Echo received characters
102

103
u8Data  = USART_vReceiveByte();
104

105
USART_vSendByte(u8Data);
106

107
}
108

109
}
#1528125
Lesenswert?

Tim schrieb:
> Danke, leider funktioniert es weiterhin nicht:


Du sendest am Anfang ein einzelnes 'A'.
Siehst du das auf der anderen Seite?

Was ist wenn du den µC einfach mal ständig 'A' senden lässt? Kommen die 
auf der anderen Seite richtig an?

Und bitte: Zieh den Code doch nicht so in die Länge! Code wird nicht 
übersichtlicher, wenn man mehr Leerzeilen einfügt. Er zieht sich nur in 
die Länge und sonst gar nichts. Wenn du Übersicht haben willst, dann 
kümmere dich um die Einrückungen.
#1528134
Lesenswert?

Andreas Guter schrieb:
> Nein, es kommt rein gar nichts an. Weder die As, noch die
> Repeater-Funktion.
> Ich mache das ganze übrigens mit hterm unter Windows Vista, da ich kein
> anderes Betriebssystem zu Verfügung habe.

Dann solltest du fürs erste den Repeater zur Seite legen und dich nur 
auf das Senden konzentrieren (eine Fehlerquelle weniger).

http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

Insebsondere könntest du mit dem vorletzten Punkt im Abschnitt "Sonstige 
Fehlerquellen bei UART/USART" anfangen und zunächst feststellen ob die 
Hardware-Kette vom µC zum PC in Ordnung ist, bzw. ob das Kabel korrekt 
ausgekreuzt ist. Diesen Test würde ich dir zur Sicherheit sowieso 
empfehlen. Solange dieser Test nicht einwandfrei klappt, hat es keinen 
Sinn nach anderen Ursachen zu fahnden.
Also: Mega8 aus dem Sockel raus. RX/TX im Sockel mit einem Stück Draht 
verbinden und im hTerm drauflosklimpern. Alles was du tippst, muss im 
hTerm auch aufscheinen. Gegentest machen: Drahtbrücke entfernen. Jetzt 
darf Getipptes im hTerm nicht mehr aufscheinen.
Gast #1528192
Lesenswert?

Das Programm im Anhang ist dein neustes Programm leicht geändert für 
einen Test mit Attiny2313 @ 8 MHz. Dein Programm funktioniert. Ich 
vermute daher ein Hardwareproblem.

Prüfe dein RS232-Kabel.

Bei dem myAVR Board MK1 LPT endet TXD des Atmega auf Pin 3 des 
DB9-Anschlusses. 
http://shop.myavr.de/index.php?ws=download_file.ws.php&dlid=44&filename=produkte/myavr_board_mk1/techb_schaltplan-myavr-board-mk1-lpt.png 
D.h. das Board ist beschaltet sich wie ein PC (DTE Data Terminal 
Equipment). Zur Verbindung zweiter DTEs also myAVR<->PC brauchst du ein 
sog. Nullmodemkabel mit gekreuzten Leitungen.

Bei dem myAVR Board MK2 USB, Version 2.1 ist das im Schaltplan nicht 
offensichtlich. Ich vermute aber, es ist genauso wie beim MK1 
implementiert.

Zusätzlich kannst du noch auf dem myAVR Board CTS/RTS per Jumper 
brücken. Wenn der PC auf Hardwareflusskontrolle eingestellt wäre, würde 
das helfen. Und wenn er nicht auf Hardwareflusskontrolle eingestellt 
ist, schadet es nicht.

Die Übertragungsstrecke (Buchsen, Kabel, MAX232) kannst du ausserdem so 
prüfen: Atmega8 in den Dauerreset versetzen (z.B. Drahtjumper RESET nach 
GND). RXD und TXD sind dann als Eingang geschaltet. Dann Drahtjumper 
zwischen RXD und TXD anbringen. Jedes vom PC aus gesendete Zeichen 
sollte jetzt als Echo zurückkommen. Die drei Buchsen für die Jumper 
sitzen unmittelbar am Atmega8.
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren