From f2fdee42e25fafe445fc37e695ce736b82610a7a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 12 Nov 2013 16:01:36 +0200 Subject: [PATCH] Add function to change serial port baud rate on the fly --- common/serial.c | 25 ++++++++++++++++++++++--- common/serial.h | 1 + 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/common/serial.c b/common/serial.c index 8874c3e..6bf730c 100644 --- a/common/serial.c +++ b/common/serial.c @@ -1,5 +1,6 @@ #include #include +#include "delay.h" #include "ringbuffer.h" #include "serial.h" @@ -18,19 +19,37 @@ static uint8_t rx_overrun; #define INTERRUPTS 0 #endif +static inline void set_baud(uint16_t baud) +{ + baud = (F_CPU/16+baud/2)/baud-1; + UBRR0H = baud>>8; + UBRR0L = baud; +} + void serial_init(uint16_t baud) { DDRD = (DDRD&~0x03) | 0x02; PORTD &= ~0x03; - baud = (F_CPU/16+baud/2)/baud-1; - UBRR0H = baud>>8; - UBRR0L = baud; + set_baud(baud); UCSR0A = 0; UCSR0C = BIT(UCSZ00) | BIT(UCSZ01); // 8N1 UCSR0B = BIT(RXEN0) | BIT(TXEN0) | INTERRUPTS; } +void serial_set_baud(uint16_t baud) +{ +#ifdef SERIAL_ASYNC + while(!(UCSR0A&BIT(UDRE0))) ; +#endif + /* It's impossible to reliably find out when transmission has finished. + Wait for one character duration to be safe. */ + uint16_t delay = (UBRR0H<<8)|UBRR0L; + for(uint8_t i=0; i<40; ++i) + delay_loop16(delay); + set_baud(baud); +} + uint8_t serial_read() { #ifdef SERIAL_ASYNC diff --git a/common/serial.h b/common/serial.h index f5d5987..9e48a6e 100644 --- a/common/serial.h +++ b/common/serial.h @@ -4,6 +4,7 @@ #include void serial_init(uint16_t); +void serial_set_baud(uint16_t); uint8_t serial_read(); uint8_t serial_read_available(); uint8_t serial_read_overrun(); -- 2.43.0