Подробное объяснение приемопередатчика последовательного порта на основе STM32 (библиотека HAL)
Подробное объяснение приемопередатчика последовательного порта на основе STM32 (библиотека HAL)

представлять

Связь через последовательный порт (универсальный асинхронный приемник-передатчик UART, TTL) представляет собой последовательный полнодуплексный метод связи между устройствами. Поскольку UART является асинхронной передачей и не передает синхронные часы, для обеспечения точности данных UART использует тактовый сигнал, в 16 раз превышающий скорость передачи данных для выборки. Поскольку это просто и удобно, большинство электронного оборудования поддерживает этот метод связи. Инженеры часто используют этот метод для вывода отладочной информации при отладке оборудования. Подробности в этой статьепредставлять Как написать программу приемопередатчика последовательного порта,Мы используем часто используемую логику отправки и получения.,Отправьте непосредственно написанную функцию для реализации,Прием завершается с помощью прерываний. Прерывание приема использует два метода запуска прерывания при приеме байта и кадра данных.

Прерывание USART

USART имеет несколько событий запроса прерывания.

Причина, по которой это звание Прерывание Запрос USART вызван тем, что многие люди на начальном этапе не очень хорошо знают, как оценить статус прерывания последовательного порта, поэтому я сосредоточусь здесь на должности. Как правило, после того, как мы запустим и настроим прерывание последовательного порта, при входе в обработчик прерывания последовательного порта возникнет множество ситуаций. Мы также можем выбрать, какие ситуации прерывания последовательного порта открывать. В обычных обстоятельствах флаги событий прерывания, которые мы в основном используем при принятии, — это RXNE и IDLE. RXNE — это прерывание приема. Это прерывание запускается каждый раз при получении байта. Это также наиболее часто используемый запрос прерывания. IDLE Это прерывание по простою. Каждый раз, когда принимается кадр данных, шина временно простаивает, и срабатывает это прерывание.

Статус последовательного порта

Статус последовательного порта можно прочитать через регистр состояния USART_SR. Ребята из USART_SR описывают это следующим образом:

Здесь мы сосредоточимся на двух битах: битах 5 и 6 RXNE и TC. RXNE (регистр считанных данных не пуст), когда этот бит установлен в 1, это указывает, что данные получены и могут быть считаны. Что нам нужно сделать в этот момент, так это как можно скорее прочитать USART_DR. Читая USART_DR, этот бит можно очистить, или мы можем записать 0 в этот бит, чтобы очистить его напрямую. TC (передача завершена), когда этот бит установлен, это означает, что данные в USART_DR были отправлены. Если этот бит установлен, будет сгенерировано прерывание. Есть два способа очистить этот бит:

  1. Прочтите USART_SR,USART_DR.
  2. Запишите 0 непосредственно в этот бит.

Пример

анализ потребностей

Этот проект в основном пишет трансивер последовательного порта. Использование STM32F103C8T6 в качестве MCU,Используйте помощник по отладке последовательного порта на ПК в качестве главного компьютера. Каждый раз, когда ПК отправляет кадр данных в MCU, Каждый раз, когда MCU получает байт данных, он проверяет, есть ли в данных команда 0x23. При получении команды 0x23 MCU отправляет «ПК» на главный компьютер. Когда получен один кадр данных, MCU отправляет «Receive a frame data”.

Инициализация последовательного порта

Общие этапы инициации постепенного порта можно резюмировать следующим образом:

  1. Часы последовательного порта включены и часы GPIO включены.
  2. Установите сопоставление выводов мультиплексора: вызовите функцию GPIO_PinAFConfig.
  3. Настройка инициализации GPIO: установите режим мультиплексирования.
  4. Инициализация параметров последовательного порта: установка скорости передачи данных, длины слова, четности и других параметров.
  5. Включите прерывания, инициализируйте NVIC и разрешите прерывания (этот шаг требуется только в том случае, если прерывания необходимо включить).
  6. Включите последовательный порт.
Язык кода:javascript
копировать
#include "usart.h"
#include <stdio.h>
#include "stm32f1xx_hal.h
UART_HandleTypeDef huart3
void MX_USART3_UART_Init(void)

  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler()
  __HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);//получим разрешение прерывания
  __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);//Разрешение прерывания простоя 
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART3)
  {
    __HAL_RCC_USART3_CLK_ENABLE()
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**USART3 GPIO Configuration
    PB10     ------> USART3_TX
    PB11     ------> USART3_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct)
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART3_IRQn);

Обычно нам нужно изменить некоторую конфигурацию параметров последовательного порта.

  • BaudRate: скорость передачи данных
  • WordLength;: длина слова
  • StopBits: стоп-биты
  • Паритет: проверка четности
  • Режим: настройка режима приема/приема
  • HwFlowCtl: настройки аппаратного потока
  • OverSampling: настройки передискретизации.

Отправка через последовательный порт

Отправка через последовательный порт Используемый здесь метод непрерывной отправки.

Язык кода:javascript
копировать
/*******************************************************************************
  * @имя функции  USART_Send
  * @описание функции   Отправить сообщение
  * @входные параметры   _UART: номер последовательного порта
      данные: первый адрес информации, которая будет отправлена.
      len: отправленная длина
  * @выходной параметр   никто
  * @return параметры   никто
*******************************************************************************/
void USART_Send(USART_TypeDef *_UART,uint8_t *data,uint8_t len)
{
  for(int i;i<len;i++)
  {
    HAL_UART_Transmit(&huart3,&data[i],1,1000);
  }
}

В основном используютсяHAL_UART_Transmit(&huart3,&Res,1,0Xffff); Это функция блокировки отправки, поэтому нет необходимости повторно определять, завершил ли последовательный порт отправку. Отправляйте каждый символ до тех пор, пока не встретите нулевой символ. Первый параметр — это номер последовательного порта, второй параметр — начальный адрес отправляемых данных, третий — длина отправляемых данных и четвертый — время ожидания (если передача не увенчалась успехом после этой длины). , блокировка завершена и прекращается. Отправлено, выполнение функции завершено).

Прием последовательного порта

Здесь Прием последовательного Порт использует метод прерывания. Категория прерывания уже упомянута в начале статьи. Мы устанавливаем тип прерывания, которое срабатывает при инициализации. установлено в этой статье

Язык кода:javascript
копировать
__HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);//получим разрешение прерывания
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);//Разрешение прерывания простоя

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

Язык кода:javascript
копировать
void USART3_IRQHandler(void)
{
  uint8_t Res;
if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE)!=RESET
{
  HAL_UART_Receive(&huart3,&Res,1,0Xffff); 
 if(Res==0x23)  
  printf("PC");
}
else if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)!=RESET)//Прерывание ожидания (означает, что передача данных этого кадра завершена)
{
  printf("Receive a frame data.");
  __HAL_UART_CLEAR_IDLEFLAG(&huart3);
}

Давайте рассмотрим ключевые моменты здесь один за другим. Первый — определить бит флага. Мы используем функцию __HAL_UART_GET_FLAG() в библиотеке HAL, которая имеет два параметра: первый — это дескриптор последовательного порта, а второй — конкретный бит флага. if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE)!=RESET)Используется для определения того, обнаружено ли однобайтовое прерывание.。 if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)!=RESET) используется для определения наличия прерывания по простою (это означает, что передача данных этого кадра завершена).

Перенаправление printf и scanf

Еще следует отметить, что для использования функций fput и fgetc для перенаправления функций ввода и вывода стандартной библиотеки языка C необходимо установить флажок «Использовать MicroLIB» в параметрах проекта MDK. MicroLIB является альтернативой библиотеке C по умолчанию. Стандартная библиотека C оптимизирована для использования меньшего количества кода и ресурсов. Чтобы использовать функции printf и scanf, вам необходимо включить в файл заголовочный файл stdio.h.

Язык кода:javascript
копировать
/**
  * Функция функция: Перенаправить функцию библиотеки c printf
  * Входные параметры: никто
  * возвращаться раз ценить: никто
  * объяснять    яркий:никто
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * Функция функция: Перенаправить функции библиотеки C getchar, scanf
  * Входные параметры: никто
  * возвращаться раз ценить: никто
  * объяснять    яркий:никто
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart3, &ch, 1, 0xffff);
  return ch;
}

Эффект

  1. ПК выдано: 11 22 33 44
  1. ПК выпущено: 12 23 34 45
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose