Модули UART микроконтроллеров STM8 реализованы в трёх различных исполнениях: UART1, UART2 и UART3.
При этом цифровые индексы в названиях модулей для конкретной модели указывают именно на вариант исполнения, а не
на их порядковый номер в составе данной модели.
Все вместе модули UART обеспечивают следующие основные возможности:
Асинхронный режим с поддержкой многопроцессорного
обмена; Синхронный режим; Режим "Smartcard”
; Режим поддержки инфракрасных приёмопередатчиков IrDA; Полудуплексный (однопроводной) режим; Интерфейс LIN в режиме master и slave.
При этом модуль UART1 поддерживает весь указанный набор функций, кроме
режима LIN Slave. UART2 не поддерживает обмен данными в однопроводном режиме. UART3 может работать только в асинхронном режиме
с поддержкой многопроцессорного обмена, а так же режимах LIN master и slave.
Далее будет описана последовательность действий
по инициализации модулей UART
для работы в традиционном асинхронном режиме обмена.
§
|
> Разрешение выводов UART
|
Для переключения выводов UART из состояния портов общего назначения в состояние UART_RX, TX необходимо установить биты TEN и REN регистра UART_CR2: #include "iostm8s105c6.h" UART2_CR2 |= (MASK_UART2_CR2_REN)|(MASK_UART2_CR2_TEN); // Разрешить TX, RX.
|
Примечание: здесь и далее имена регистров и битовых масок под компилятор IAR.
§
|
> Задание скорости обмена
| Скорость обмена (BaudRate)
определяется значением регистра делителя частоты тактирования UART, которое не может быть меньше 16 и рассчитывается по формуле:
UART_DIV = Fmaster / BaudRate.
Два байта
значения UART_DIV записываются
в регистры делителя по следующему правилу: старшая и младшая тетрады шестнадцати
разрядов коэффициента деления записываются в старшую и младшую тетраду регистра
BRR2, две средние тетрады значения UART_DIV записываются в регистр BRR1. При этом вначале
необходимо записывать регистр BRR2, а затем BRR1.
Программа для
расчёта инициализационных значений регистров BRR1, BRR2 приведена в конце
статьи. Так, например,
для UART1 с тактированием от 16МГц, при скорости обмена 9600 bps, значение коэффициента деления будет равно 0x0683, а инициализационный
код должен выглядеть так:
UART1_BRR2 = 0x03; UART1_BRR1 = 0x68;
|
Длина слова
данных кадра UART определяется состоянием бита
M в регистре UARTn_CR1. Если он сброшен, осуществляется приём и передача 8 бит данных, если
установлен – 9 бит. В девятибитном режиме обмена значение девятого разряда при
передаче извлекается из бита T8 регистра UARTn_CR1, а при приёме копируется в бит R8 того же регистра. Количество стоп-битов задаётся комбинаций разрядов 4 и 5 в
регистре UARTn_CR3:
Bits
5:4= 00: 1 стоп бит;
Bits
5:4= 01: Зарезервировано;
Bits
5:4= 10: 2 стоп бита;
Bits 5:4= 11: 1.5 стоп бита (используется
в режиме "Smartcard”).
Для включения режима контроля
чётности/нечётности необходимо установить бит PCEN регистра UARTn_CR1. При этом контрольный разряд займёт место последнего бита данных,
бит7 и бит 8 для 8- и 9-разрядного режима обмена соответственно. Назначение контрольного разряда определяется
состоянием бита PS в регистре UARTn_CR1:
Bit
1 = 0: Even parity (контроль чётности);
Bit 1 = 1: Odd parity (контроль нечётности).
Бит чётности устанавливается в единицу
при нечётном количестве установленных разрядов в слове данных, бит нечётности при
чётном. Таким образом, биты дополняют число единичных битов до чётного и нечётного
значений соответственно. В режиме передачи контрольный разряд формируется
автоматически, при приёме происходит его расчёт и сравнение с принятым
значением. В случае получения ошибочного значения контрольного разряда в
статусном регистре UARTn_SR устанавливается бит PE (Parity error).
Пример
инициализации:
// Разрешить выводы TX, RX. UART2_CR2 |= (MASK_UART2_CR2_REN)|(MASK_UART2_CR2_TEN);
UART2_CR3_STOP=2; // Bits 5:4= 10 два стоп-бита. // Режим 9 бит, контроль нечётности.
UART2_CR1 |= (MASK_UART2_CR1_M)|(MASK_UART2_CR1_PCEN)|(MASK_UART2_CR1_PS);
UART2_BRR2 = 0x0B; UART2_BRR1 = 0x08; // BaudRate = 115200.
|
§
|
> Режим передачи данных
| Передающий тракт UART
состоит из двух
регистров: предварительного буферного регистра TDR и сдвигового регистра,
осуществляющего непосредственную побитовую отправку кадра в линию TXD.
После записи байта в регистр
UART_DR он сразу же перемещается в буферный регистр TDR, при этом сбрасывается
флаг готовности буфера TXE в регистре UARTn_SR. Если на текущий момент сдвиговый
регистр оказывается свободным, байт переписывается в него, начинается его отправка и флаг TXE снова устанавливается в единицу. Если же сдвиговый регистр занят, записанный байт будет ожидать завершения отправки текущего
байта в буфере TDR. Таким образом повторная запись в UART_DR при занятом буфере (бит TXE
сброшен) приведёт к потере ожидающего отправки байта. Пример кода для циклической отправки байта по флагу TXE:
while(1) { while (!(UART2_SR_TXE)) {} // Ожидать освобождения буфера TDR.
UART2_DR='S'; // Отправить символ "S".
}
|
Для индикации фактического
завершения передачи байта по UART предназначен флаг TC (transmission is complete) регистра UARTn_CR2. Он устанавливается аппаратно
после передачи последнего бита в линию TXD, но при условии, что в
передающем буфере TDR нет байта ожидающего пересылки в сдвиговый регистр (TXE=1). Таким
образом, при непрерывной передаче конечной последовательности байт по факту освобождения буфера TXE=1, из-за постоянной его занятости, флаг TC
установиться только один раз после фактической передачи последнего байта
последовательности.
При
установке флагов TXE
и TC возможен вызов прерывания, если при этом в регистре UARTn_CR2 установлены биты TIEN
и TCIEN соответственно. Режиму передачи UART сопоставлен всего один
вектор прерывания, а значит при разрешении двух прерываний одновременно,
фактический источник, вызвавший данное прерывание нужно определять программно по
состоянию соответствующих флагов.
Пример программы передающей строку по прерыванию от TXE:
#include "iostm8s105c6.h" #include "intrinsics.h" // Здесь описана функция __enable_interrupt ().
unsigned char HELLO[]="Hello, I'm STM8S105C6, but who are you?"; unsigned char *byteNum = HELLO; // Указатель на передаваемый байт.
void main (void)
{
CLK_ECKR_HSEEN=1; // Разрешаем работу генератора с внешним кварцем (HSEEN).
CLK_SWCR_SWEN=1; // Разрешаем переключение генераторов.
CLK_SWR=0xB4; // Тактирование от кварцевого генератора (HSE).
CLK_CKDIVR=0; // Делители частоты на 1 - частота ядра максимальная.
while (CLK_CMSR!=0xB4); // Ждем стабилизации частоты.
UART2_CR2_REN=UART2_CR2_TEN=1; // Разрешить выводы TX, RX. UART2_BRR2 = 0x0B; UART2_BRR1 = 0x08; // BaudRate = 115200.
UART2_CR2_TIEN=1; // Разрешить прерывание по TXE. Начало передачи.
__enable_interrupt (); // Разрешаем прерывания. while (1) { }
}
#pragma vector=UART2_T_TXE_vector // Прерывание по освобождению буфера.
__interrupt void UART2_TXE(void) { if (*byteNum) { UART2_DR=*byteNum; byteNum++; } // Отправить байт. else UART2_CR2_TIEN=0; // Запретить прерывания по TXE, всё передано. }
|
По
завершении приёма, байт данных из сдвигового регистра перемещается в буферный регистр
RDR, при этом устанавливается бит RXNE регистра статуса UARTn_SR. После чего принятый байт становиться доступным при помощи чтения регистра данных UART_DR, которое, в свою очередь, сбрасывает флаг
RXNE. Если до момента окончания приёма очередного байта, значение байта хранящегося в
RDR не было считано или бит RXNE не был сброшен принудительно, микроконтроллер
зафиксирует ошибку переполнения входного буфера (Overrun error), устанавливив бит
OR регистра UARTn_SR. Для разрешения прерывания по флагу RXNE необходимо установить бит RIEN
регистра UARTn_CR2.
Пример программы с приёмом, декрементом
и отправкой байта по UART:
#include "iostm8s105c6.h" #include "intrinsics.h" //Здесь описана функция __enable_interrupt() void main( void ) { CLK_ECKR_HSEEN=1; // Разрешаем работу генератора с внешним кварцем (HSEEN) CLK_SWCR_SWEN=1; // Разрешаем переключение генераторов; CLK_SWR=0xB4; //Выбираем clock от кварцевого генератора (HSE) CLK_CKDIVR=0; //Делители частоты на 1 - частота ядра максимальная. while(CLK_CMSR!=0xB4); //Ждем стабилизации частоты UART2_CR2_REN=UART2_CR2_TEN=1; // Разрешить выводы TX, RX. UART2_BRR2 = 0x0B; UART2_BRR1 = 0x08; // BaudRate = 115200. UART2_CR2_RIEN=1; // Разрешить прерывание по RXE. __enable_interrupt(); //Разрешаем прерывания while(1) { } } #pragma vector=UART2_R_OR_vector __interrupt void UART2_RXE(void) { UART2_DR=++UART2_DR; // Декремент и отправка принятого числа. }
Проект IAR_STM8 >> STM8UART.RAR
Автоматический расчёт битрейта UART STM8 и его точности.
Введите частоту тактирования UART, МГц:
|
|
Введите ожидаемый битрейт, bps
|
|
|