STM32F USART настрой и использование с помощью SPL.
В статье я опишу как настроить USART и использовать для приёма-передачи данных а так же подключить к выводам контроллера используя функцию переназначения(Remap). Если кто не знает в чём различие между UART и USART это наличие у последнего возможности использования дополнительной линии для синхронизации передачи данных, а так они одинаковы.
Для примера я буду использовать популярный контроллер STM32f103C8, USB-UART на чипе CH340G переходник(преобразователь) и свою программу UART терминал-помощник(скачать можно в разделе программы).
Первым делом нужно разобраться с подключением или сопряжением двух устройств, основное условие это то, что каждое устройство должно обеспечить подтяжку своей линии RX через резистор к питанию в моём случае микросхема CH340G обеспечивает внутрисхемную подтяжку как линии RX так и TX, подтягивающие резисторы не нужны.
Схема подключения обычное(Default) и к дополнительным выводам через перенаправление(Remap) а также пример соединение двух контроллеров на примере USART2 и USART3.
Пример настройки для обычного подключения, к выводам по умолчанию.
#include "stm32f10x.h"
int main(){
RCC_DeInit();
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1| RCC_APB2Periph_GPIOA, ENABLE);
/*Настройка выводов контроллера для USART.*/
GPIO_InitTypeDef gpio_uart;
gpio_uart.GPIO_Mode=GPIO_Mode_AF_OD;
gpio_uart.GPIO_Pin=GPIO_Pin_9;
gpio_uart.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init( GPIOA,&gpio_uart);
gpio_uart.GPIO_Mode=GPIO_Mode_IN_FLOATING;
gpio_uart.GPIO_Pin=GPIO_Pin_10;
GPIO_Init( GPIOA,&gpio_uart);
/*Настройка самого USART.*/
USART_InitTypeDef settings_UART1;
settings_UART1.USART_BaudRate=9600;
settings_UART1.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
settings_UART1.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
settings_UART1.USART_Parity=USART_Parity_No;
settings_UART1.USART_StopBits=USART_StopBits_1;
settings_UART1.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&settings_UART1);
USART_Cmd(USART1, ENABLE);
while(1){}
return 0;
}
Для подключения через переназначение нам нужно знать какие выводы контроллера являются альтернативными, смотрим Datasheets.
Пример перенаправления выводов и настройки USART.
#include "stm32f10x.h"
int main(){
RCC_DeInit();
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1| RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef gpio_uart;
gpio_uart.GPIO_Mode=GPIO_Mode_AF_OD;
gpio_uart.GPIO_Pin=GPIO_Pin_6;
gpio_uart.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init( GPIOB,&gpio_uart);
gpio_uart.GPIO_Mode=GPIO_Mode_IN_FLOATING;
gpio_uart.GPIO_Pin=GPIO_Pin_7;
GPIO_Init( GPIOB,&gpio_uart);
/*Переназначаем выводы USART.*/
GPIO_PinRemapConfig( GPIO_Remap_USART1, ENABLE);
USART_InitTypeDef settings_UART1;
settings_UART1.USART_BaudRate=9600;
settings_UART1.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
settings_UART1.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
settings_UART1.USART_Parity=USART_Parity_No;
settings_UART1.USART_StopBits=USART_StopBits_1;
settings_UART1.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&settings_UART1);
USART_Cmd(USART1, ENABLE);
while(1){}
return 0;
}
Пример подключения двух микросхем через USART, у меня будут соединены USART2 и USART3 данного контроллера.
#include "stm32f10x.h"
int main(){
RCC_DeInit();
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2| RCC_APB1Periph_USART3, ENABLE);
GPIO_InitTypeDef gpio_uart;
gpio_uart.GPIO_Mode=GPIO_Mode_AF_OD;
gpio_uart.GPIO_Pin=GPIO_Pin_2;
gpio_uart.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init( GPIOA,&gpio_uart);
gpio_uart.GPIO_Pin=GPIO_Pin_10;
GPIO_Init( GPIOB,&gpio_uart);
/*Выводы RX подтянуты к питанию.*/
gpio_uart.GPIO_Mode=GPIO_Mode_IPU;
gpio_uart.GPIO_Pin=GPIO_Pin_3;
GPIO_Init( GPIOA,&gpio_uart);
gpio_uart.GPIO_Pin=GPIO_Pin_11;
GPIO_Init( GPIOB,&gpio_uart);
USART_InitTypeDef settings_UART;
settings_UART.USART_BaudRate=9600;
settings_UART.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
settings_UART.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
settings_UART.USART_Parity=USART_Parity_No;
settings_UART.USART_StopBits=USART_StopBits_1;
settings_UART.USART_WordLength=USART_WordLength_8b;
USART_Init(USART2,&settings_UART);
USART_Cmd(USART2, ENABLE);
USART_Init(USART3,&settings_UART);
USART_Cmd(USART3, ENABLE);
while(1){}
return 0;
}
Отправка и приём данных через USART.
Тут будем пробовать отправлять и принимать данные, для этого качаем мою программу UART терминал-помощник, устанавливаем и подключаем наш контроллер через USB-URAT конвертер к компьютеру.
Первый пример отслеживаем приход данных в коде программы, контроллер принимает данные и тут же отсылает ответ, что должно отразится в программе терминале.
#include "stm32f10x.h"
int main(){
RCC_DeInit();
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1| RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef gpio_uart;
gpio_uart.GPIO_Mode=GPIO_Mode_AF_OD;
gpio_uart.GPIO_Pin=GPIO_Pin_9;
gpio_uart.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init( GPIOA,&gpio_uart);
gpio_uart.GPIO_Mode=GPIO_Mode_IN_FLOATING;
gpio_uart.GPIO_Pin=GPIO_Pin_10;
GPIO_Init( GPIOA,&gpio_uart);
USART_InitTypeDef settings_UART1;
settings_UART1.USART_BaudRate=9600;
settings_UART1.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
settings_UART1.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
settings_UART1.USART_Parity=USART_Parity_No;
settings_UART1.USART_StopBits=USART_StopBits_1;
settings_UART1.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&settings_UART1);
USART_Cmd(USART1, ENABLE);
while(1){
/*Проверяем наличие принятых данных.*/
if(USART_GetFlagStatus( USART1, USART_FLAG_RXNE)){
/*Читаем данные и после этого сам сбрасывается флаг приёма данных.*/
uint16_t data = USART_ReceiveData(USART1);
/*Отвечаем, отсылаем обратно принятый байт данных.*/
USART_SendData(USART1, (uint8_t)(data));
while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));
}
}
return 0;
}
Для сброса флага принятого байта данных нужно прочесть принимающий регистр функцией uint16_t USART_ReceiveData(USART_TypeDef* USARTx); или самостоятельно сбросить функцией USART_ClearFlag( USART_TypeDef* USARTx, USART_FLAG_RXNE);.При отправке данных особенно циклическим методом обязательно ждите пока освободится сдвиговой регистр кодом while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));, иначе контроллер может не успеть отправить данные и вы их перепишите.И последний пример отправки и приёма данных в прерывании. Программа будет принимать пять байт данных и отправлять их обратно.
#include "stm32f10x.h"
/*Массив для отправки данных и его счётчик. */
uint8_t send_data[5];
uint16_t count_dataSend=0;
/*Массив для приёма данных и его счётчик.*/
uint8_t received_data[5];
uint16_t count_dataReceived=0;
int main(){
RCC_DeInit();
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1| RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef gpio_uart;
gpio_uart.GPIO_Mode=GPIO_Mode_AF_OD;
gpio_uart.GPIO_Pin=GPIO_Pin_9;
gpio_uart.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init( GPIOA,&gpio_uart);
gpio_uart.GPIO_Mode=GPIO_Mode_IN_FLOATING;
gpio_uart.GPIO_Pin=GPIO_Pin_10;
GPIO_Init( GPIOA,&gpio_uart);
USART_InitTypeDef settings_UART1;
settings_UART1.USART_BaudRate=9600;
settings_UART1.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
settings_UART1.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
settings_UART1.USART_Parity=USART_Parity_No;
settings_UART1.USART_StopBits=USART_StopBits_1;
settings_UART1.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&settings_UART1);
USART_ClearFlag( USART1, USART_FLAG_RXNE);
USART_ITConfig( USART1, USART_IT_RXNE, ENABLE);
/*Включаем прерывание.*/
NVIC_EnableIRQ( USART1_IRQn);
USART_Cmd(USART1, ENABLE);
while(1){
/*Если принято 5 байт данных то отсылаем их обратно.*/
if( count_dataReceived == 5 ){
/*Переписываем счётчик отправляемых данных и массив для отправки данных.*/
count_dataSend = count_dataReceived;
for( uint16_t count = 0; count != count_dataReceived; count++ ){ send_data[count] = received_data[count];}//
count_dataReceived = 0;
/*Включаем прерывание если пустой регистр отправки данных.*/
USART_ITConfig( USART1, USART_IT_TXE, ENABLE);
}
}
return 0;
}
/*Обработчик прерываний USART приёма и отправки данных.*/
void USART1_IRQHandler(){
/*Принимаем данные и копируем их в массив.*/
if( USART_GetFlagStatus( USART1, USART_FLAG_RXNE )){
received_data[ count_dataReceived ] = USART_ReceiveData( USART1 );
count_dataReceived++;
}
/*Отправка данных, после отправки всех данных выключаем прерывание.*/
if( count_dataSend > 0 ){
/*Данные отправляются в обратном порядке.*/
USART_SendData( USART1, (uint8_t)( count_dataSend));
count_dataSend--;
if(count_dataSend == 0){ USART_ITConfig( USART1, USART_IT_TXE, DISABLE);}
}
}