UART прерывает отключение ввода-вывода на Sam3X8E/ Arduino Due
Я начинаю использовать Arduino Due для некоторых работ по проекту, для которых требуется UART, и меня смущает то, что выглядит как взаимодействие между прерываниями UART и вводом / выводом.
Моим первым фрагментом кода была небольшая процедура для настройки UART, непрерывной отправки данных путем загрузки буфера передачи при получении прерывания TXBE. Я подключил выход UART к осциллографу и установил другой вывод ввода / вывода в качестве выхода общего назначения, который перевернул бы состояние и, следовательно, использовался для запуска прицела при перезагрузке буфера передачи. Проблема заключалась в том, что я видел данные UART, и они выглядели хорошо, но ввод / вывод не переворачивался. На данный момент мой loop()
подпрограмма была пуста, поэтому я настроил другой выходной порт и в loop()
просто переключил его состояние в качестве проверки здравомыслия. По-прежнему нет выхода, кроме UART.
Вот код, с которым я закончил:
uint32_t tempo; // 32-bit temporary variable
boolean flag = true;
void UART_Handler(void) {
REG_UART_THR = 0x6DL; // load data into the transmit buffer
if (flag) {
REG_PIOD_SODR = 0x02L; // drive PD1 high
flag = false;
} else {
REG_PIOD_CODR = 0x02L; // drive PD1 low
flag = true;
}
}
void setup() {
// set up the UART I/O
REG_PIOA_IDR = 0x0300L; // disable interrupts on PA8 and PA9
tempo = REG_PIOA_ABSR; // get the current settings of the AB select register
REG_PIOA_ABSR = tempo & 0xFFFFFCFF; // set PA8 and PA9 to peripheral A control
REG_PIOA_PDR = 0x0300L; // disable parallel I/O for PA8 and PA9
NVIC_EnableIRQ(UART_IRQn); // enable UART interrupts in NVIC
// now set up the UART
tempo = REG_PMC_PCSR0; // get the current settings of the peripheral clock register 0
REG_PMC_PCER0 = tempo | 0x0100L; // enable the UART clocks
REG_UART_CR = 0x0CL; // reset UART receiver and transmitter
REG_UART_MR = 0x0800L; // set to normal outputs with no parity
REG_UART_BRGR = 0x89L; // baud rate set to 38400
REG_UART_IDR = 0x1FBL; // disable all UART interrupts
REG_UART_IER = 0x0800L; // enable TXBUFE interrupt
REG_UART_CR = 0x50L; // enable UART receiver and transmitter
// set up the debug outputs
REG_PIOD_IDR = 0x03L; // disable interrupts on PD0 and PD1
REG_PIOD_PER = 0x03L; // enable parallel I/O for PD0 & PD1
REG_PIOD_OER = 0x03L; // set PD0 & PD1 output enabled
REG_PIOD_CODR = 0x03L; // drive PD0 & PD1 low
}
void loop() // run over and over
{
REG_PIOD_SODR = 0x01L; // drive PD0 high
delay(1);
REG_PIOD_CODR = 0x01L; // drive PD0 low
delay(1);
}
выходной объем можно посмотреть по адресу http://www.iwanczuk.com/temp/scope1.png (здесь недостаточно репутации для публикации изображений!).
Поработав некоторое время и не зная, что я отключил прерывания TXBUFE, закомментировав строку REG_UART_IER = 0x0800L; // enable TXBUFE interrupt
и тогда было видно переключение PortD1, но, очевидно, нет выхода UART (см. http://www.iwanczuk.com/temp/scope2.png). Кажется, что они взаимоисключающие, что было бы глупо, если бы это было правдой. Я уверен, что что-то упустил, но я не вижу и не вижу, что это такое.
Я прочитал таблицу данных SAM3X8E, чтобы увидеть, есть ли что-то очевидное, что я пропускаю, и если есть, я не вижу его. Я также сделал то, что я считаю релевантными поисковыми запросами в Интернете, и мне не повезло найти решение. Я также попытался использовать выходы общего назначения для двух выходов на порт A и порт D и попробовал это на двух платах Arduino Due с похожими результатами на обоих.
У кого-нибудь есть идеи, что я могу делать не так? Заранее спасибо.
2 ответа
Я только что понял, что может быть настоящей ошибкой в источнике моей проблемы. Описания регистров прерываний UART говорят о бите TXBUFE в контексте пустого буфера передачи, и поэтому я предположил, что это бит, который говорит мне, когда я могу вставить другой байт в регистр хранения передачи. Однако в описании регистра состояния UART говорится, что бит TXBUFE является "сигналом заполнения буфера от канала PDC передатчика". Последнее ставит совершенно другой взгляд на то, что делает этот бит. Согласно описанию регистра состояния UART, бит, на который я должен смотреть, это бит TXRDY!
Ну, я дошел до сути этой проблемы. Не уверен, что это лучший ответ, но это решение. Короче говоря, нужно избегать прерываний TXBE. Если я использую прерывания TXEMPTY вместо этого, он работает нормально.
Строка на странице 168 таблицы данных Atmel говорит (sic): "Прерывание может войти в состояние ожидания, даже если оно отключено", поэтому я подумал, была ли проблема с TXBE из-за того, что я не очищал ожидающее прерывание до или даже внутри ISR, так я добавил NVIC_ClearPendingIRQ(UART_IRQn);
в начале ISR, а также непосредственно перед тем, как я включил прерывание TXBE, но поведение (mis) не изменилось.
Операция TXEMPTY все еще немного странна (для меня), потому что кажется, что прерывание генерируется сдвиговым регистром передачи, просто являющимся пустым, а не когда он становится пустым. Если вы разрешите прерывания без загрузки буфера передачи, вы сразу получите прерывание. Кому-то может понравиться это поведение "self = priming", но оно не делает это для меня. Я пишу свою процедуру отправки так, что прерывание TXEMPTY не включается, пока передатчик не будет загружен первым байтом для отправки.
Основываясь на этом посте на форуме Arduino: http://forum.arduino.cc/index.php?topic=186388.0 Я предполагаю, что у USART есть похожая проблема.
Надеюсь, это поможет другим.