Forum: Compiler & IDEs Mega168 Modul Seriell ansprechen


von Moritz S. (mollitz)


Lesenswert?

Hi,

Ich sitz jetzt schon Tage daran meinen 
ATMega168(http://embedit.de/content/view/37/26/) seriell anzusprechen.
Ich habs mit mehreren eigenen und mehreren kopierten(aus dem Internet) 
Quelltexten und mit Linux und Windows probiert.
Hier mal ein Beispiel aus dem Internet, das einwandfrei kompiliert:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

int main (void)
{
  DDRB = 0xff;
  PORTB = 0xff;
  UCSR0B |= (1 << RXEN0) | (1 << TXEN0);   // Turn on the transmission 
and reception circuitry
   UCSR0C |= (1 << UMSEL00) | (1 << UCSZ00) | (1 << UCSZ01); // Use 
8-bit character sizes

   UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value 
into the low byte of the UBRR register
   UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate 
value into the high byte of the UBRR register

   UCSR0B |= (1 << RXCIE0) | (1 << RXC0); // Enable the USART Recieve 
Complete interrupt (USART_RXC)
   sei(); // Enable the Global Interrupt Enable flag so that interrupts 
can be processed
   while(1);
}

ISR(SIG_USART_RECV)
{
   char ReceivedByte;
   ReceivedByte = UDR0; // Fetch the recieved byte value into the 
variable "ByteReceived"
   UDR0 = ReceivedByte; // Echo back the received byte back to the 
computer
   if(PORTB == 0xff)
     PORTB = 0x00;
   else
     PORTB = 0xff;
}

Die 3 wichtigen Pins RxD, TxD und Ground sind mit dem PC verbunden( RxD 
und TxD sind gekreuzt).
Signale geb ich mit SuperTerm 2. Ich Connecte mit der Baudrate 9600 auf 
den entsprechenden COM-Port und schreib was ins Terminal-> Nichts 
passiert.

Was mir unter Linux mit einem anderen Quelltext, in dem nur das RXEN0 
angeschaltet sein musste und ein serielles Signal ankommen musste, 
passiert ist, war dass der Controller einfach gar nichts mehr getan hat. 
(Da war eine while Schleife, die die Lampe immer an und ausgeschalten 
hatte und wo das Byte kam, blieb die Lampe an bzw. aus).

Sicher ist das ganze ein Anfängerfehler da ich aber schon ewig 
rumprobiere, kann ich grad echt nicht weitergooglen. Ich finde einfach 
nichts mehr, weil ich nicht weiß obs am PC, am Kabel, am Controller oder 
sonst was liegt.

Für Hilfe wär ich sehr dankbar,

Moritz

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Moritz Sch wrote:

> Hier mal ein Beispiel aus dem Internet, das einwandfrei kompiliert:

Bitte benutze [c]-Markierungen um deine Quelltexte, sonst kann die
keiner mehr lesen.

> Die 3 wichtigen Pins RxD, TxD und Ground sind mit dem PC verbunden( RxD
> und TxD sind gekreuzt).

Aber RS-232-Levelshifter (und -Inverter) hast du drin, ja?

von Stefan P. (form)


Lesenswert?

Hast Du einen Pegelwandler zwischen AVR und PC?
Die TTL-Signale (0V 5V) müssen erst noch auf höhere Pegel (+12V -12V) 
gebracht werden, damit der PC damit was anfangen kann.

z.B. Der MAX232 ist dafür da.....

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan P. wrote:

> Hast Du einen Pegelwandler zwischen AVR und PC?
> Die TTL-Signale (0V 5V) müssen erst noch auf höhere Pegel (+12V -12V)
> gebracht werden, damit der PC damit was anfangen kann.

Vor allem müssen sie negiert werden.  Viele PC-Schnittstellen
würden vermutlich statt ±12 V ganz brauchbar mit 0 V / 5 V
hinkommen, aber dummerweise entspricht TTL/CMOS-High einem
RS-232-Pegen von -(5...12) V und TTL/CMOS-Low einem RS-232-Pegel
von +(5...12) V.

von Moritz S. (mollitz)


Lesenswert?

1
Auf dem Modul ist ein Pegelwandler für RS232 Signale untergebracht. Dadurch kann das Modul von
2
einem PC gesteuert werden oder kann selbst über die serielle Schnittstelle andere Geräte steuern. Die
3
RS232 Signale sind auf einer 10 poligen Stiftleiste herausgeführt wie sie auch auf einem PC Mainboard zu
4
finden sind.
Ein Pegelwandler ist auf dem Modul. Ich geh mal davon aus, dass er die 
Signale gleich noch mit invertiert.

von Moritz S. (mollitz)


Lesenswert?

Hi,

Also ich habe jetzt mal einen neuen Code (unter Linux) probiert:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include <stdint.h>
5
#include <util/delay.h>
6
7
#define USART_BAUD_RATE 9600
8
#define USART_BAUD_SELECT (F_CPU/(USART_BAUD_RATE*16L)-1)
9
10
11
uint16_t gloFrequ;
12
13
int main()
14
{
15
  //SREG |=(1<<7);
16
  sei();
17
18
  UBRR0H = (unsigned char)(USART_BAUD_SELECT>>8);
19
  UBRR0L = (unsigned char)USART_BAUD_SELECT;
20
  UCSR0B = (1<<RXEN0)|(1<<TXEN0) | (1<<RXCIE0);
21
  /* Set frame format: 8data, 2stop bit */
22
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
23
24
  DDRC = 0xff;
25
  DDRB = 0xff;
26
  //register aktivieren
27
  PORTB = 0xff;
28
  PORTC = 0xff;
29
  gloFrequ=500;
30
  //lichter an aus
31
  while(1)
32
  {
33
    _delay_ms(gloFrequ);
34
    if(PORTB == 0xff)
35
      PORTB = 0x00;
36
    else if(PORTB == 0x00)
37
      PORTB = 0xff;
38
  }
39
  return(0);
40
}
41
42
ISR(USART_RX_vect)
43
{
44
  gloFrequ = 100;
45
  PORTC = 0xFF;
46
}
47
48
//
und folgendes festgestellt: Sende ich ein Byte auf den seriellen Port, 
dann wird der Controller um ca. 1/10 langsamer. (die Lampe blinkt 
langsamer).
der code in ISR(USART_RX_vect) wird nicht ausgeführt. (PORTC wird nicht 
aktiviert und die lampe blinkt nach senden eines Bytes unabhängig von 
gloFrequ = ...; immer gleich schnell.
Kommentiere ich die ISR-Funktion komplett aus, dann bleibt der 
Controller ganz stehen (die Lampe bleibt bei dem Wert, als das Byte 
gesendet wurde).

Ideen?

Gruß Moritz

von Michael P. (mipo)


Lesenswert?

Du nutzt ein _delay_ms(), daher musst Du die Optimierung anschalten, 
damit das richtig funktioniert, hast Du das? (siehe 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29)

Ist das Modul tatsächlich mit 20 MHz getaktet, sprich sind die Fuses 
richtig gesetzt? (http://www.mikrocontroller.net/articles/AVR_Fuses)

Wo wird F_CPU definiert? Makefile? Einfach mal "#define F_CPU 20000000" 
Testweise ausprobieren.

Ansonsten 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_UART

von Moritz S. (mollitz)


Lesenswert?

Erstmal zu dem Mhz-Problem: Ich verwende Eclipse AVR Plugin und da kann 
ich den Projekt-Einstellungen die Frequenz einstellen. Wenn ich die 
verändere verändert sich auch die Geschwindigkeit mit der die Lampe 
blinkt.
Und wenn ich die Frequenz auf 20000000 stelle, dann blinkt die Lampe 
auch so schnell wie sie soll. (In meinem Code einmal an und einmal aus 
pro Sekunde). Das heißt doch, dass F_CPU richtig ist oder?

von Stefan E. (sternst)


Lesenswert?

> der code in ISR(USART_RX_vect) wird nicht ausgeführt.

Vermutlich doch.

> (PORTC wird nicht aktiviert

Was soll denn da aktiviert werden? Du setzt den Port doch schon in 
main auf 0xFF, wie soll denn das "PORTC = 0xFF;" in der ISR noch 
irgendetwas sichtbares bewirken?

> und die lampe blinkt nach senden eines Bytes unabhängig von
> gloFrequ = ...; immer gleich schnell.

Weil du gloFrequ nicht volatile deklariert hast.

Und dass der Controller scheinbar langsamer wird, liegt daran, dass du 
in der ISR das UART-Datenregister nicht ausließt. Deshalb wird der 
Interrupt nach Verlassen der ISR sofort (naja, fast sofort, nach einem 
Befehl) wieder ausgelöst, und die ISR wird daher immer und immer wieder 
ausgeführt.

von Moritz S. (mollitz)


Lesenswert?

Hi,

Hab grad nicht so viel Zeit, werd mich aber nachher vielleicht mal drann 
setzen und das Register auslesen.

von Moritz S. (mollitz)


Lesenswert?

Vielen Dank jetzt tuts:
1
#ifndef F_CPU
2
#define F_CPU 20000000UL
3
#endif
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
8
#include <stdint.h>
9
#include <util/delay.h>
10
11
12
#define USART_BAUD_RATE 9600
13
#define USART_BAUD_SELECT (F_CPU/(USART_BAUD_RATE*16L)-1)
14
15
16
volatile uint16_t gloFrequ;
17
18
int main()
19
{
20
  //SREG |=(1<<7);
21
  sei();
22
23
  UBRR0H = (unsigned char)(USART_BAUD_SELECT>>8);
24
  UBRR0L = (unsigned char)USART_BAUD_SELECT;
25
  UCSR0B = (1<<RXEN0)|(1<<TXEN0) | (1<<RXCIE0);
26
  /* Set frame format: 8data, 2stop bit */
27
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
28
29
  DDRC = 0xff;
30
  DDRB = 0xff;
31
  //register aktivieren
32
  PORTB = 0xff;
33
  gloFrequ=500;
34
  //lichter an aus
35
  while(1)
36
  {
37
    _delay_ms(gloFrequ);
38
    if(PORTB == 0xff)
39
      PORTB = 0x00;
40
    else if(PORTB == 0x00)
41
      PORTB = 0xff;
42
  }
43
  return(0);
44
}
45
46
ISR(USART_RX_vect)
47
{
48
  gloFrequ = UDR0*5;
49
}

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.