USART с прерыванием, использующий UDRE с ATmega328P

У меня проблема с программированием сериала для Arduino на C. Приложение требует скорости, поэтому мне нужно сделать это на C. Я использую для этого Codeblocks, так как его легко скомпилировать.

Поскольку я также хочу, чтобы последовательная функция не блокировала приложение и не давала возможность отладки, я пытаюсь написать кольцевой буферный тип последовательной библиотеки. Приложение не должно получать данные, только печатать.

Проблема начинается с того, что последовательное прерывание, по-видимому, не срабатывает, и программные блоки блокируются компилятором:

main.c|11|warning: ‘UART_UDRE_vect’ appears to be a misspelled signal handler|

Программа испытаний выглядит следующим образом:

#include<avr/io.h>
#include<avr/interrupt.h>

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU/(USART_BAUDRATE*16UL)))-1)

char ok = 0;

ISR(UART_UDRE_vect) {
    ok = 1;
    UCSR0B &= ~(1<<5);
}

int main(void) {
  UBRR0H  = (BAUD_PRESCALE >> 8);
  UBRR0L  = BAUD_PRESCALE;
  UCSR0B |= (1<<TXEN0);
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
  sei();
  while(1){
    // write the byte to the serial port
    UDR0 = '0';
    UCSR0B |= (1<<5);
    while(ok != 1){}
    ok = 0;
    UDR0 = '\n';
    UCSR0B |= (1<<5);
    while(ok != 1){}
    ok = 0;
  }
  return 0;
}

Конфигурация и скорость передачи данных правильны, потому что пример эха, найденный здесь, работает.

Также другие примеры не используют UDRE, только прерывание RX, и это не то, что я ищу.

Я что-то забыл?

1 ответ

Решение

Две проблемы:

  • В соответствии с документацией, которую вы связали, вектор прерывания для вашей конкретной части ATmega328p должен быть назван USART_UDRE_vect,

  • Переменные, используемые совместно с прерыванием, всегда должны быть объявлены как volatile или компилятор может не понимать, что они используются, и поэтому нарушать вашу программу при оптимизации. В основном компилятор считает, что переменная ok никогда не может получить значение, отличное от 0, так как он нигде не видит вызов функции для ISR (так как он вызывается аппаратно, а не программой). Изменить объявление на static volatile char ok;

Другие вопросы по тегам