En utilisant le strict minimum, à partir de la
datasheet de l'ATmega368 :
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
/*
** UART
*/
void uart_init(void)
{
UBRR0H = 0x00;
UBRR0L = 103; /* F_CPU/16/baud-1 for 9600 bps*/
UCSR0C = (1<<USBS0) | (3<<UCSZ00); /* 8N1 */
UCSR0B = (1<<RXEN0) | (1<<TXEN0); /* enable */
}
char my_getc()
{
while (!(UCSR0A & (1<<RXC0)))
;
return(UDR0); /* should handle errors */
}
void my_putc(char c)
{
while (!(UCSR0A & (1<<UDRE0)))
;
UDR0 = c;
}
/*-----------------------------------------------*/
int main(void)
{
uart_init();
for (;;)
my_putc(my_getc());
}
Avec comme commandes :
$ avr-gcc -mmcu=atmega328 -Os -o echo.elf echo.c
$ avrdude -c arduino -p atmega328P -P /dev/ttyUSB0 -b 57600 -U flash:w:echo.elf
On peut tester avec
$ minicom -D /dev/ttyUSB0 -b 9600
AVR libc
Intrigué par le fait que mes putc() et getc() entraient en conflit avec des 'built-in', j'ai fini par me rendre compte de l'existence d'une véritable
libc pour AVR... Et c'est quand même vachement mieux fichu que l'
API Arduino. Ouf! Notamment du côté de
stdio. Adapté, le programme devient quelque chose comme :
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <stdio.h>
#include <string.h>
/*
** UART
*/
void uart_init(void)
{
UBRR0H = 0x00;
UBRR0L = 103; /* 9600 bps | F_CPU/16/baud-1 */
UCSR0C = (1<<USBS0) | (3<<UCSZ00); /* 8N1 */
UCSR0B = (1<<RXEN0) | (1<<TXEN0);
}
int uart_getchar(FILE *stream)
{
while (!(UCSR0A & (1<<RXC0)))
;
return(UDR0);
}
int uart_putchar(char c, FILE *stream)
{
while (!(UCSR0A & (1<<UDRE0)))
;
UDR0 = c;
}
/*-----------------------------------------------*/
/* line input with minimal editing */
char *getline(char *cp, int n)
{
int i=0;
char c;
for(;;)
{
c = fgetc(stdin);
if (c=='\n' || c=='\r' || i==(n-1))
{
cp[i] = '\0';
return(cp);
}
if (c=='\b' && i>0)
{
fputc(c, stdout);
fputc(' ', stdout);
i -= 1;
}
else cp[i++] = c;
fputc(c, stdout);
}
}
int main(void)
{
char buf[32];
uart_init();
fdevopen(uart_putchar, uart_getchar);
printf("Hello World\n\r");
for (;;)
{
printf("\n\rReady> ");
getline(buf, sizeof(buf));
printf("\n\rstrlen('%s') is %d.\n\r", buf, strlen(buf));
}
}