Главная » Статьи » Уроки по программированию stm32fxxx » Уроки по программированию stm32f4xx

Урок 3: Настрока USART для stm32f4
Краткое описание USART.

Интерфейс USART — последовательный универсальный синхронно-асинхронный приемо-передатчик. Передача данных в USART осуществляется через равные промежутки времени. Этот временной промежуток определяется заданной скоростью USART и указывается в бодах (Для символов, которые могут принимать значения, равные только нулю или единице бод эквивалентен битам в секунду). Существует общепринятый ряд стандартных скоростей: 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 бод.
Помимо бит данных USART автоматически вставляет в поток синхронизирующие метки, так называемые стартовый и стоповый биты. При приёме эти лишние биты удаляются. Обычно стартовый и стоповый биты отделяют один байт информации (8 бит), однако встречаются реализации USART, которые позволяют передавать по 5, 6, 7, 8 или 9 бит. Биты, отделённые стартовым и стоповым сигналами, являются минимальной посылкой. USART позволяет вставлять два стоповых бита при передаче для уменьшения вероятности рассинхронизации приёмника и передатчика при плотном трафике. Приёмник игнорирует второй стоповый бит, воспринимая его как короткую паузу на линии.
Принято соглашение, что пассивным (в отсутствие данных) состоянием входа и выхода USART является логическая «1». Стартовый бит всегда логический «0», поэтому приёмник USART ждёт перепада из «1» в «0» и отсчитывает от него временной промежуток в половину длительности бита (середина передачи стартового бита). Если в этот момент на входе всё ещё «0», то запускается процесс приёма минимальной посылки. Для этого приёмник отсчитывает 9 битовых длительностей подряд (для 8-бит данных) и в каждый момент фиксирует состояние входа. Первые 8 значений являются принятыми данными, последнее значение проверочное (стоп-бит). Значение стоп-бита всегда «1», если реально принятое значение иное, USART фиксирует ошибку.
На рис 1 показана временная диаграмма передаваемых данных по USART.


Рис 1.

Поскольку синхронизирующие биты занимают часть битового потока, то результирующая пропускная способность UART не равна скорости соединения. Например, для 8-битных посылок формата 8-N-1 синхронизирующие биты занимают 20 % потока, что для физической скорости 115 200 бод даёт битовую скорость данных 92160 бит/с или 11 520 байт/с.

Контроль чётности

В протоколе USART имеют возможность автоматически контролировать целостность данных методом контроля битовой чётности. Когда эта функция включена, последний бит данных («бит чётности») всегда принимает значение 1 или 0, так чтобы количество единиц в байте всегда было четным.

Управление потоком

В старые времена устройства с USART могли быть настолько медлительными, что не успевали обрабатывать поток принимаемых данных. Для решения этой проблемы модули USART снабжались отдельными выходами и входами управления потоком. При заполнении входного буфера логика принимающего USART выставляла на соответствующем выходе запрещающий уровень, и передающий USART приостанавливал передачу. Позже управление потоком возложили на коммуникационные протоколы, и надобность в отдельных линиях управления потоком постепенно исчезла.

Область применения.

USART обычно применяется для проводной связи между двумя устройствами, расстояние между которыми не превышает единиц метров. Увеличение дальности связи приводит к зашумлению сигнала и уменьшению вероятности его правильного приёма.
Настройка USART.

Программирование USART в STM32 происходит по следующему алгоритму:
0) Подключить файл, отвечающий за программирование USART в StdPeriph.
1) Включаем тактирование порта (портов), на который выведен USART.
2) Инициализируем выводы USART на работу в альтернативном режиме.
3) Включаем тактирование USART.
4) Инициализируем USART.
5) Разрешаем глобальные прерывания прерывания.
6) Разрешаем прерывания от USART.
7) Включаем работу USART.
На этом инициализация заканчивается.

Пройдёмся по всему по порядку.

0) Для подключения USART надо расскоментировать строку #include "stm32f10x_usart.h" в файле stm32f10x_conf.h.

1) Включение тактирования порта смотрите в лабораторной 1.

2) Stm32f4xx имеет в наличии 3 USART. Каждый вывод USART-а может быть подключен к одному из двух заранее заданных выводов. Конкретные номера выводов можно узнать из технической документации на конкретный микроконтроллер, в которой описываются значения всех выходов.
Подключение выводов к USART производится функцией GPIO_PinAFConfig.
Например так:

GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);

Первым параметром указывается порт на котором необходимый находится вывод. Вторым – номер вывода. Эти номера описаны в виде GPIO_PinSourceх, где х – номер вывода. Вместо этой константы можно прямую записывать номер вывода. Третьим параметром указывается, что именно требуется подключить к данному выводу. Разумеется, это подключение должно быть осуществимо физически. Т.е. требуется заранее убедиться, что к данному выводу можно подключить данное периферийное устройство.
При настройке выводов выбирается режим альтернативной функции. Чтобы USART мог успешно управлять выводом, используемым для передачи данных, его следует настроить на подтягивание к питанию-земле. Для правильной работы входного вывода USART, его требуется подтянуть к питанию, т.к. пассивным состоянием USART считается «1».
Скорость обычно выбирают равной 50МГц.

3) Включение тактирования USART производится функцией:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

Где первый параметр – регистр RCC, второй – команда.
Список устройств, которые включаются этой функцией можно найти в файле stm32f10x_rcc.h.

4) Собственно сама инициализация:
Структура инициализирующая USART описана в файле stm32f10x_usart.h и обозначается как USART_InitTypeDef.
Рассмотрим элементы этой структуры:
В USART_BaudRate описывается скорость передачи и приёма данных. Микроконтроллер может выставить практически любую скорость передачи. Это значение ограничено только частотой тактирования. Причём ограничения касаются не только максимального диапазона, но и точности тактирования USART. Обычно скорость передачи USART принимает одно из следующих стандартных значений: 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600. По-умолчанию это значение обычно принимается равным 9600.
USART_WordLength задаёт длину одной посылки. Stm32f4xx поддерживает только 2 длины в 8 и 9 бит, которые обозначаются соответственно USART_WordLength_8b и USART_WordLength_9b. По-умолчанию это значение обычно принимается равным 8 бит.
USART_StopBits – задаёт количество стоп бит. По-умолчанию это значение обычно принимается равным 1.
USART_Parity – проверка на чётность для увеличения вероятности правильной передачи данных.
По-умолчанию проверка обычно отключается.
USART_Mode определяет режим работы USART. Будет ли тот работать только на передачу, только на приём или сразу в обе стороны. Обозначается соответственно USART_Mode_Tx, USART_Mode_Rx и USART_Mode_Tx|USART_Mode_Rx.
USART_HardwareFlowControl включает аппаратное управление потоком. Может принимать одно из следующих значений:

USART_HardwareFlowControl_None
USART_HardwareFlowControl_RTS
USART_HardwareFlowControl_CTS
USART_HardwareFlowControl_RTS_CTS

По-умолчанию управление потоком обычно отключается.
Инициализация производится функцией USART_Init. Например:

USART_Init(USART1, &USART_InitStructure);

Где первый параметр – идентификатор USART. Второй – Указатель на заполненную структуру.

5) Включение прерываний от USART

NVIC_EnableIRQ(USART1_IRQn);

6) разрешаем прерывания по приёму:

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

7) Включаем USART.

USART_Cmd(USART1, ENABLE);


Теперь опишем функцию прерывания от USART, которая возвращает принятый байт. Только тут стоит учитывать 2 момента:
1) Флаг прерывания зачастую аппаратно не сбрасывается.
2) У USART все прерывания вызывают одну и ту же функцию.

Т.е. нам надо различать прерывания от разных источников и программно сбрасывать флаг прерывания. В итоге функция, вызываемая USART выглядит, так:

void USART1_IRQHandler(void)
{
// Обработка события RXNE (приёма)
if ( USART_GetITStatus(USART1, USART_IT_RXNE) )
{
// очистка бита прерывания
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
//Сюда пишется, что должно произойти приёме одного байта
};
// Обработка события TXE
if ( USART_GetITStatus(USART1, USART_IT_TXE) )
{
// очистка бита прерывания
USART_ClearITPendingBit(USART1, USART_IT_TXE);

//Сюда пишется, что должно произойти после передачи байта.
};

}
}

И последнее, перед посылкой ожидайте отправки предыдущего байта с помощью строки: while (!USART_GetFlagStatus(USART1, USART_SR_TXE)) {}


Т.е. функцию отправки одного байта данных можно написать следующим образом:
//-------------------------------------------------------------------------------------
//Функция отправляющая байт в USART
//-------------------------------------------------------------------------------------
void send_to_USART(uint8_t data)
{
while(!(USART1->SR & USART_SR_TC)); //Ждем пока бит TC в регистре SR станет 1
USART1->DR=data; //Отсылаем байт через USART
}

Пример настройки USART.

Предположим, что нам надо настроить UART1, расположенный на выводе 6 порта В и на выводе 10 порта А. Инициализация с комментариями выглядит следующим образом:

//Прежде всего определяем типы для инициализации выводов и самого USART соответственно.
GPIO_InitTypeDef GPIO_USART_ini;
USART_InitTypeDef USART1_User_ini;

//Включаем тактирования портов А,В и USART1
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

/*Тут заключается основное отличие stm32f4 от stm32f1. USART может быть подлючен к одному из нескольких выводов МК. К какому конкретно определяется ниже. Без этих строк USART подключен НЕ будет.*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

/*Уже известные строки. Режим работы тут разаётся альтернативный, т.к. работает USART. Подтягивание на вход советую сделать к питанию, т.к. по умолчанию именно туда подтягивание линия.*/
GPIO_USART_ini.GPIO_Pin = GPIO_Pin_10;
GPIO_USART_ini.GPIO_Mode = GPIO_Mode_AF;
GPIO_USART_ini.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_USART_ini.GPIO_OType = GPIO_OType_PP;
GPIO_USART_ini.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init(GPIOA, &GPIO_USART_ini);

GPIO_USART_ini.GPIO_Pin = GPIO_Pin_6;
GPIO_USART_ini.GPIO_Mode = GPIO_Mode_AF;
GPIO_USART_ini.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_USART_ini.GPIO_OType = GPIO_OType_PP;
GPIO_USART_ini.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init(GPIOB, &GPIO_USART_ini);


//Тут настраивается сам USART.
USART1_User_ini.USART_BaudRate = 115200;/*задаётся скорость работы. Она может быть любой, которую в принципе может сделать МК.*/
USART1_User_ini.USART_WordLength = USART_WordLength_8b;/*Задаёт длину передаваемых за один раз бай. Либо 8 либо 9.*/
USART1_User_ini.USART_StopBits = USART_StopBits_1;//Количество стоп бит.
USART1_User_ini.USART_Parity = USART_Parity_No;//Проверка чётности.
USART1_User_ini.USART_HardwareFlowControl = USART_HardwareFlowControl_None;/*Аппаратное управление потоком.*/
USART1_User_ini.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//Режим работы на приём и передачу.

//Инициализируем USART
USART_Init(USART1, &USART1_User_ini);

//Включаем общие прерывания от USART.
NVIC_EnableIRQ(USART1_IRQn);

//Включаем прерывания по приёму.
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

//Включаем USART.
USART_Cmd(USART1, ENABLE);

На этом инициализация заканчивается.

Если хотите передавать данные, это делается функцией:

void send_to_PC(uint16_t data)
{
while(!(USART1->SR & USART_SR_TC));//Ждём кокончания передачи
USART_SendData(USART1, data);//Передаём
}

Приём производится обычно в прерывании следующим образом:
//-------------------------------------------------------------------------------------
// From PC
//-------------------------------------------------------------------------------------

void USART1_IRQHandler(void)
{
// RXNE прерывания по приёму
if ( USART_GetITStatus(USART1, USART_IT_RXNE) )
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
send_to_PC(USART_ReceiveData(USART1));
};

// TXE прерывания по передаче
if ( USART_GetITStatus(USART1, USART_IT_TXE) )
{
USART_ClearITPendingBit(USART1, USART_IT_TXE);
};
}
Категория: Уроки по программированию stm32f4xx | Добавил: Korvin (27.09.2013)
Просмотров: 10504 | Рейтинг: 5.0/2
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]