Программный UART для любого микроконтроллера. Ч1
01/02/2012 - 22:15
Pavel Bobkov
Иногда возникает ситуация, когда аппаратных ресурсов микроконтроллера не хватает или требуемый ресурс в его составе отсутствует. Решить эту проблему можно двумя способами – заменить используемый микроконтроллер на другой или реализовать требуемый ресурс программно. Оба способа имеют свои достоинства и недостатки, однако второй вариант часто более предпочтительный, а иногда и единственно возможный. Например, как в случае с 1-Wire интерфейсом, который не поддерживается аппаратно ни в одном 8-ми разрядном микроконтроллере AVR.
В этой статье рассмотрена реализация программного UART`а, которую можно модифицировать под любой микроконтроллер, программируемый на Си. Во второй части статьи будет рассмотрена реализация программного UART`а модифицированного под микроконтроллер AVR. Материал написан на основе IAR`овского апноута, найденного на просторах интернета.
Требования
Для использования кода программного UART`а, необходимо выполнение следующих требований:
1. Наличие Си компилятора под используемый микроконтроллер
2. Наличие у микроконтроллера таймерного прерывания.
3. Наличие у микроконтроллера двух выводов, состояние которых можно программно читать и изменять.
Возможности
В данном коде реализованы следующие функции.
1. void flush_input_buffer( void )
Очистка входного (приемного) буфера.
2. char kbhit( void )
Тестирование входного буфера на наличие данных.
3. char getchar( void )
Чтение символа из входного буфера.
Принимаемые данные сохраняются в кольцевом буфере, емкость которого задается с помощью макроопределения.
Если на момент вызова данной функции входной буфер пуст, функция ожидает поступление данных. При этом в цикле выполняется пользовательская функция idle(). Про нее написано ниже.
4. void turn_rx_on( void )
Разрешает прием данных по UART`у. По умолчанию прием данных разрешен.
5. void turn_rx_off( void )
Запрещает прием данных по UART`у.
Прием и передача данных выполняется в обработчике прерывания таймера. Запрещение приема данных уменьшает время выполнения обработчика.
6. void putchar( char )
Запись символа в последовательный порт
7. void init_uart( void )
Инициализация программного UART`a. Устанавливает внутренние флаги, настраивает выводы микроконтроллера и таймер.
Ограничения
Данная программная реализация UART`а основана на использовании прерывания таймера. Разрядность таймера и режим работы значения не имеют, главное чтобы частота его прерываний могла быть установлена в три раза выше требуемой скорости обмена.
Например, требуется скорость 9600 бит в секунду. Тогда прерывания таймера должны происходить с частотой 9600*3 = 28800 Гц. Или в пересчете на временной интервал – каждые 34,72 микросекунды.
Это накладывает скоростные ограничения на возможности применения программного UART`a, особенно в микроконтроллерах с низкой тактовой частотой.
Если установить слишком высокую скорость обмена, код обработчика прерывания таймера не будет успевать выполняться между вызовами прерываний, что приведет к ошибкам приема/передачи, а то и к полной потере связи.
Также высокая частота прерываний таймера будет негативно влиять на производительность остальной части программы. (Для аналогии можно привести ситуацию, когда вы пытаетесь выполнять свою работу, а вас постоянно отвлекают на посторонние дела.)
Применение
Код программного UART`a из IAR`овского апноута записан в сишном файле. Подключить его к проекту можно двумя путями:
– скопировать этот код в один из сишных файлов своего проекта
– написать к сишному файлу заголовочный и подключить к проекту полноценный модуль
Второй путь более грамотный, поэтому программный UART во второй части статьи я подключаю к проекту именно так.
Однако это еще не все.
Для переносимости кода в нем не реализовано несколько платформенно-зависимых функций, которые вам потребуется написать. Функции перечислены в списке ниже.
В принципе ничего сложного в этом нет.
1. void get_rx_pin_status( void )
Возвращает состояние приемного вывода (receive pin).
2. void set_tx_pin_high( void )
Устанавливает на передающем выводе (transmit pin) логическую единицу.
3. void set_tx_pin_low( void )
Устанавливает на передающем выводе логический ноль.
4. void idle( void )
Фоновая пользовательская функция. Выполняется, когда ожидается прием данный.
5. void timer_set( int BAUD_RATE )
Устанавливает частоту прерываний таймера. Частота прерываний должна быть в 3 раза выше требуемой скорости обмена!
Функции передается значение требуемой скорости обмена, а она должна устанавливать соответствующую частоту таймерных прерываний.
6. void set_timer_interrupt( timer_isr )
Разрешает прерывания таймера.
Для экономии памяти и увеличения производительности кода некоторые из этих функций можно заменить макросами. Например, функции 1, 2, 3 и 6.
Функцию 4 можно оставить пустой.
И последнее что нужно сделать, это поместить код функции void timer_isr(void) в прерывание таймера. Сделать это можно опять-таки двумя способами:
- поместить вызов функции timer_isr() в код обработчика прерывания
- сделать из самой функции timer_isr() обработчик прерывания
Второй вариант более грамотный, поскольку требует меньших накладных расходов – оперативной памяти и процессорного времени. Впрочем, ты и так должен знать, к чему приводит вызов функций из прерываний.
Программный UART вторая часть...
Программный UART вторая часть...
Comments
Создал 2 МК Attiny85, соединил крест накрест ножки (PB3 первого МК к PB4 второго и наоборот) В Вашем заголовочном файле изменил F_CPU: 8000000->165000 00, IN_BUF_SIZE: 32->6, RX_PIN: 1->4, TX_PIN: 0->3
Первый работет приемником, второй передатчиком.
На передатчике :
int main( void )
{
SUART_Init();
sei();
while(1)
{
SUART_PutChar(b uf);
buf++;
}
return 0;
}
На приемнике:
int main( void )
{
SUART_Init();
sei();
while(1)
{
buf=SUART_GetCh ar();
}
return 0;
}
Приемник ничего не получает! Помогите разобраться начинающему.
Кстати запустил Ваш проект в протеусе, на осцилографе нету изменений. Может я чего-то не понимаю.
а arriny85 так и не пересылает данные (точнее пересылает, но любой символ приходит как 0.
В комментариях на этой странице мой рабочий код для STM.
http://we.easyelectronics.ru/STM32/vcp-soft_uart_x3-modifikaciya-stm32vldiscovery.html
RSS feed for comments to this post