Технический форум по робототехнике.
наверное стоит поставить нормальный терминал и отладить работу прошивки на нем
при закороченных rx<->tx и пк, и минибот слышат и видят все, что пишут в уарт
#define DISABLE_RX() UCSRB &= ~(1<<RXEN)
#define ENABLE_RX() UCSRB |= (1<<RXEN)
/* Сеанс черной магии.
* Подробности смотри <util/atomic.h>
*/
static __inline__ uint8_t __disblRxRet()
{
DISABLE_RX();
return 1;
}
static __inline__ void __enblRxParam(const uint8_t *__s)
{
ENABLE_RX();
(void)__s; // чтобы компилятор не сыпал предупреждений про неиспользуемую переменную
}
/* OUT_BLOCK_FORCEON() {
* puts("output");
* }
*/
#define OUT_BLOCK_FORCEON() for(uint8_t __st __attribute__((__cleanup__(__enblRxParam))) = __disblRxRet(); __st; __st=0)
#ifndef USART_H_
#define USART_H_
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include "global.h"
/**
* Use the following macros to determine the 'baud' parameter values
* for uart_init()
* @warning 'baud' SHOULD ALWAYS BE A CONSTANT or a lot of code
* will be generated.
*/
//#define USART_BAUD(baud) ((uint16_t)((F_CPU / (16.0 * (baud))) + 0.5) - 1)
#define USART_BAUD(baud) ((uint16_t)((F_CPU + (baud * 8L)) / (16L * (baud))) - 1) //! vg
/**
* Some typical baud rates
* Confirm the cpu clock rate will support the desired baud rate
*/
#define B115200 (USART_BAUD(115200L))
#define B76800 (USART_BAUD(76800UL))
#define B57600 (USART_BAUD(57600UL))
#define B38400 (USART_BAUD(38400UL))
#define B28800 (USART_BAUD(28800U))
#define B19200 (USART_BAUD(19200U))
#define B14400 (USART_BAUD(14400))
#define B9600 (USART_BAUD(9600))
#define B4800 (USART_BAUD(4800))
#define B2400 (USART_BAUD(2400))
/**
* Double Speed operation
* use the following macros to determine the 'baud' parameter values
* for uartInit() for Double Speed operation. The macros above will
* also work just fine.
* @warning 'baud' SHOULD ALWAYS BE A CONSTANT or a lot of code
* will be generated.
*/
#define DOUBLE_SPEED_BIT (1<<15)
#define USART_2x_BAUD(baud) \
(((uint16_t)((F_CPU / (8.0 * (baud))) + 0.5) - 1) | DOUBLE_SPEED_BIT)
/**
* Some typical baud rates
* Confirm the cpu clock rate will support the desired baud rate
*/
#define B2x115200 (USART_2x_BAUD(115200L))
#define B2x76800 (USART_2x_BAUD(76800UL))
#define B2x57600 (USART_2x_BAUD(57600UL))
#define B2x38400 (USART_2x_BAUD(38400UL))
#define B2x28800 (USART_2x_BAUD(28800U))
#define B2x19200 (USART_2x_BAUD(19200U))
#define B2x14400 (USART_2x_BAUD(14400))
#define B2x9600 (USART_2x_BAUD(9600))
#define B2x4800 (USART_2x_BAUD(4800))
#define B2x2400 (USART_2x_BAUD(2400))
//! Type of interrupt handler to use for uart interrupts.
/// Value may be SIGNAL or INTERRUPT.
/// \warning Do not change unless you know what you're doing.
#ifndef UART_INTERRUPT_HANDLER
#define UART_INTERRUPT_HANDLER SIGNAL
#endif
// compatibility with most newer processors
#ifdef UCSRB
#define UCR UCSRB
#endif
// compatibility with old Mega processors
#if defined(UBRR) && !defined(UBRRL)
#define UBRRL UBRR
#endif
/** defines
**/
#define UART_DISABLE_RX() UCSRB &= ~(1<<RXEN)
#define UART_ENABLE_RX() UCSRB |= (1<<RXEN)
// USART file device
extern FILE usart_fdev;
/**
* This function initializes the USART
*
* @param baud baudrate divisor
* @return void
*
* Example
* @code
* usart_init(B9600);
* // or
* usart_init(USART_BAUD(9600));
* @endcode
*/
void usart_init(uint16_t baud);
/**
* Send one character to the UART.
*/
int usart_putchar(char c, FILE *stream);
int usart_putchar0(char c, FILE *stream);
/**
* Receive one character from the UART.
*/
int usart_getchar(FILE *stream);
int usart_getchar0(FILE *stream);
#endif /*USART_H_*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "irs_uart.h"
// usart file device
FILE usart_fdev = FDEV_SETUP_STREAM(usart_putchar, usart_getchar, _FDEV_SETUP_RW);
// This function initializes the USART
void usart_init(uint16_t baud) {
// disable the USART
UCSRB = 0x00;
UCSRA = 0x00;
if ( baud & DOUBLE_SPEED_BIT )
UCSRA |= (1 << U2X);
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Mode: Asynchronous
UCSRC=0x86;
UCSRB &= ~(UCSZ2);
// load the baudrate divisor register
UBRRL = baud;
// output the upper four bits of the baudrate divisor
UBRRH = (baud >> 8) & 0x0F;
// enable the USART0 transmitter & receiver
// enable RxD/TxD and interrupts
UCSRB |= (1<<TXCIE)|(1<<RXCIE)|(1<<TXEN)|(1<<RXEN);
}
/*
* Send character c down the UART Tx, wait until tx holding register
* is empty.
*/
int usart_putchar(char c, FILE *stream) {
if ( c == '\n' )
usart_putchar('\r', stream);
loop_until_bit_is_set(UCSRA, UDRE);
UART_DISABLE_RX();
UDR = c;
return 0;
}
int usart_putchar0(char c, FILE *stream) {
loop_until_bit_is_set(UCSRA, UDRE);
UART_DISABLE_RX();
UDR = c;
return 0;
}
int usart_getchar(FILE *stream) {
uint8_t c;
loop_until_bit_is_set(UCSRA, RXC);
c = UDR;
if ( c == '\r' )
c = '\n';
return c;
}
int usart_getchar0(FILE *stream) {
uint8_t c;
loop_until_bit_is_set(UCSRA, RXC);
c = UDR;
return c;
}
UART_INTERRUPT_HANDLER(SIG_UART_RECV) {
}
// UART Transmit Complete Interrupt Handler
UART_INTERRUPT_HANDLER(SIG_UART_TRANS) {
UART_ENABLE_RX();
}
[code=cpp][/code]
Толку использовать прерывания, если вызовы все равно блокирующие?
И еще маленькое замечание, копируете код — оставляйте заголовок с копирайтом/лицензией.
// ........
#define USART_BAUD(baud) ((uint16_t)((F_CPU + (baud * 8L)) / (16L * (baud))) - 1)
#define B9600 (USART_BAUD(9600))
#ifndef UART_INTERRUPT_HANDLER
#define UART_INTERRUPT_HANDLER SIGNAL
#endif
#define UART_DISABLE_RX() UCSRB &= ~(1<<RXEN)
#define UART_ENABLE_RX() UCSRB |= (1<<RXEN)
// .........
// ........
// This function initializes the USART
void usart_init(uint16_t baud) {
// disable the USART
UCSRB = 0x00;
UCSRA = 0x00;
if ( baud & DOUBLE_SPEED_BIT )
UCSRA |= (1 << U2X);
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Mode: Asynchronous
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
UCSRC &= (~(1<<UMSEL))&(~(1<<UPM1))&(~(1<<UPM0))&(~(1<<USBS))&(~(1<<UCPOL));
UCSRB &= ~(UCSZ2);
// load the baudrate divisor register
UBRRL = baud;
// output the upper four bits of the baudrate divisor
UBRRH = (baud >> 8) & 0x0F;
// enable the USART0 transmitter & receiver
// enable RxD/TxD and interrupts
UCSRB |= (1<<TXCIE)|(1<<RXCIE)|(1<<TXEN)|(1<<RXEN);
}
// .......
int usart_putchar(char c, FILE *stream) {
if ( c == '\n' )
usart_putchar('\r', stream);
loop_until_bit_is_set(UCSRA, UDRE);
UART_DISABLE_RX();
UDR = c;
return 0;
}
int usart_putchar0(char c, FILE *stream) {
loop_until_bit_is_set(UCSRA, UDRE);
UART_DISABLE_RX();
UDR = c;
return 0;
}
// .......
UART_INTERRUPT_HANDLER(SIG_UART_RECV) {
}
// UART Transmit Complete Interrupt Handler
UART_INTERRUPT_HANDLER(SIG_UART_TRANS) {
UART_ENABLE_RX();
}
// .......
// .......
usart_init(B9600);
// use USART device for stdio
stderr = stdout = stdin = &usart_fdev;
char tmpbuff[5] = {'H', 'E', 'L', 'L', 'O'};
while(1) {
for(unsigned int i=0; i<5; i++)
usart_putchar(tmpbuff[i], stdout);
}
// .......
int usart_putchar(char c, FILE *stream) {
if ( c == '\n' )
usart_putchar('\r', stream);
loop_until_bit_is_set(UCSRA, UDRE); // перестраховка
UART_DISABLE_RX();
UDR = c;
loop_until_bit_is_set(UCSRA, UDRE); // ждем пока символ отравляется
UART_ENABLE_RX(); // отправили, включили прием
return 0;
}
//...
usart_init(B9600);
// use USART device for stdio
stderr = stdout = stdin = &usart_fdev;
char tmpbuff[] = "Hello world!\n";
while(1) {
puts(tmpbuf);
}
//...
char tmpbuff[] = "Hi!"