PIC мк. Эксперимент №14. Модуль USART.

Рассмотрим примеры работы с 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.

Рекомендованная последовательность действий для передачи в асинхронном режиме.

  1. Установить требуемую скорость передачи с помощью регистра SPBRG и бита BRGH.
  2. Выбрать асинхронный режим сбросом бита SYNC в 0 и установкой SPEN в 1.
  3. Если необходимо, разрешить прерывания.
  4. Если передача 9 разрядная, установить бит TX9 в 1.
  5. Разрешить передачу установкой бита TXEN в 1.
  6. Если передача 9 разрядная записать 9 бит данных в TX9D.
  7. Записать данные в регистр 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-й бит принятых данных

Структурная диаграмма приемника:

rec

В приемнике главным также является сдвиговый регистр RSR, именно в него записываются данные со входа RB1, после получения стопового бита данные попадают в регистр RCREG, который имеет двойную буферизацию. То есть фактически, приемник принимает два байта буферы FIFO и еще один в сдвиговый регистр. После приема третьего байта устанавливается флаг переполнения OERR. После этого бит OERR необходимо сбросить выключением/включением приемника с помощью CREN.

Рекомендации по использованию приемника в асинхронном режиме:

  1. Установить требуемую скорость передачи данных.
  2. Выбрать асинхронный режим сбросом бита SYNC в 0 и установкой бита SPEN в 1.
  3. Если необходимо, включить прерывания.
  4. Если прием 9-разрядный, установить бит RX9 в 1.
  5. Разрешить прием установкой бита CREN в 1.
  6. Ожидаем установку RCIF или прерывание.
  7. Считать 9-й бит данных.
  8. Считать 8 бит данных из регистра RCREG.
  9. При возникновении ошибки переполнения сбросить бит CREN в 0.

Ниже временная диаграмма работы приемника:

Что ж, пожалуй хватит теоретической части, и перейдем к практической. У нас есть два пути проверки работоспособности:

  1. Проверка в протеусе.
  2. Проверка на 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);     //зачем эта фигня я так и не понял :)

#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      //фигня :)

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){

}

}

Результат работы кода:

result

Все работает, теперь передадим этот символ “грубым” методом. Пишем код, следуя рекомендациям работы с передатчиком в асинхронном режиме:


#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 микроконтроллерах.

 

Исходники здесь.

PIC мк. Эксперимент №14. Модуль USART.: 15 комментариев

  1. уважаемый серж большое количество людей вам будут благодарны если вы подробно опишите работу МК по USB,заранее спасибо!

    Ответить

  2. Да я сам все хочу разобраться с этим, я бы даже сказал, что это почти первоочередная задача для меня, но сейчас времени катастрофически не хватает, как только разберусь – сразу будет статья, будьте уверены :)

    PS. По русски читается сарж :)

    Ответить

  3. уважаемый Сарж, так и не дождались мы USB, так и не появилось свободное время?или отпала необходимость в этом? очень сильно продолжаем ждать!

    Ответить

  4. уважаемый sarge с USB я разобрался,сейчас работаю над управлением по SMS,если что-то заинтересует могу выложить коды,есть вопросик,а вы с шиной CAN разбирались?

    Ответить

  5. О круто, с усб разбирались под хай теч или под C18? С каном не сталкивался никогда, и насколько я понимаю есть множество разновидностей этого протокола, которые зависят от производителя, поэтому каждый раз может быть все по новому. Про усб было бы круто чтобы статья была, в которой все расписано, но на худой конец и от кодов конечно не откажусь :)

    Ответить

  6. нет,на счет USB я имел ввиду,что я обошелся микросхемой FT232BM, а смс -я не знаю что такое SIM900, брал обычную симку с телефона,модем использовал QUECTEL

    Ответить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">