Search code examples
arduinointerruptuartserial-communicationatmega

UART Receiving keyboard input doesn't work


I am having trouble with reading data sent from my laptop to the microcontroller via UART. The transmitting part works fine - I can send data to my laptop without problems, but echoing data, or reading keyboard input data from the laptop doesn't work. I have tried to implement reading both with polling and with Rx interrupt routines, but without success. The microcontroller I am using is ATMEGA2560, and I am conntected to my laptop via FTD1232 USB to TTL serial converter.

I am using Putty as a serial comm terminal, and the Arduino IDE for programming.

I am assuming that the problem is not in the hardware based on the following - I have tried initializing different USARTs and tried to use different COM ports, as well as another USB to TTL converter, various wires, but the result is the same. I have also connected another power source to supply enough voltage to all devices.

I am trying to get at least a response by turning a LED on when Rx interrupt occurs (when I type something in the terminal).

~

#define F_CPU 16000000UL //16MHz
#define BAUD 115200UL //bps
#define BAUD_PRESCALER (((F_CPU/(BAUD*8UL)))-1) //Table 101, page 212

volatile uint8_t temp;

void UART_init(){
  //Set baud rate
  UBRR0H = (uint8_t)(BAUD_PRESCALER >> 8); //Higher portion of the baud rate
  UBRR0L = (uint8_t)BAUD_PRESCALER; //Lower portion of the baud rate

  //Enable Receiver and Transmitter
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  //Set frame format: 8-bit format, 1 stop bit, no parity
  UCSR0C |= (3 << UCSZ00);
  UCSR0C &= ~(1 << USBS0); //clear for 1 stop bit

  //Set Double Speed Asynchronous mode
  UCSR0A |= (1 << U2X0);

  UCSR0B |= (1 << RXCIE0); //Enables interrupt rxc
}

uint8_t UART_getchar(){
  //Wait for RXC flag
  while(!(UCSR0A & (1 << RXC0))){};
  return UDR0;
}

//Arduino setup()
void setup(){
  pinMode(8, OUTPUT);
  UART_init();
  sei();
}

//Arduino loop()
void loop(){
  delay(500);
  UART_putchar('a');
}

ISR(USART0_RX_vect){
  temp = UDR0;
  digitalWrite(8, HIGH);
}

It is a lenghty post, but I tried to be specific and also post the whole code. The datasheet I am using for the ATMEGA2560 can be found here.

My Putty settings:

COM Port Settings


Solution

  • I've just tested it on my Mega board and it's working fine without interrupts enabled (simple loopback):

    #define BAUD 115200UL
    #define BAUD_PRESCALER (((F_CPU/(BAUD*8UL)))-1)
    
    volatile uint8_t temp;
    
    void UART_init(){
      //Set baud rate
      UBRR0H = (uint8_t)(BAUD_PRESCALER >> 8); //Higher portion of the baud rate
      UBRR0L = (uint8_t)BAUD_PRESCALER; //Lower portion of the baud rate
    
      //Enable Receiver and Transmitter
      UCSR0B = (1 << RXEN0) | (1 << TXEN0);
      //Set frame format: 8-bit format, 1 stop bit, no parity
      UCSR0C |= (3 << UCSZ00);
      UCSR0C &= ~(1 << USBS0); //clear for 1 stop bit
    
      //Set Double Speed Asynchronous mode
      UCSR0A |= (1 << U2X0);
    //  UCSR0B |= (1 << RXCIE0); //Enables interrupt rxc
    }
    
    uint8_t UART_getchar(){
      //Wait for RXC flag
      while(!(UCSR0A & (1 << RXC0))){};
      return UDR0;
    }
    
    void UART_putchar(uint8_t data){
      //Do nothing until UDR is ready
      while(!(UCSR0A &(1 << UDRE0))){};
      UDR0 = data;
    }
    
    void UART_putstring(uint8_t *data){
      while(*data != 0x00){
        UART_putchar(*data);
        data++;
      }
    }
    
    //Arduino setup()
    void setup(){
      pinMode(8, OUTPUT);
      UART_init();
      sei();
    }
    
    //Arduino loop()
    void loop(){
      UART_putchar(UART_getchar());
    }
    
    /*ISR(USART0_RX_vect){
      temp = UDR0;
      digitalWrite(8, HIGH);
    }*/
    

    RX interrupt must be disabled, otherwise Serial interrupt vector is taking place and polled get char can't work as characters are readed by ISR