Уважаемые посетители, коллеги и друзья, традиционно снова рад приветствовать вас на нашем сайте 🤝 Давеча разговорились мы с пользователем TQFP на тему разрастания и продвижения нашего сообщества, в результате чего он выразил желание оформить небольшой курс по подключению простейших, но что более важно, наиболее популярных датчиков к STM32. Основные цели в этом действе двояки - это как облегчение старта и понижение порога вхождения для тех, кто только начинает ступать на тропу работы с микроконтроллерами, так и потенциальная оптимизация/доработка для опытных профессионалов, так или иначе уже использующих то, о чем пойдет речь. Собственно, TQFP решил взять за базу готовый набор датчиков, который у него есть в наличии под рукой - а именно этот (набор датчиков 37 в 1):

Многие входящие в состав набора компоненты слишком просты в использовании для того, чтобы посвящать им отдельный материал, поэтому мы договорились, чтобы в таком случае уделять больше внимания каким-либо скрытым на первый взгляд деталям, либо интересным практическим применениям. Кроме того, я на фоне данной беседы вспомнил, что и у меня где-то пылится аналогичный набор, так что я тоже сделаю пару статей на эту тему. Но в данном случае несколько проявлю наглость и на себя возьму только то, что мне более-менее интересно самому )
Ну и, в общем-то, одна из ближайших по плану статей у меня о реализации ПИД-регулятора на STM32, поскольку очень много поступает запросов именно о практическом примере использования ПИДа. И поэтому из коробки с датчиками я извлек на свет датчик температуры DS18B20 (модуль KY-001), на базе которого осуществим работу с шиной 1-Wire на STM32.
Начнем, опять же традиционно, с краткого экскурса в некоторые историко-теоретические аспекты. Для работы с датчиком используется уже упомянутая шина 1-Wire, которая является двунаправленной шиной для обмена данными с устройствами на относительно невысокой скорости (не более 125 Кбит/с). Разработана шина была компанией Dallas Semiconductor, которая является и производителем DS18B20. Отличительной особенностью можно считать то, что для полноценного подключения устройств нужны лишь две линии:
- общая (GND)
- одна линия как для передачи данных, так и для питания. То есть подача питания осуществляется той же линией, что и служит для передачи полезной информации.
Для вводного слова думаю достаточно, переходим к активной деятельности 👍 Итак, что у нас по аппаратной части. Пункт первый - непосредственно датчик DS18B20 в виде модуля KY-001. Пункт второй, завершающий - плата с микроконтроллером STM32F401CC. Какой именно контроллер использовать особой роли не играет, библиотеку для работы с 1-Wire будем, конечно же, делать универсальной по максимуму. Ввиду растущей популярности проекты для сайта и сейчас делаю в STM32CubeIDE, что также до неприличия облегчает процесс потенциального переноса ПО на другой контроллер.
Для работы с датчиком есть 2 основных способа:
- Bit-banging - то есть датчик подключается к любому порту GPIO и обмен данными происходит путем дергания этой ногой, а также считывания ее состояния вручную.
- С использованием USART. Именно этот способ я задействую, как более интересный и оптимальный.
Настройка и инициализация периферии.
С электрической частью покончили, переходим к созданию проекта и настройке необходимой периферии в STM32CubeMx. Активируем базово-необходимые вещи, такие как внешний кварцевый резонатор и интерфейс SWD для отладки:

Тактовые частоты зададим так:

Но опять же, в данном конкретном проекте это все не слишком существенно. Больше внимания уделим непосредственно USART'у. Я взял USART1, соответственно, обмен данными будет осуществляться через PA9. Настраиваем следующим образом:

Касаемо скорости передачи данных еще поговорим, по умолчанию ставим 115200 Бит/с. На этом заканчиваем с частью, посвященной периферии, и перемещаемся к программной реализации.
Принцип работы 1-Wire.
Сразу же структурируем проект подобающий образом, создав файлы для работы с шиной (onewire.c/onewire.h). В них инкапсулируем всю низкоуровневую часть для обмена данными, на базе которой впоследствии надстроим работу конкретно с датчиком DS18B20:

И начнем с разбора того, как мы собственно будем взаимодействовать с 1-Wire. И все процессы будут заключены всего лишь в 4-х возможных операциях:
- Команда сброса
- Передача бита 1.
- Передача бита 0.
- Чтение бита.
Так что планомерно и систематично добавим поддержку перечисленного, и на этом можно будет переходить к следующему этапу. Итак, команда сброса... Официальная документация говорит нам следующее:

То есть команда сброса представляет из себя не что иное, как низкий уровень на линии на протяжении обозначенного времени. Вспоминаем, что мы решили использовать USART и производим необходимые расчеты. Классический метод заключается в том, что при отправке команды сброса, USART переконфигурируется на скорость передачи данных 9600 бит/с. При данной скорости время передачи одного бита составляет:
T_{bit} = \frac{1000000 \medspace мкс}{9600 } = 104 \medspace мксИтого - для генерации Reset'а отправим в USART байт 0xF0 (0b11110000). Что это нам даст? Тут все просто - биты будут передаваться, начиная с младшего, значит первой будет выдана последовательность из четырех нулей. Приплюсовываем к этому нулевой старт-бит USART'а и получаем 5 бит, что эквивалентно низкому уровню на шине на протяжении 5 * 104 мкс = 520 мкс:

Это в свою очередь полностью соответствует внешнему виду команды Reset 👍 После отправки 0xF0 встаем на прием, и в том случае, если на шине присутствуют другие устройства, мы примем значение, не равное тому, что мы отправили. Если же устройств на шине нет, то примем ровно то, что отправили, а именно 0xF0, поскольку фактически Tx и Rx USART'а у нас замкнуты (одна линия для передачи данных по шине). Таким вот способом будет осуществляться обнаружение подключенных датчиков.
На этом с первым пунктом интерфейсной части успешно прощаемся. Переходим к передачи информационных битов. Передача единицы:

Как видите, механизм при работе с 1-Wire един и неизменен - по умолчанию линия подтянута к питанию, устройства же взаимодействуют выдачей на линию нуля. Вся разница только в длительностях. В данном случае для передачи единицы необходимо подать ноль на время, соответствующее интервалу 1-15 мкс. Да, кстати, скорость 9600 бит/с будет использоваться только и исключительно для команды Reset. Для оставшихся трех пунктов переконфигурируем снова на 115200 бит/с. С этим наглядно разберемся на практическом примере.
На скорости 115200 бит/с передача одного бита это:
T_{bit} = \frac{1000000 \medspace мс}{115200} = 8.7 \medspace мсПоэтому передавать будем байт 0xFF, что вкупе со старт-битом даст нам требуемое:

Сразу же рассмотрим и передачу нуля:

Все то же самое, разница, как мы уже обсудили, только во временных интервалах. Передаем в USART 0x00, имеем:

Все четко! Остается только один пункт - чтение информационного бита. И снова все завязано на физическом устройстве шины, при котором линия подтянута вверх, а устройства при возникновении такого желания опускают ее вниз принудительно. Для чтения осуществляем выдачу 0xFF в USART (по-прежнему на 115200) и встаем на прием данных. При приеме в ответ того же байта 0xFF делаем вывод, что приняли бит "1", при любом другом значении - приняли "0". Собираем все вышеобозначенное воедино в графической инсталляции )
| 1-Wire | USART baudrate | USART data |
|---|---|---|
| Reset | 9600 Кбит/с | 0xF0 |
| Bit 1 | 115200 Кбит/с | 0xFF |
| Bit 0 | 115200 Кбит/с | 0x00 |
То есть при обмене данными одному биту на шине 1-Wire соответствует один байт (8 бит), передаваемый/принимаемый по USART. С общей концепцией разобрались, если и остались какие-либо неявные моменты, то их мы без проблем развеем при помощи пресловутого практического примера, к которому и переходим.
Библиотека для работы с шиной 1-Wire на STM32.
Периферия у нас уже готова, то есть проинициализирована усилиями CubeMx, на нас же ложится вся интеллектуальная часть взаимодействия. Пойдем, дабы не нарушать целостность изложения, по тем же шагам, которые мы обсудили. Поэтому и начинаем снова с команды Reset, из которой сразу же следует необходимость перестраивать скорость передачи данных по USART на лету. И этой цели послужит соответствующая функция, принимающая в качестве аргумента ту самую требуемую скорость:
/*----------------------------------------------------------------------------*/
static void SetBaudrate(UART_HandleTypeDef *huart, uint32_t baudrate)
{
uint32_t pclk = 0;
huart->Init.BaudRate = baudrate;
#if defined(USART6) && defined(UART9) && defined(UART10)
if ((huart->Instance == USART1) || (huart->Instance == USART6) ||
(huart->Instance == UART9) || (huart->Instance == UART10))
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#elif defined(USART6)
if ((huart->Instance == USART1) || (huart->Instance == USART6))
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#else
if (huart->Instance == USART1)
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#endif /* USART6 */
else
{
pclk = HAL_RCC_GetPCLK1Freq();
}
if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
{
huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
}
else
{
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
}
}
/*----------------------------------------------------------------------------*/
У меня здесь использован контроллер STM32F4xx, поэтому при переходе на другое семейство потребуется внести изменения. В общем-то, похожую часть кода можно найти в HAL'овской static void UART_SetConfig(UART_HandleTypeDef *huart). Поэтому в случае необходимости нужно без лишних сомнений и сложностей позаимствовать оттуда 👍 Все готово для осуществления деятельности по выполнению команды сброса:
/*----------------------------------------------------------------------------*/
ONEWIRE_Status OneWire_Reset(UART_HandleTypeDef *huart)
{
OneWire_ProcessByte(huart, 0x43);
ONEWIRE_Status status = ONEWIRE_OK;
uint8_t txByte = ONEWIRE_RESET_BYTE;
uint8_t rxByte = 0x00;
SetBaudrate(huart, ONEWIRE_RESET_BAUDRATE);
HAL_UART_Transmit(huart, &txByte, 1, ONEWIRE_UART_TIMEOUT);
HAL_UART_Receive(huart, &rxByte, 1, ONEWIRE_UART_TIMEOUT);
SetBaudrate(huart, ONEWIRE_BAUDRATE);
if (rxByte == txByte)
{
status = ONEWIRE_ERROR;
}
return status;
}
/*----------------------------------------------------------------------------*/
Здесь все в точности по тем теоретическим принципам, которые мы уже обсудили. Отправляем 0xF0 (ONEWIRE_RESET_BYTE) и по ответу делаем вывод о наличии устройств на шине. Все определения в onewire.h:
#define ONEWIRE_BAUDRATE 115200
#define ONEWIRE_RESET_BAUDRATE 9600
#define ONEWIRE_RESET_BYTE 0xF0
#define ONEWIRE_UART_TIMEOUT 10
#define ONEWIRE_BITS_NUM 8
typedef enum
{
ONEWIRE_OK = 0x00,
ONEWIRE_ERROR = 0x01,
} ONEWIRE_Status;
Для отправки и получения полезных данных у нас будут функции:
uint8_t OneWire_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte)uint8_t OneWire_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit)
В первую мы передаем байт, которой необходимо выдать на шину, а также указатель на структуру, соответствующую используемому USART'у, определение которой для конкретного случая можно найти в main.c:
/* Private variables ---------------------------------------------------------*/ UART_HandleTypeDef huart1;
Структура HAL подразумевает генерацию кода такого вида для любой выбранной периферии. Итак, возвращаемся к передаче информации.
OneWire_ProcessByte() принимает аргументом байт данных. И здесь имеется ввиду именно один байт в контексте 1-Wire. А как мы уже выяснили, выдача одного байта в шину 1-Wire представляет из себя выдачу 8-ми байт в USART (1 бит 1-wire = 1 байт в USART, 8 бит 1-wire = 8 байт в USART). Поэтому байт, переданный в OneWire_ProcessByte(), мы разбиваем на биты и передаем в функцию OneWire_ProcessBit():
/*----------------------------------------------------------------------------*/
uint8_t OneWire_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte)
{
uint8_t rxByte = 0x00;
for (uint8_t i = 0; i < ONEWIRE_BITS_NUM; i++)
{
uint8_t txBit = (byte >> i) & 0x01;
uint8_t rxBit = 0;
uint8_t tempRxData = OneWire_ProcessBit(huart, txBit);
if (tempRxData == 0xFF)
{
rxBit = 1;
}
rxByte |= (rxBit << i);
}
return rxByte;
}
/*----------------------------------------------------------------------------*/
uint8_t OneWire_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit)
{
uint8_t txData = 0xFF;
uint8_t rxData = 0x00;
if (bit == 0)
{
txData = 0x00;
}
HAL_UART_Transmit(huart, &txData, 1, ONEWIRE_UART_TIMEOUT);
HAL_UART_Receive(huart, &rxData, 1, ONEWIRE_UART_TIMEOUT);
return rxData;
}
/*----------------------------------------------------------------------------*/
Если посмотреть на табличку, которую мы организовали, то все четко по ней здесь и происходит. Вычленяем txBit из byte и запихиваем его в OneWire_ProcessBit(). Если бит "1", то в USART улетает 0xFF, иначе - 0x00. Сразу же встаем на прием и, если приняли 0xFF (if (tempRxData == 0xFF)), то это сигнализирует о том, что с 1-Wire принят бит "1" - rxBit = 1 - в противном случае rxBit будет равен 0. Остается поместить бит в rxByte на нужную позицию - rxByte |= (rxBit << i). И в итоге на выходе из функции OneWire_ProcessByte() мы имеем принятый байт rxByte.
Полный код созданных файлов получаем такой:
/**
******************************************************************************
* @file : onewire.c
* @brief : 1-Wire driver
* @author : MicroTechnics (microtechnics.ru)
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "onewire.h"
/* Declarations and definitions ----------------------------------------------*/
/* Functions -----------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
static void SetBaudrate(UART_HandleTypeDef *huart, uint32_t baudrate)
{
uint32_t pclk = 0;
huart->Init.BaudRate = baudrate;
#if defined(USART6) && defined(UART9) && defined(UART10)
if ((huart->Instance == USART1) || (huart->Instance == USART6) ||
(huart->Instance == UART9) || (huart->Instance == UART10))
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#elif defined(USART6)
if ((huart->Instance == USART1) || (huart->Instance == USART6))
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#else
if (huart->Instance == USART1)
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#endif /* USART6 */
else
{
pclk = HAL_RCC_GetPCLK1Freq();
}
if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
{
huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
}
else
{
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
}
}
/*----------------------------------------------------------------------------*/
uint8_t OneWire_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit)
{
uint8_t txData = 0xFF;
uint8_t rxData = 0x00;
if (bit == 0)
{
txData = 0x00;
}
HAL_UART_Transmit(huart, &txData, 1, ONEWIRE_UART_TIMEOUT);
HAL_UART_Receive(huart, &rxData, 1, ONEWIRE_UART_TIMEOUT);
return rxData;
}
/*----------------------------------------------------------------------------*/
uint8_t OneWire_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte)
{
uint8_t rxByte = 0x00;
for (uint8_t i = 0; i < ONEWIRE_BITS_NUM; i++)
{
uint8_t txBit = (byte >> i) & 0x01;
uint8_t rxBit = 0;
uint8_t tempRxData = OneWire_ProcessBit(huart, txBit);
if (tempRxData == 0xFF)
{
rxBit = 1;
}
rxByte |= (rxBit << i);
}
return rxByte;
}
/*----------------------------------------------------------------------------*/
ONEWIRE_Status OneWire_Reset(UART_HandleTypeDef *huart)
{
ONEWIRE_Status status = ONEWIRE_OK;
uint8_t txByte = ONEWIRE_RESET_BYTE;
uint8_t rxByte = 0x00;
SetBaudrate(huart, ONEWIRE_RESET_BAUDRATE);
HAL_UART_Transmit(huart, &txByte, 1, ONEWIRE_UART_TIMEOUT);
HAL_UART_Receive(huart, &rxByte, 1, ONEWIRE_UART_TIMEOUT);
SetBaudrate(huart, ONEWIRE_BAUDRATE);
if (rxByte == txByte)
{
status = ONEWIRE_ERROR;
}
return status;
}
/*----------------------------------------------------------------------------*/
/**
******************************************************************************
* @file : onewire.h
* @brief : 1-Wire driver
* @author : MicroTechnics (microtechnics.ru)
******************************************************************************
*/
#ifndef ONEWIRE_H
#define ONEWIRE_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/* Declarations and definitions ----------------------------------------------*/
#define ONEWIRE_BAUDRATE 115200
#define ONEWIRE_RESET_BAUDRATE 9600
#define ONEWIRE_RESET_BYTE 0xF0
#define ONEWIRE_UART_TIMEOUT 10
#define ONEWIRE_BITS_NUM 8
typedef enum
{
ONEWIRE_OK = 0x00,
ONEWIRE_ERROR = 0x01,
} ONEWIRE_Status;
/* Functions -----------------------------------------------------------------*/
extern ONEWIRE_Status OneWire_Reset(UART_HandleTypeDef *huart);
extern uint8_t OneWire_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte);
extern uint8_t OneWire_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit);
#endif // #ifndef ONEWIRE_H
И вот на этом месте сделаем паузу... Поскольку статья получилась объемнее, чем я планировал, а я не очень люблю чересчур затянутые материалы, да и поисковики их не так чтобы сильно любят, поэтому разобьем работу с 1-Wire на две части. В ближайшее время выйдет вторая, в которой будем использовать созданное сегодня, и сразу перейдем непосредственно к получению данных с DS18B20. Так что до скорого🤝
Ссылка на проект (здесь уже содержится и часть для работы с датчиком из следующей статьи) - MT_DS18B20_Project.




Спасибо большое за статью. Написано всё очень просто и разложено по полочкам.
Благодарю)
Добрый день, спасибо за материал, мкс поправьте в формулах, а то я ступор мозговины поймал: время передачи одного бита делю 1/9600 = 1,04*10^-4 секунд = 104мкс.
Благодарю )
Еще бы статью с bit-bang тоже бы сделать. Через прерывания. Было бы интересно почитать.
Есть еще способ через таймер шим
файлы onewire.c or onewire.h зеркало. у кого как и что могло получиться , хз
А, ну вставил одно и то же под спойлер случайно, сейчас обновлю. В архиве полный проект со всеми файлами - так и работает.
Подскажите, пожалуйста, я пробовал перенести на STM32F7xx и столкнулся с ошибкой, что функция UART_BRR_SAMPLING8 объявлена неявно и недействительна на С99. Пробовал искать эту функцию и нашёл только в HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart) нечто похожее - UART_DIV_SAMPLING8, однако, если использовать её, то в отладчике ничего не показывает. Пробовал посмотреть на осциллографе и вижу только какую-то команду на 30мкс. В чём может быть проблема?
На самом деле проще всего - посмотреть в HAL, как для этого семейства они baudrate настраивают, и кусок этот оттуда скопировать )
Подскажите, нафига в начале функции сброса отправка байта 0x43?
Прекрасный вопрос, но идей нет )
Единственное объяснение пока вижу, что я для отладки добавил, а потом забыл убрать... Сейчас еще подумаю на предмет тайного смысла, потом удалю и обновлю проекты/код.
Спасибо за замечание )
Бывает)
В файле onewire.c в строке 51 ругается на UART_OVERSAMPLING_8. Если заменить на UART_OVERSAMPLING_16, то компилятор проглатывает. Пока не стал разбираться, может, Вам будет проще увидеть в чём дело и существенно ли это.
Это для какого контроллера?
STM32F103C8T6, STM32CubeIDE
Да, функцию SetBaudrate() надо адаптировать вручную под использующийся контроллер тогда.
И ещё вопрос. Под 1-wire хочу использовать USART2. Так понимаю, что для этого в onewire.c все USART1 надо заменить на USART2. Правильно ли это?
В onewire.c UART_HandleTypeDef *huart идет аргументом в функциях, поэтому нужный UART просто указывается в момент вызова функции, то есть допустим:
или
В ds18b20.c использующийся модуль в момент инициализации однократно задаем.
Здравствуйте! Как изменить SetBaudrate на
stm32g0xx? Там похожестей с серией f очень мало(
Добрый вечер! Там тоже можно из HAL выдернуть из драйвера для USART.
Вот эта часть за настройку baudrate отвечает:
/*-------------------------- USART BRR Configuration -----------------------*/ UART_GETCLOCKSOURCE(huart, clocksource); /* Check LPUART instance */ if (UART_INSTANCE_LOWPOWER(huart)) { /* Retrieve frequency clock */ switch (clocksource) { case UART_CLOCKSOURCE_PCLK1: pclk = HAL_RCC_GetPCLK1Freq(); break; case UART_CLOCKSOURCE_HSI: pclk = (uint32_t) HSI_VALUE; break; case UART_CLOCKSOURCE_SYSCLK: pclk = HAL_RCC_GetSysClockFreq(); break; case UART_CLOCKSOURCE_LSE: pclk = (uint32_t) LSE_VALUE; break; default: pclk = 0U; ret = HAL_ERROR; break; } /* If proper clock source reported */ if (pclk != 0U) { /* Compute clock after Prescaler */ lpuart_ker_ck_pres = (pclk / UARTPrescTable[huart->Init.ClockPrescaler]); /* Ensure that Frequency clock is in the range [3 * baudrate, 4096 * baudrate] */ if ((lpuart_ker_ck_pres < (3U * huart->Init.BaudRate)) || (lpuart_ker_ck_pres > (4096U * huart->Init.BaudRate))) { ret = HAL_ERROR; } else { /* Check computed UsartDiv value is in allocated range (it is forbidden to write values lower than 0x300 in the LPUART_BRR register) */ usartdiv = (uint32_t)(UART_DIV_LPUART(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler)); if ((usartdiv >= LPUART_BRR_MIN) && (usartdiv <= LPUART_BRR_MAX)) { huart->Instance->BRR = usartdiv; } else { ret = HAL_ERROR; } } /* if ( (lpuart_ker_ck_pres < (3 * huart->Init.BaudRate) ) || (lpuart_ker_ck_pres > (4096 * huart->Init.BaudRate) )) */ } /* if (pclk != 0) */ } /* Check UART Over Sampling to set Baud Rate Register */ else if (huart->Init.OverSampling == UART_OVERSAMPLING_8) { switch (clocksource) { case UART_CLOCKSOURCE_PCLK1: pclk = HAL_RCC_GetPCLK1Freq(); break; case UART_CLOCKSOURCE_HSI: pclk = (uint32_t) HSI_VALUE; break; case UART_CLOCKSOURCE_SYSCLK: pclk = HAL_RCC_GetSysClockFreq(); break; case UART_CLOCKSOURCE_LSE: pclk = (uint32_t) LSE_VALUE; break; default: pclk = 0U; ret = HAL_ERROR; break; } /* USARTDIV must be greater than or equal to 0d16 */ if (pclk != 0U) { usartdiv = (uint32_t)(UART_DIV_SAMPLING8(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler)); if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX)) { brrtemp = (uint16_t)(usartdiv & 0xFFF0U); brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U); huart->Instance->BRR = brrtemp; } else { ret = HAL_ERROR; } } } else { switch (clocksource) { case UART_CLOCKSOURCE_PCLK1: pclk = HAL_RCC_GetPCLK1Freq(); break; case UART_CLOCKSOURCE_HSI: pclk = (uint32_t) HSI_VALUE; break; case UART_CLOCKSOURCE_SYSCLK: pclk = HAL_RCC_GetSysClockFreq(); break; case UART_CLOCKSOURCE_LSE: pclk = (uint32_t) LSE_VALUE; break; default: pclk = 0U; ret = HAL_ERROR; break; } if (pclk != 0U) { /* USARTDIV must be greater than or equal to 0d16 */ usartdiv = (uint32_t)(UART_DIV_SAMPLING16(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler)); if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX)) { huart->Instance->BRR = (uint16_t)usartdiv; } else { ret = HAL_ERROR; } } }Либо можно просто функцию UART_SetConfig() вызвать, поставив новое значение в huart->Init.BaudRate перед этим.
Спасибо! Все заработало)
Отлично )