Hello!
I am working on a simple project and want to enable interrupt based UART communication. However, I encountered a problem that after every transmission my Arduino UNO resets and I cannot determine why. I have deleted most of my code and written a simple program to check what is the current time (millis()) and after every transmission it seems the clock and everything else is set back to zero.
The only items I'm enabling or disabling are cli(), sei() and UDRIE0 interrupt register but from what I understand I am doing the correct thing by disabling them while writing and enabling them when transmitting. Otherwise it is a simple register shift which should not reset the clock.
Any idea where is my problem? You can find my full code below.
#include <RTClib.h> // for RTC
#include <avr/interrupt.h>
#include <arduino-timer.h>
#include <avr/io.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#define F_CPU 16000000UL
#define RX_BUFFER_SIZE 128
#define TX_BUFFER_SIZE 128
// definition for UART
#define BAUD 9600
// #define UBRR_VAL (((F_CPU / (BAUD * 16UL))) - 1)
#define UBRR_VAL (((F_CPU / (BAUD * 8UL))) - 1)
volatile char tx_buffer[TX_BUFFER_SIZE];
volatile uint8_t tx_head = 0;
volatile uint8_t tx_tail = 0;
bool rx_end;
volatile char uart_write[64]="";
unsigned long init_time = millis();
unsigned long current_time;
float tmp_mili;
//-----------------------------------------------------------------------------------------//
// Start of functions //
//-----------------------------------------------------------------------------------------//
// ISR(USART_TX_vect) { // interrupt write function, this function writes UART0 value without hard locking the processor
ISR(USART_UDRE_vect) { // interrupt write function, this function writes UART0 value without hard locking the processor
if (tx_head != tx_tail) {
UDR0 = tx_buffer[tx_tail];
tx_tail = (tx_tail + 1) % sizeof(tx_buffer);
}
// else {
// cli();
// UCSR0B &= ~(1<<UDRIE0); // disable UDRE interrupt if tx_buffer is empty
// sei();
// }
}
void uart_init() {
cli();
UBRR0 = UBRR_VAL;
// UBRR0H = (unsigned char) (UBRR_VAL >> 8); // baud rate significant bits
// UBRR0L = (unsigned char) UBRR_VAL; // baud rate insignificant bits
UCSR0A = 0x00;
UCSR0B = 0x00;
UCSR0C = 0x00;
// UCSR0A = (0<<RXC0) | (1<<TXC0); // Status register fo RX and TX completion
// UCSR0A = (1<<UDRE0); // Status register for empty register
// UCSR0A = (1<<FE0) | (1<<DOR0) | (1<<UPE0); // Error status registers Frame, Data OverRun and Parity
UCSR0A = (1<<U2X0) | (0<<MPCM0); // Double speed disabled 0 ; Multi MCU mode 0 disabled
UCSR0B = (0<<RXCIE0) | (1<<TXCIE0);// RX Interrupt 0 disabled, TX interupt 1 enabled
UCSR0B |= (0<<UDRIE0);// USART data register empty interrupt 0 disabled, 1 enabled
UCSR0B |= (0<<RXEN0) | (1<<TXEN0);// RX 0 disabled, TX 1 Enabled
UCSR0B |= (0<<UCSZ02);// Frame size 0 - disabled, 1 - 9 frame format
//UCSR0B = (0<<RXB80) | (1<<TXB80);// RX and TX data storage for 9 bit frame format
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); // Frame format - 1 1 8 bits
UCSR0C |= (0<<UMSEL01) | (0<<UMSEL00); // USART mode - 0 0 Asynchronous USART mode
UCSR0C |= (0 << UPM01 | 0 << UPM00); // Parity mode - 0 0 no parity
UCSR0C |= (0 << USBS0); // Stop bit number - 0 one bit, 1 two bits
UCSR0C |= (0 << UCPOL0); // clock polarity, used for synchronous mode only 0 disabled
sei();
}
void uart_transmit(const char *str){
// cli();
UCSR0B &= ~(1<<UDRIE0); // disable UDRE interrupt before putting data inside
char dummy= UDR0; //clearing UDR0 register
uint8_t i = 0;
uint8_t next_head;// = (tx_head + 1) % sizeof(tx_buffer);
while (str[i] != '\0'){
// uint8_t tx_head = (tx_head + 1) % sizeof(tx_buffer);
// if (tx_head != tx_tail){
next_head = (tx_head + 1) % sizeof(tx_buffer);
if (next_head != tx_tail){
tx_buffer[tx_head] = str[i];
tx_head = (tx_head + 1) % sizeof(tx_buffer);
i++;
// if (!(UCSR0B & (1 << UDRIE0))){
// cli();
// UCSR0B |= (1<<UDRIE0); // enable UDRE interrupt to start transmitting data
// sei();
// }
}
// cli();
UCSR0B |= (1<<UDRIE0); // enable UDRE interrupt to start transmitting data
// sei();
}
while(tx_head==tx_tail && (!(UCSR0A & (1 << UDRE0)))){}; // hard wat to complete transmission
}
void setup() {
//setting the inputs/outputs pins
// New function for timed interrupts rather time delays
uart_init();
init_time = millis();
}
// Main loop
void loop() {
current_time=millis();
if (current_time-init_time>1000){
tmp_mili = millis() / 1000.0;
dtostrf(tmp_mili, 20, 10, uart_write);
uart_transmit(uart_write);
init_time=millis();
}
}