From: Pat Thoyts Date: Wed, 19 Aug 2015 21:33:32 +0000 (+0100) Subject: Demonstrate basic use of USART serial comms with AVR microcontroller. X-Git-Url: https://privyetmir.co.uk/gitweb.cgi?a=commitdiff_plain;h=HEAD;p=avr%2Fserial-demo.git Demonstrate basic use of USART serial comms with AVR microcontroller. Signed-off-by: Pat Thoyts --- 60fcb7b742645cef977ffbcb364960819999e446 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6c2e45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.hex diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c968506 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +# -*- Makefile -*- + +PROJECT := serial-demo +DEVICE := atmega328p +F_CPU := 16000000UL +INC := -I. +AVRDUDE := avrdude -c usbasp -p $(DEVICE) -C $(AVR_DIR)\etc\avrdude.conf + +CC := avr-gcc +LD := avr-gcc +OBJCOPY := avr-objcopy +RM := del >NUL +CFLAGS :=-Wall -Wstrict-prototypes -Wmissing-prototypes -Wcast-align -Wshadow \ + -std=gnu99 -fshort-enums -pedantic-errors -Os -mcall-prologues \ + -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) +LDFLAGS := -Wall -mmcu=$(DEVICE) + +V := @ +Q := $(V:1=) +QUIET_CC = $(Q:@=@echo CC $@ &)$(CC) +QUIET_LD = $(Q:@=@echo LD $@ &)$(LD) +QUIET_OBJCOPY = $(Q:@=@echo OBJCOPY $@ &)$(OBJCOPY) +QUIET_AVRDUDE = $(Q:@=@echo AVRDUDE $@ &)$(AVRDUDE) + +all: $(PROJECT).hex + +%.hex: %.elf + $(QUIET_OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.elf: %.o + $(QUIET_LD) $(LDFLAGS) $< -o $@ + +%.o: %.c + $(QUIET_CC) $(CFLAGS) $(INC) -c $< + +flash: $(PROJECT).hex + $(QUIET_AVRDUDE) -U flash:w:$<:i + +clean: + -@$(RM) $(addprefix $(PROJECT), .elf .hex) + +.PHONY: clean +.SECONDARY: $(addsuffix .elf, $(PROJECT)) diff --git a/serial-demo.c b/serial-demo.c new file mode 100644 index 0000000..1432c5d --- /dev/null +++ b/serial-demo.c @@ -0,0 +1,85 @@ +/* serial-demo.c - Copyright (c) 2015 Pat Thoyts + * + * Simple synchronous serial echo firmware for AVR without using stdio. + */ + +#include +#include + +void usart_init(int baud); +inline uint8_t usart_is_rx_ready(void); +inline uint8_t usart_is_tx_ready(void); +int usart_getchar(void); +int usart_putchar(char c); + +void usart_init(int baud) +{ + uint16_t ubrr = F_CPU / 16 / baud - 1; + UBRR0H = (uint8_t)(ubrr >> 8); /* write before UBRR0L */ + UBRR0L = (uint8_t)ubrr; + UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* enable RX and TX */ + UCSR0C = _BV(USBS0) | _BV(UCSZ01) | _BV(UCSZ00); /* async, 8,1,n */ +} + +/* nonzero if serial data is available to read. */ +inline uint8_t usart_is_rx_ready(void) +{ + return bit_is_set(UCSR0A, RXC0); +} + +/* nonzero if transmit register is ready to receive new data. */ +inline uint8_t usart_is_tx_ready(void) +{ + return bit_is_set(UCSR0A, UDRE0); +} + +int usart_getchar(void) +{ + loop_until_bit_is_set(UCSR0A, RXC0); /* wait for rx ready */ + return UDR0; +} + +int usart_putchar(char c) +{ + loop_until_bit_is_set(UCSR0A, UDRE0); /* wait until data register empty */ + UDR0 = c; + return 0; +} + +int +main (void) +{ + int n; + static char version[] = {'S','e','r','i','a','l',' ','D','e','m','o','\r','\n'}; + + /* turn off all unused peripherals */ + power_adc_disable(); + power_spi_disable(); + power_twi_disable(); + + /* set all unused pins to high-Z state */ + DDRB = 0; PORTB = 0xff; + DDRC = 0; PORTC = 0xff; + DDRD = 0; PORTD = 0xff; + + /* use PB5 (pin 13) as serial receive indicator and trigger */ + DDRB |= _BV(DDB5); PORTB &= ~_BV(PB5); + + usart_init(9600); + + for (n = 0; n < sizeof(version); ++n) + usart_putchar(version[n]); + + for (;;) + { + if (usart_is_rx_ready()) + { + char c = 0; + PORTB ^= _BV(PB5); + c = usart_getchar(); + usart_putchar(c); + PORTB ^= _BV(PB5); + } + } + return 0; +}