Ik heb een probleempje met het versturen van data van een atmega8 naar de seriële poort.

Verbindingen zijn als volgt:
PD0 (atmega8) -> R1OUT (MAX232N)
PD1 (atmega8) -> T1IN (MAX232N)

Ik gebruik de interne klok, aan 1MHz.

Onderstaande code is een vereenvoudigde versie van http://www.nitt.edu/portal/rmi/home/projects/avr_usart_for_serial_comm…


#define F_CPU 1000000
#define USART_BAUDRATE 1200
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#include <avr/io.h>
#include <util/delay.h>

void usart_init()
{
  UCSRB |= (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
  UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1)|(1<<UPM1); // Use 8-bit character sizes even parity
  UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
  UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
}

void usart_putch(unsigned char send)
{
  while ((UCSRA & (1 << UDRE)) == 0) {};
  UDR = send;
}

void usart_puts(unsigned char *stringptr)
{
   while (*stringptr != 0x00)
   {
      usart_putch(*stringptr);
      stringptr++;
   }
}

int main (void)
{
  unsigned char str[] = "Ready For Transmission.";
  DDRB=0xff;
  usart_init();
  _delay_ms(1000); 

  while(1) // Loop forever
  {
  	usart_puts(str);
  	usart_putch(0x0D);
  	usart_putch(0x0A);
	_delay_ms(1000);
  }
}

Op de PC (gtkterm op Ubuntu, baud 1200, parity even, 8 bits) geeft dit een reeks onleesbare characters:


ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_
...

In hex:


FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
5F 04 0D 0A FF FF FF FF
...

Ik heb ook andere firmware en terminals geprobeerd maar zonder resultaat. Iemand nog een ander idee?

Bedankt!


void usart_putch(unsigned char send)
{
  while ((UCSRA & (1 << UDRE)) == 0) {};
  UDR = send;
}

Het UDRE-bit is hoog, zolang de USART "bezet" is. Moet dus zijn:


  while ((UCSRA & (1 << UDRE)) != 0) {};

Het UDRE-bit is hoog, zolang de USART "bezet" is.

Heb het even geprobeerd, maar nu krijg ik helemaal geen data meer. Op http://www.captain.at/electronic-atmega16-serial-port.php wordt bovendien ook op ==0 getest. Het aantal ontvangen characters lijkt ook overeen te komen met de lengte van str[]...

Op 8 augustus 2009 15:56:20 schreef pros:


Het UDRE-bit is hoog, zolang de USART "bezet" is. Moet dus zijn:
[code]
  while ((UCSRA & (1 << UDRE)) != 0) {};

Sorry Pros maar dit ies fout. Het UDRE is het USART DATA REGSITER EMPTY bit en is 1 als de Usart nieuwe data kan ontvangen.
Dus de oorspronkelijke code was correct.
Zie ook in de datadump dat de 0x0A en 0x0D wel goed verzonden worden. Moet ergens in de uart_puts wat fout gaan. Zie alleen nog niet wat.
edit: lijkt toch een beetje op een niet correcte buadrate. Mocht je een scoop ter beschikking hebben meet dan eens de bit-tijd. Dit gaat het makkelijkst als je continue een 'U' verzendt.

[Bericht gewijzigd door driessens_nl op (15%)]

Ik heb een tijdje geleden een gelijkaardig probleem gehad bij het schrijven naar een LCD. Ik heb de code even opgesnord en het werkt zowaar:


#include <avr/pgmspace.h> 

void usart_puts(unsigned char *stringptr)
{
	while(pgm_read_byte(stringptr) != 0x00){
		usart_putch(pgm_read_byte(stringptr));
		stringptr++;
	}
}

usart_puts(PSTR("test"));

Nu ben ik wel heel benieuwd waarom voorbeeldcode nooit werkt bij mij, en ik altijd dergelijk kunst- en vliegwerk moet toepassen. Kan het iets te maken hebben met de configuratie van mijn chip (fuses)?

Op 8 augustus 2009 16:19:41 schreef driessens_nl:
Sorry Pros maar dit ies fout. Het UDRE is het USART DATA REGSITER EMPTY bit en is 1 als de Usart nieuwe data kan ontvangen.

Mijn fout, idd. Ik had "loop_until_bit_is_set(UCSRA, UDRE);" snel even vertaald naar een while()-lus. |:(

Het kan ook liggen aan het feit dat je geen kristal gebruikt als kloksource. De baudrate kan dan op het randje van de maximale afwijking zitten.

Als je de mogelijkheid hebt om een kristal aan te sluiten kun je dat altijd even proberen.

Op 8 augustus 2009 22:43:33 schreef shizzle dizzle:
Het kan ook liggen aan het feit dat je geen kristal gebruikt als kloksource. De baudrate kan dan op het randje van de maximale afwijking zitten.

Als je de mogelijkheid hebt om een kristal aan te sluiten kun je dat altijd even proberen.

Ik denk dat de gebruikte baudrate voldoende laag is voor mijn kloksnelheid. Wanneer ik enkel putch gebruik en niet puts dan lukt het trouwens wel. Het probleem moet toch iets met die pointer te maken hebben. Zolang ik program memory gebruik gaat alles probleemloos, maar met RAM lijkt het niet te lukken...

In de datasheet staan keurig voorbeeld codes, zowel in c als asm. http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf vanaf pag. 139.

Als die code niet werkt, ligt het aan je hardware of je fuse-instelling.

In de datasheet staat helaas geen code om strings te versturen, enkel losse characters. Ik heb even een verse IC geprobeerd zonder iets aan de fuses te veranderen en dat geeft hetzelfde resultaat :(

Ow, het gaat om strings. Even zoeken i heb ergens een stukje werkende code om strings via de uart te versturen. Heb ik jaren geleden gebruikt om teksten naar een pc te sturen. Zoals "Hello world, I'm ATmega128, press enter and I do all what you want"

Edit:
Ben nog aan het zoeken, maar als je zelf even naar strlen zoekt.

[Bericht gewijzigd door WilToyo op (13%)]

Het probleem is min of meer opgelost. Blijkbaar werkte alles wel naar behoren met AVR Studio op Windows. Ik heb dan maar de commando's overgenomen in Ubuntu en daar lukt het nu ook. Geen idee waarom, ik zal de command line options eens in detail bekijken...

ter info, usart_puts werkt niet


avr-gcc -mmcu=atmega8 -Wall -O1 -o firm2.elf firm2.c
avr-objcopy -j .text -O ihex firm2.elf firm2.hex
avrdude -p m8 -c avrusb500 -e -U flash:w:firm2.hex -v

usart_puts werkt wel


avr-gcc -mmcu=atmega8 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT firm2.o -MF firm2.o.d -c firm2.c
avr-gcc -mmcu=atmega8 -Wl,-Map=firm2.map firm2.o -o firm2.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature firm2.elf firm2.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex firm2.elf firm2.eep || exit 0
avr-objdump -h -S firm2.elf > firm2.lss
avrdude -p m8 -c avrusb500 -e -U flash:w:firm2.hex -v

Er is wel nog een (vreemd) probleempje bijgekomen: blijkbaar werkt mijn schakeling enkel als de programmer verbonden is. Ik heb wat getest en hij doet het wanneer één van de programmer pinnen (gelijk welke!) verbonden is met ofwel VCC ofwel GND (maakt opnieuw helemaal niets uit welke)...

Voedingsspanning stabiel?
AVR goed ontkoppeld?
Zowel Vcc als AVcc van spanning voorzien?
AGND ook aangesloten?

Ik heb je programma even uitgetest, met enkele wijzigingen:
USART ingesteld zonder parity (8N1, dus).
De while-lus spuwt eindeloos 'U' uit.

De frequentie van het uitgangssignaal bedroeg 597Hz. Dat wijkt iets af van de ideale 600Hz, maar het verschil is te klein om foutief geïnterpreteerd te worden.

Op 9 augustus 2009 22:42:27 schreef pros:
Voedingsspanning stabiel?
AVR goed ontkoppeld?
Zowel Vcc als AVcc van spanning voorzien?
AGND ook aangesloten?

Alles gecheckt, gewoon een led laten flikkeren lukt trouwens wel, enkel gegevens versturen via usart niet. Dit is trouwens het circuit waar ik mij op gebaseerd heb: http://img35.imageshack.us/img35/1460/miniboardinternalclock.png

Probleem opgelost, pin 5 van mijn DB9 connector was niet geaard...

[Bericht gewijzigd door pieterprovoost op (62%)]