цифровая электроника
вычислительная техника
встраиваемые системы

 

Микроконтроллеры семейства PIC32. Модуль UART.

Автор: Mike(admin) от 9-09-2013, 07:43

UART или универсальный асинхронный приемопередатчик присутствует практически во всех микроконтроллерах. Он позволяет обмениваться данными с периферийными устройствами и персональными компьютерами по протоколам RS232, RS485, LIN, IrDA.


Передача и прием данных с помощью UART в PIC32 производятся по линиям UxTX (для передачи) и UxRX (для приема). Кроме того, для более надежного использования UART в микроконтроллере предусмотрено аппаратное управление потоком данных, реализуемое с помощью выводов UxCTS и UxRTS. Блок-схема модуля UART показана на рисунке:


UART

На схеме видно, что специальный генератор частоты определяет скорость работы (в бодах) приемника, передатчика, кодера/декодера ИК-интерфейса IrDA и модуля управления потоком. Генератор имеет 16-разрядный предделитель и обеспечивает широкий диапазон скоростей: от 76 б/с до 20 Мб/с при частоте ядра 80 МГц. В общем, при желании на UART можно сделать очень быстрый последовательный интерфейс. Но это не нынешний случай, сейчас мы поработаем со стандартным протоколом RS-232. Его в основном настраивают на 1200, 2400, 4800, 9600 и 115200 бод.


Частоту генератора определяет регистр UxBRG. Его значение вычисляется в соответствии с требуемой скоростью передачи данных:


UART baudrate

Здесь Fpb представляет собой частоту работы периферийной шины, а число 16 соответствует тому, что выбран стандартный скоростной режим, определенный битом BRGH режимного регистра UxMODE. В данном случае BRGH = 0, если установить BRGH = 1, то вместо 16 будет 4, что соответствует высокоскоростному режиму.


Допустим, нам необходимо установить связь со скоростью 115200 бод. При максимальной частоте ядра 80 МГц рабочая частота периферийной шины будет составлять 40 МГц, то есть половину от частоты ядра. Тогда при бите BRGH = 0 получим:


UxBRG = (40000000/(16*115200))-1 = 20.7

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


Итак, перейдем непосредственно к настройке самого порта. Конечно же, это проще сделать, используя библиотеку plib. Основной функцией для настройки UART является OpenUARTx, которая манипулирует регистрами UxMODE и UxSTA. Она имеет следующую структуру: void OpenUART1(unsigned int config1, unsigned int config2, unsigned int ubrg). Аргументы config1 и config2, содержат довольно много параметров, изменяющих значение регистров UxMODE и UxSTA. Про всех них можно почитать подробнее в документации, а здесь остановимся на наиболее важных.


В config1 можно включить или отключить модуль UART с помощью записи UART_EN/ UART_DIS. Здесь же производится настройка порта, для этого нужно ввести один из параметров UART_NO_PAR_8BIT (четность - нет, 8 бит) / UART_EVEN_PAR_8BIT (четность - чет, 8 бит) / UART_ODD_PAR_8BIT (четность - нечет, 8 бит) / UART_NO_PAR_9BIT (четность - нет, 9 бит). Количество стоповых битов устанавливается как UART_1STOPBIT / UART_2STOPBITS. В config1 также бит BRGH как UART_BRGH_SIXTEEN / UART_BRGH_FOUR.


В config2 следует включить возможность приема и передачи данных UART_RX_ENABLE и UART_TX_ENABLE, если нужно, чтобы модуль ничего не принимал и не получал, то ваш выбор – UART_RX_DISABLE и UART_TX_DISABLE.


И, наконец, в ubrg записываем заранее рассчитанное значение регистра UxBRG.


Для того, чтобы разрешать/запрещать различные прерывания от модуля и играться с приоритетностью прерываний можно воспользоваться функцией ConfigIntUARTx. В этой функции могут быть следующие аргументы. UART_ERR_INT_EN(DIS) разрешает (запрещает) прерывание при возникновении ошибки; UART_RX_INT_EN(DIS) разрешает (запрещает) прерывание при приеме байта; UART_INT_PRx устанавливает приоритет прерывания (здесь x от 0 до 7); UART_INT_SUB_PR устанавливает подприоритет прерывания (здесь x от 0 до 3); UART_TX_INT_EN(DIS) разрешает (запрещает) прерывание при отправке байта и, наконец, UART_TX_INT_PRx устанавливает приоритет прерывания при передаче данных (x от 0 до 7).


Для того, чтобы считывать данные из буфера существует функция, объявляемая следующим образом unsigned int ReadUARTx(void). Возвращаемое значение определяется как unsigned int, а не char, потому как может быть выбран режим с 9 битами. Для отправки данных в буфер для передачи служит функция void WriteUARTx(unsigned int data). Здесь data является переменной, в которой хранится передаваемая информация.


Прелестью использования plib является то, что в ней имеются функции для приема и отправки массива данных. Для приема используется unsigned int getsUART1(unsigned int length, char *buffer, unsigned int uart_data_wait). Здесь length представляет собой длину строки, которую нужно получить, *buffer является указателем на массив, в который должны быть помещены принятые данные, и uart_data_wait определяет время, которое модуль будет ждать до того, как вернуть значение. Сама функция возвращает количество принятых байтов. Если она вернула 0, то значит, что вся строка принята, в противном случае процесс приема продолжается.


Отправка массива данных производится с помощью функции, объявляемой как void putsUARTx(const char *buffer). Она ничего не возвращает, и в качестве аргумента требует указатель на массив *buffer.


Из полезного также следует отметить функции int BusyUARTx(void) и int DataRdyUARTx(void). Первая позволяет узнать, не занят ли модуль в данный момент. Она возвращает 0, если модуль не совершает ни приема ни передачи данных. DataRdyUARTx сообщает о готовности для считывания данных, которые находятся в приемном буфере. Если возвращается не 0, то в буфере имеются данные для считывания.


Итак, для примера установим связь с компьютером (можно через HyperTerminal) на скорости 115200 б/с при 8-битной передачи, 1 стоповом бите и отсутствии четности. Аппаратное управление потоком отключим. В плане схемотехники нужно предусмотреть согласование уровней с COM-портом, например, с помощью MAX3232. По кнопке будем записывать в порт строку, а по приему символа от компьютера, переходить в обработчик прерывания и оттуда отправлять какой-нибудь символ.



#include <p32xxxx.h>
#include <plib.h>
// настраиваем частоту
#pragma config FNOSC=XTPLL
#pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_20, FPLLODIV=DIV_1
#pragma config FWDTEN=OFF // отключаем сторожевой таймер

// Обработчик прерываний
void __ISR(0, ipl3) InterruptHandler(void)
{
WriteUART1('y'); //отправка символа y
mU1ClearAllIntFlags(); //очистка флагов прерывания модуля UART1
}

main ()
{

//настройка кэша
mCheConfigure(CHE_CONF_WS2 | CHE_CONF_PF_ALL | CHE_CONF_COH_INVUNL | CHE_CONF_DC_NONE);

CheKseg0CacheOn();
mBMXDisableDRMWaitState();


//Настройка портов

TRISG=0x03C0;
PORTG=0x0000;

//настройка модуля UART и его прерываний

// вкл. прерывание по приему, приоритет 3, подприоритет 0
ConfigIntUART1(UART_RX_INT_EN | UART_TX_INT_DIS | UART_ERR_INT_DIS
| UART_INT_PR3 | UART_INT_SUB_PR0);

// включаем модуль, стандартный скоростной режим BRGH=16,
//один стоповый бит, передача 8 бит без четности,
//разрешаем прием и передачу, UxBRG = 21
OpenUART1(UART_EN | UART_BRGH_SIXTEEN | UART_1STOPBIT
| UART_NO_PAR_8BIT, UART_RX_ENABLE | UART_TX_ENABLE, 21);

INTEnableSystemSingleVectoredInt(); // разрешаем прерывания

//------------------------------------------------
//бесконечный цикл
do
{

if (PORTG & 0x40) //нажимаем кнопку
{
putsUART1("Hello UART!!!"); //отправляем строку Hello UART!!!
}
}
while(1); // закрытие бесконечного цикла

} // закрытие функции main



Предыдущие разделы:
Микроконтроллеры семейства PIC32. Первый проект.
Микроконтроллеры семейства PIC32. Работа с таймерами.
Микроконтроллеры семейства PIC32. Прерывания.

© digitrode.ru


Теги: PIC32, UART, RS232




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий