Solo tengo un conocimiento limitado en interrupciones.
Esto es lo que entiendo sobre las siguientes funciones de ISR
ISR(USART_RX_vect)
se llamará cuando haya nuevos datos disponibles en el búfer de recepción (RXC0 de USCR0A se establecerá en 1) y se borrará cuando se lean los datos
ISR(USART_UDRE_vect)
será llamado cuando UDRE0 se convierta en 1, lo que indica que el búfer de transmisión está vacío y listo para recibir datos
Configuré un código de interrupción UART como se muestra a continuación, no estoy seguro de que esta sea la forma correcta en que debería verse la función ISR pero funciona
/*
* uart_interrupt.c
*
* Created: 12-10-2018 04:54:04 PM
* Author : Athul
*/
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include <util/setbaud.h>
#define BAUD 9600
#define SIZE 500
int i = 0, j = 0;
uint8_t data_int;
/* For U2X0 = 0 */
uint16_t UBRR0_value = ((F_CPU / (4L * BAUD)) - 1)/2;
/* For U2X0 = 1 */
//uint16_t UBRR0_value = ((F_CPU / (8L * BAUD)) - 1)/2;
void uart_init(void)
{
/* For a baud rate of 9600 (F_CPU = 1000000), error is 7% when U2X0 = 0. Writing this bit to one will
reduce the divisor of the baud rate divider from 16 to 8 effectively doubling the
transfer rate for asynchronous communication and reduce error to 0.2% */
UCSR0A |= (1 << U2X0);
/*set (global) interrupt enable bit*/
sei();
/* transmit enable, receive enable & RX Complete Interrupt Enable */
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
/* 8 bit mode */
UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
/* Baud rate registers */
UBRR0H = UBRR0_value >> 8;
UBRR0L = UBRR0_value;
}
void uart_tx(uint8_t data)
{
/*wait till USART Receive Complete*/
loop_until_bit_is_set(UCSR0A, UDRE0); // same as while(!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
uint8_t uart_rx(void) {
/*wait till USART Data Register Empty*/
loop_until_bit_is_set(UCSR0A, RXC0); // same as while(!(UCSR0A & (1 << RXC0)));
return UDR0;
}
void printString(uint8_t *ptr)
{
while(*ptr != '//USART Data Register Empty Interrupt Enable
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << UDRIE0);
ISR(USART_RX_vect)
{
data_int = UDR0;
}
ISR(USART_UDRE_vect)
{
UDR0 = data_int;
}
')
{
uart_tx(*ptr);
ptr++;
}
}
/*Interrupt sub-routine for RX Complete Interrupt Enable*/
ISR(USART_RX_vect)
{
data_int = UDR0;
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = data_int;
}
int main(void)
{
/*Initialize uart*/
uart_init();
/*Test*/
uint8_t *p = "Hello";
printString(p);
/*Set PORTB pins as output*/
DDRB = 0XFF;
/*event loop*/
while (1)
{
/*Toggle PORTB pins*/
PORTB = 0XFF;
_delay_ms(100);
PORTB = 0X00;
_delay_ms(100);
}
}
Para saber cómo implementar UDRIE0
, hice los siguientes cambios,
#define SIZE 64
int i = 0, j = 0;
uint8_t data_int[SIZE];
ISR(USART_RX_vect)
{
data_int[i] = UDR0;
i++;
if(i > 64)
{
i = 0;
}
}
ISR(USART_UDRE_vect)
{
UDR0 = data_int[j];
j++;
if(j == 64)
{
UCSR0B &= ~(1 << UDRIE0); //disable UDRIE0 interrupt
}
}
Sigue imprimiendo los datos que ingresé por última vez
Luego decidí crear una matriz y almacenar los caracteres recibidos en ella y el ISR(USART_UDRE_vect)
leería cada carácter y lo transmitiría.
/*
* uart_interrupt.c
*
* Created: 12-10-2018 04:54:04 PM
* Author : Athul
*/
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include <util/setbaud.h>
#define BAUD 9600
#define SIZE 500
int i = 0, j = 0;
uint8_t data_int;
/* For U2X0 = 0 */
uint16_t UBRR0_value = ((F_CPU / (4L * BAUD)) - 1)/2;
/* For U2X0 = 1 */
//uint16_t UBRR0_value = ((F_CPU / (8L * BAUD)) - 1)/2;
void uart_init(void)
{
/* For a baud rate of 9600 (F_CPU = 1000000), error is 7% when U2X0 = 0. Writing this bit to one will
reduce the divisor of the baud rate divider from 16 to 8 effectively doubling the
transfer rate for asynchronous communication and reduce error to 0.2% */
UCSR0A |= (1 << U2X0);
/*set (global) interrupt enable bit*/
sei();
/* transmit enable, receive enable & RX Complete Interrupt Enable */
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
/* 8 bit mode */
UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
/* Baud rate registers */
UBRR0H = UBRR0_value >> 8;
UBRR0L = UBRR0_value;
}
void uart_tx(uint8_t data)
{
/*wait till USART Receive Complete*/
loop_until_bit_is_set(UCSR0A, UDRE0); // same as while(!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
uint8_t uart_rx(void) {
/*wait till USART Data Register Empty*/
loop_until_bit_is_set(UCSR0A, RXC0); // same as while(!(UCSR0A & (1 << RXC0)));
return UDR0;
}
void printString(uint8_t *ptr)
{
while(*ptr != '//USART Data Register Empty Interrupt Enable
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << UDRIE0);
ISR(USART_RX_vect)
{
data_int = UDR0;
}
ISR(USART_UDRE_vect)
{
UDR0 = data_int;
}
')
{
uart_tx(*ptr);
ptr++;
}
}
/*Interrupt sub-routine for RX Complete Interrupt Enable*/
ISR(USART_RX_vect)
{
data_int = UDR0;
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = data_int;
}
int main(void)
{
/*Initialize uart*/
uart_init();
/*Test*/
uint8_t *p = "Hello";
printString(p);
/*Set PORTB pins as output*/
DDRB = 0XFF;
/*event loop*/
while (1)
{
/*Toggle PORTB pins*/
PORTB = 0XFF;
_delay_ms(100);
PORTB = 0X00;
_delay_ms(100);
}
}
Imprime " hola " y nada más.
¿Alguien puede decir por qué no funciona?
¿Un pequeño ejemplo de UDRIE0
si es posible?
También el compilador da una advertencia. %código% ¿Qué significa esto?