Рассмотрим примеры работы с USART. В статье я постараюсь идти двумя путями:
1. Применяем готовые решения из компилятора.
2. Пишем свои функции.
В общем обо всем по-порядку. USART он же UART он же SCI — универсальный протокол передачи данных, который может работать в асинхронном либо в синхронном режиме передачи. Собственно, на данный момент нас интересует первый режим, так как именно он используется для связи с ПК. В этом случае шина данных выглядит примерно вот так: Несколько замечаний о режиме: В состоянии ожидания на линии высокий логический уровень. Каждая передача инициализируется стартовым нулевым битом. Сначала передается младший бит. Каждая передача заканчивается стоповым битом единицей.
Для начала разберемся с генератором частоты обмена USART BRG (Baud Rate Generator).
BRG представляет собой 8-разрядный генератор скорости обмена в бодах, период которого определяется значением в регистре SPBRG, а также значением BRGH. Ниже формулы расчета скорости: В качестве примера рассчитаем значение регистра SPBRG для следующих условий:
Fosc = 16 MHz
Скорость обмена = 9600
BRGH = 0
SYNC = 0
Расчет:
9600 = 16 000 000/(64(Х+1)) => X = 25.042 = 25
Перейдем к передатчику и приемнику.
Регистр TXSTA — передатчик CSRC Выбор источника тактового сигнала Синхронный режим 1 ведущий, сигнал с BRG 0 ведомый, сигнал с CK Асинхронный режим Не используется TX9 Разрешение 9-разрядной передачи 1 разрешена 0 не разрешена TXEN Разрешение передачи 1 разрешена 0 запрещена SYNC 1 синхронный 0 асинхронный BRGH Выбор высокоскоростного режима Синхронный режим Не имеет значения Асинхронный режим 1 высокоскоростной 0 низкоскоростной TMRT Флаг очистки TSR 1 TSR пуст 0 TSR полон TX9D 9-й бит данных
Структурная схема передатчика: Главный элемент передатчика — сдвиговый регистр TSR, который получает данные из буфера передатчика TXREG. После передачи стопового бита TSR загружается новым значением из TXREG (если оно присутствует), после чего устанавливается флаг прерывания TXIF. Этот флаг устанавливается независимо от того, в единице TXIE или в нуле. Также одна из особенностей — этот флаг нельзя сбросить в 0 программно, он сбрасывается только после загрузки данных в TXREG.
Рекомендованная последовательность действий для передачи в асинхронном режиме. Установить требуемую скорость передачи с помощью регистра SPBRG и бита BRGH. Выбрать асинхронный режим сбросом бита SYNC в 0 и установкой SPEN в 1. Если необходимо, разрешить прерывания. Если передача 9 разрядная, установить бит TX9 в 1. Разрешить передачу установкой бита TXEN в 1. Если передача 9 разрядная записать 9 бит данных в TX9D. Записать данные в регистр TXREG.
Временная диаграмма передачи одного байта: Регистр RCSTA — приемник: SPEN Разрешение работы 1 модуль USART включен 0 модуль USART выключен RX9 Разрешение 9-разрядного приема 1 разрешен 0 не разрешен SREN Разрешение одиночного приема Синхронный режим 1 разрешен 0 запрещен Асинхронный режим Не имеет значения CREN Разрешение приема Синхронный режим 1 разрешен 0 запрещен Асинхронный режим 1 разрешен 0 запрещен ADDEN Разрешение детектирования адреса Асинхронный 9-разрядный прием 1 разрешено 0 запрещено FERR Ошибка кадра 1 ошибка произошла 0 ошибка кадра не было OERR Ошибка переполнения внутреннего буфера 1 произошла ошибка переполнения 0 ошибки переполнения не было RX9D 9-й бит принятых данных
Структурная диаграмма приемника: В приемнике главным также является сдвиговый регистр RSR, именно в него записываются данные со входа RB1, после получения стопового бита данные попадают в регистр RCREG, который имеет двойную буферизацию. То есть фактически, приемник принимает два байта буферы FIFO и еще один в сдвиговый регистр. После приема третьего байта устанавливается флаг переполнения OERR. После этого бит OERR необходимо сбросить выключением/включением приемника с помощью CREN.
Рекомендации по использованию приемника в асинхронном режиме: Установить требуемую скорость передачи данных. Выбрать асинхронный режим сбросом бита SYNC в 0 и установкой бита SPEN в 1. Если необходимо, включить прерывания. Если прием 9-разрядный, установить бит RX9 в 1. Разрешить прием установкой бита CREN в 1. Ожидаем установку RCIF или прерывание. Считать 9-й бит данных. Считать 8 бит данных из регистра RCREG. При возникновении ошибки переполнения сбросить бит CREN в 0.
Ниже временная диаграмма работы приемника: Что ж, пожалуй хватит теоретической части, и перейдем к практической. У нас есть два пути проверки работоспособности: Проверка в протеусе. Проверка на devboard, подключая ее через max232 to rs232 level converter.
Сначала мы пойдем по первому пути, а в конце просто сварганим большую тестовую прогу и проверим ее на терминале ББ.
Начнем с передачи данных. Заходим в папку с установленным компилятором и находим в образцах папку «usart», содержащую три файла: main.c usart.c usart.h
Модифицируем файл usart.h до такого состояния: #ifndef _SERIAL_H_ #define _SERIAL_H_ #define BAUD 9600 //скорость обмена данными генератора BRG #define FOSC 4000000L //частота кварца #define NINE 0 //используем 9 битовую передачу или нет? #define DIVIDER ((int)(FOSC/(16UL * BAUD) -1)) //вычисляем значение регистра SPBRG #define HIGH_SPEED 1 //высокоскоростная передача #if NINE == 1 #define NINE_BITS 0x40 #else #define NINE_BITS 0 #endif #if HIGH_SPEED == 1 #define SPEED 0x4 #else #define SPEED 0 #endif #define RX_PIN TRISB1 //Порт приема #define TX_PIN TRISB2 //Порт передачи /* Инициализация модуля */ #define init_comms() RX_PIN = 1; TX_PIN = 1; SPBRG = DIVIDER; RCSTA = (NINE_BITS|0x90); TXSTA = (SPEED|NINE_BITS|0x20) void putch(unsigned char); //передача символа unsigned char getch(void); //прием символа unsigned char getche(void); //зачем эта фигня я так и не понял <img src="http://diymicro.ru/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley"> #endif Содержание файла usart.c: #include <htc.h> #include <stdio.h> #include "usart.h" void putch(unsigned char byte) { /* передача одного байта */ while(!TXIF) /* устанавливается, когда регистр пуст */ continue; TXREG = byte; } unsigned char getch() { /* получение одного байта */ while(!RCIF) continue; return RCREG; } unsigned char //фигня <img src="http://diymicro.ru/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley"> getche(void) { unsigned char c; putch(c = getch()); return c; } Содержание файла main будем строчить сами. Как уже я упоминал, начинаем с передачи 1 байта. Для примера передадим символ ‘K’ = 0b01001011
пишем небольшую программку: #include <stdio.h> #include <htc.h> #define _XTAL_FREQ 4000000 #include "usart.h" __CONFIG(LVPDIS & WDTDIS & MCLREN & UNPROTECT & HS); void main(void){ unsigned char input; INTCON=0; //выключаем прерывания init_comms(); // инициализируем usart putch('K'); // отправляем символ K while(1){ } } Результат работы кода: Все работает, теперь передадим этот символ «грубым» методом. Пишем код, следуя рекомендациям работы с передатчиком в асинхронном режиме: #include <htc.h> #define _XTAL_FREQ 4000000 __CONFIG(LVPDIS & WDTDIS & MCLREN & UNPROTECT & HS); void main(void){ TRISB = 0xFF; //порт B на вход BRGH = 0; //низкоскоростной режим SPBRG = 0x05; //вычисленное значение SYNC = 0; //асинхронный режим SPEN = 1; TXEN = 1; //разрешаем передачу TXREG =0b01001011; //впихиваем символ К while(1){ } } А вот, то что получаем на выходе (не забываем что здесь 7 бит идет вторым по счету) : Перейдем к приемнику, юзаем готовые варианты: #include <stdio.h> #include <htc.h> #define _XTAL_FREQ 4000000 #include "usart.h" __CONFIG(LVPDIS & WDTDIS & MCLREN & UNPROTECT & HS); void main(void){ unsigned char input; INTCON=0; // purpose of disabling the interrupts. init_comms(); // set up the USART - settings defined in usart.h // Output a message to prompt the user for a keypress printf("\rPress a key and I will echo it back:\n"); while(1){ input = getch(); // read a response from the user printf("\rI detected [%c]",input); // echo it back } }
Программа отслеживает нажатие клавиши и тут же возвращает эту клавишу обратно: Что касается работы приемника «напрямую», то тут я расписывать все подробно не вижу смысла, так как предустановки такие же как для передатчика, а сама функция будет выглядеть точно так же как и в файле примера: unsigned char getch() { /* retrieve one byte */ while(!RCIF) /* set when register is not empty */ continue; return RCREG; }
Вот в принципе и все, данной информации хватит для того, чтобы вполне успешно использовать USART в PIC микроконтроллерах.
Источник: http://diymicro.ru/?p=111 |