Author Topic: Serial communication from ATMEGA32 to PC via USART and Serial to USB converter  (Read 10788 times)

0 Members and 1 Guest are viewing this topic.

Offline jkernsTopic starter

  • Robot Overlord
  • ****
  • Posts: 270
  • Helpful? 12
OK, I must be overlooking something basic.

Hardware:

ATMEGA32, external 8MHz crystal and 18pF caps (tried the internal oscilator at 8MHzalso)
https://www.sparkfun.com/products/9716? Serial USB converter - this appears to be set up for 9600 baud, 8 data bits, no parity, one stop bit when I look at the port properties.
Windows 7 professional laptop.

Fuses
High byte = 99 CKOPT = 1
Low Byte = EF CKSEL3,2,1,0 all = 1
That should select the external crystal.


What has worked.

Loop back test connecting TX, RX at the ATMEGA32 - I can write / read a byte and control some LEDs.
Loop back test of the Sparkfun converter - connecting TX RX I get characters echoed back to the terminal emulator.
With everything hooked up (all on a breadboard) I get flashing lights on the USB - serial converter

What doesn't work:

It appears that no matter what I write to the UART, the PC is recieving 00 hex.

I've tried writing to the UART a couple different ways, I've tried running the UART at double speed (and changing the baud rate calculation to shift 3 instead of 4)

I suspect that I am somehow getting the wrong baud rate - but when I compare to sample code from multiple sources I seem to be doing the same calculations.

I've tried printf and just shoving the byte into the register as you can see from the bits of code that have been commented in/out. Results are pretty much the same. Writing a string gives a longer flash on the RX light on the sparkfun board than just writing a byte.

Code:

Code: [Select]
/*
 * URTTest.c
 *
 * Created: 9/13/2012 11:52:21 AM
 *  Author: jkerns
 */


#include <avr/io.h>
//#include <util/delay.h>
//#include <stdint.h>
#include <stdio.h>

// Define baud rate
#define F_CPU 8000000ul

//#define USART_BAUD 115200ul
#define USART_BAUD 9600ul

#define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1)  //was 4 (*16)
//From data sheet: UBBR for Asynchronous Double Speed Mode (U2X = 1)
// UBRR = (fOSC / 8*BAUD) -1



static int uart_putchar(char c, FILE *stream);
uint8_t uart_getchar(void);

// I have no clue what this means.
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

 void USART_vInit(void)
 
 {
 
 // this seems to match the example in the data sheet.
 
  // Set baud rate
 
 UBRRH = (uint8_t)(USART_UBBR_VALUE>>8);
 
 UBRRL = (uint8_t)USART_UBBR_VALUE;
 
  // Set frame format to 8 data bits, no parity, 1 stop bit
 
 UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
 
  // Enable receiver and transmitter
 
 UCSRB = (1<<RXEN)|(1<<TXEN);
 
  // double usart speed - shift a 1 into U2X (bit 1) in USCRA
 
 //UCSRA = (1<< U2X);
 
 }
 
 
   // previously used versions of the functions to send / recieve
  void USART_vSendByte(uint8_t u8Data)
 
  {
 
   // Wait if a byte is being transmitted
 
  while((UCSRA&(1<<UDRE)) == 0);
  { }
 
   // Transmit data
 
  UDR = u8Data;
 
  }
 
  uint8_t USART_vReceiveByte(void)
 
  {
 
   // Wait until a byte has been received
 
  while((UCSRA&(1<<RXC)) == 0);
 
   // Return received data
 
  return UDR;
 
  }



int main(void)
{
DDRB = 0b00001111;  // 4 outputs on port B
    PORTB = 0b00000000; // all low
   
// what is this for?
TCCR1B |= 1<<CS10 | 1<<CS11; //set scaling to 64 ticks

    uint8_t LEDNumber = 0;  // unsigned 8 bit
//uint8_t LEDNumberx = 0;
uint8_t u8Data;

// Initialize USART
USART_vInit();
 
 stdout = &mystdout; //Required for printf init per sparkfun example



while(1)
{

if( TCNT1 > 122072/2)  // one second 1000* 8,000,000/65,535
// max value 65535!!!!
{
   TCNT1 = 0;
   LEDNumber ++; // next "number"
   
   if (LEDNumber > 0b1111)
   {
   LEDNumber = 0;
   }
   
   
   // from Sparkfun example...
   //printf("Test it! LEDNumber = %d \n", LEDNumber);
   
   
   
//Send string 
   USART_vSendByte('a');
 
   //u8Data = USART_vReceiveByte();

   
  // PORTB = u8Data; //LEDNumber;  // output the value in binary
    PORTB = LEDNumber;


}

}






// Echo received characters

//u8Data = USART_vReceiveByte();

//USART_vSendByte(u8Data);

}



//send / recieve from sparkfun example


 static int uart_putchar(char c, FILE *stream)
 {
     if (c == '\n') uart_putchar('\r', stream);
   
//insert code cut / pasted from data sheet.
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
 
  UDR = c;
     
     return 0;
 }
 
 uint8_t uart_getchar(void)
 {
     // more cut/paste from data sheet.
      /* Wait for data to be received */
      while ( !(UCSRA & (1<<RXC)) )
      ;
 
     return(UDR);
 }
« Last Edit: September 18, 2012, 10:07:04 AM by jkerns »
I get paid to play with robots - can't beat that with a stick.

http://www.ltu.edu/engineering/mechanical/bachelor-science-robotics-engineering.asp

Offline jkernsTopic starter

  • Robot Overlord
  • ****
  • Posts: 270
  • Helpful? 12
Progress...

I put a scope on the serial line. It is transmitting an ascii "a" but it does appear that the speed is wrong.
I am measuring 3.2msec per bit. At 9600 baud I think it should be .104 msec. That would explain why I am getting garbage at the PC, but not where I've boogered up the calculation of the baud rate.

I wasn't able to measure the clock directly (putting the scope across the crystal just brought things to a halt).

It is running faster than it was on the default 1MHz internal clock based on the rate at which the LEDs count up.
I get paid to play with robots - can't beat that with a stick.

http://www.ltu.edu/engineering/mechanical/bachelor-science-robotics-engineering.asp

Offline jkernsTopic starter

  • Robot Overlord
  • ****
  • Posts: 270
  • Helpful? 12
Fixed...

Code change:
 
Code: [Select]
UCSRB = (1<<RXEN)|(1<<TXEN);
 /* Set frame format: 8data, 1stop bit */
 UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
  // Set frame format to 8 data bits, no parity, 1 stop bit
 
 //UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
 
  // Enable receiver and transmitter
 
 //UCSRB = (1<<RXEN)|(1<<TXEN);
 


I replaced the stuff to write to UCSRC with the sample provided in the data sheet. The difference appears to be the "1<<URSEL" is added.

I tried playing around with the pre-scale number for the baud rate control - just inserting random numbers did not seem to actually change the pulse duration as seen on the scope. So the UCSCR write must not have actually changed the register without the URSEL bit

Quote
Bit 7 – URSEL: Register Select
This bit selects between accessing the UCSRC or the UBRRH Register. It is read as one when
reading UCSRC. The URSEL must be one when writing the UCSRC.

Read the data sheet, eh?
I get paid to play with robots - can't beat that with a stick.

http://www.ltu.edu/engineering/mechanical/bachelor-science-robotics-engineering.asp