STM Урок 97. Подключаем bluetooth-модуль HC-05
Настало время немного отдохнуть от передачи данных по интерфейсу LAN.
Сегодня мы попробуем передать данные с микроконтроллера куда-нибудь, а также обратно, используя уже беспроводные технологии, то есть такие технологии, благодаря которым передача данных происходит без использования каких-либо проводов.
В качестве технологии беспроводной передачи данных мы будем использовать Bluetooth. А в качестве устройства для этого мы возьмём модуль HC-05, обзор и тестирование которого находится вот здесь. Обязательно просмотрите данный обзор и проделайте все тесты, описанные в нём, также установите программу на смартфон, которая была представлена в этом обзоре, а потом уже приступайте к изучению подключения модуля к контроллеру. То есть проект сегодняшнего занятия будет нормально работать на настроенном модуле.
Мы подключим данный модуль к контроллеру STM32F103C8T6, расположенному на недорогой отладочной плате, которая нам уже отлично знакома благодаря многочистенным урокам, которые мы просмотрели и прочитали.
Сначала давайте создадим и настроим проект.
Создадим новый проект в Cube MX, выбрав контроллер STM32F103C8Tx.
Настроим тактирование от кварцевого резонатора
Настроим USART. Использовать для модуля мы будем USART2, так как первый в дальнейшем нам, возможно пригодится для подключения переходника USB-TTL для связи с ПК
Включим ножку порта PC13, отвечающую за светодиод, на выход
Также на выход включим ножку PA5, посредством которой мы будем включать модулю поддержку AT-команд, правла пока не в данном уроке
Настроим частоты в System Configuration (нажмите на картинку для увеличения изображения)
Теперь перейдём в раздел Configuration, USART трогать не будем, оставим настройки по умолчанию (скорость 115200 кбпс), а вот ножкe порта PA5 настроим чуть побыстрее
Тем не менее в настройки USART нам зайти придётся для, того, чтобы включить прерывания, мы же и на вход будем его использовать
Настроим таймер на период приблизительно 2 секунды
Также включим в таймере прерывания
Настроим проект, увеличив размер стека и кучи в двое (на будущее) и выбрав в качестве среды разработки Keil, а также назовём наш проект соответствующим теме занятия именем
Применим настройки, соберём проект, откроем его в Keil, настроим программантор на авторезет, а также уровень оптимизации убавим до уровня 1.
Давайте посмотрим схему подключения модуля к контроллеру (нажмите на картинку для увеличения изображения)
Вернёмся к проекту и добавим в main.c библиотеку для работы со строками
Добавим также глобальный строковый массив
char str1[60]=;
В main() инициируем приём данных в USART, а также запустим наш таймер
HAL_TIM_Base_Start_IT(&htim2);
Добавим глобальную структуру для свойств USART, а также переменную её типа
typedef struct USART_prop
uint8_t usart_buf [60];
uint8_t usart_cnt ;
uint8_t is_tcp_connect ; //статус попытки создать соединение TCP с сервером
uint8_t is_text ; //статус попытки передать текст серверу
> USART_prop_ptr ;
USART_prop_ptr usartprop;
Тажке добавим глобальную переменную для счётчика выводимых в модуль строк, а также массив этих самых строк
Добавим также функцию разбора строки. Пока она будет почти пустая. Наполняться она будет в более поздних занятиях, а пока же в ней будет лишь изменение состояния свечения светодиода, а также возврат эхом строки источнику, его пославшему, то есть в нашем случае смартфону посредством передачи в USART
void string_parse( char * buf_str)
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
Теперь добавим обработчик приёма символа из USART
void UART2_RxCpltCallback( void )
//если вдруг случайно превысим длину буфера
if (usartprop. usart_cnt >59)
usartprop. usart_cnt =0;
usartprop. usart_buf [usartprop. usart_cnt ] = b;
usartprop. usart_buf [usartprop. usart_cnt +1]=0;
string_parse(( char *)usartprop. usart_buf );
usartprop. usart_cnt =0;
usartprop. usart_cnt ++;
Данный обработчик принимает символ из порта USART, заносит его в буфер по адресу, находящемуся в счётчике, проверяет на символ перевода строки, если таковой имеет место, то приём прекращается, набранная в буфере строка передаётся в функцию разбора строки и счётчик обнуляется, если другой символ, то счётчик наращивается. Также на ряду с этим в функцию был включен код проверки на превышение строкой размера буфера.
Добавим теперь официальный обработчик приёма из USART, в котором и вызовем наш «самодельный» обработчик
void HAL_UART_RxCpltCallback( UART_HandleTypeDef *huart)
if (huart==&huart2)
UART2_RxCpltCallback();
Соберём код, прошьём контроллер и проверим работу кода в терминальной программе на смартфоне.
Чтобы не мучиться и постоянно не вводить строки, в программе предусмотрены пять кнопок, в обработчики нажатий которых можно добавить любые строки. Вот эти кнопки
Давайте, например, пятой кнопке назначим строку, которую она будет по нажатию отправлять в bluetooth. Зайти в настройки мы можем по нажатию на кнопку
Мы можем здесь настроить несколько параметров. Изменить имя кнопки (имя отображаемое на самой кнопке, также тип данных, саму отправляемую строку, а также заканчивать ли строку кодами возврата каретки и перевода строки. Настроим всё как на скриншоте и сохраним настройки. Теперь по нажатию на нашу кнопку строка, текст которой мы добавили в поле Command, будет отправляться в порт. Конечно, будет логичный вопрос: «а как же зайти обратно в настройки и перенастроить свойства кнопки?». Ответ: «посредством длинного нажатия на кнопку (длинного тапа)»
Нажмём на кнопку и строка наша из кнопки попадёт в чат отправки, а также попадёт и в чат приёма. А в чат приёма она попадёт благодаря эху в функции разбора строки. Тем самым мы проверили, что строка отправляется в микроконтроллер и отправляется обратно из микроконтроллера в смартфон посредством подключенного модуля HC-05
Теперь давайте добавим также обработчик события от таймера, благодаря которому строки из массива будут отправляться в смартфон
void HAL_TIM_PeriodElapsedCallback( TIM_HandleTypeDef *htim)
if (htim==&htim2)
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
Соберём в очередной раз код и прошьём контроллер. После этого строки приблизительно раз в 2 секунды из нашего контроллера по интерфейсу bluetooth будут приходить в окно терминальной программе на смартфоне
Отлично! Строки приходят, причём за период в 2 секунды контроллер может выполнять любые операции благодаря использованию прерывания от таймера. проверим это, нажимая на нашу кнопку со строкой в терминальной программе смартфона. Если всё нормально, то строки, посланные по кнопке, должны эхаться практически мгновенно, не дожидаясь вывода следующей строки из МК
Так и есть, мы можем сколько угодно отправлять данные и они не уходят ни в какую очередь, прочесс рабоает мгновенно.
Таким образом, мы за столь короткий урок научились подключать модуль bluetooth HC-05 к микроконтроллеру, принимать и отправлять данные из контроллера и в контроллер другим устойствам с поддержкой bluetooth, в частности, смартфону.
Модуль bluetooth HC-05 можно купить здесь bluetooth HC-05
Отладочную плату можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Смотреть ВИДЕОУРОК (нажмите на картинку)
STM32 HC-05 Bluetooth Module
This project assumes you have already installed STM32CubeIDE. You need to have previously done a basic blink sketch with blue-pill using STM32CubeIDE. I have made a complete video from installing STM32CubeIDE to LED blink program. You can watch it by clicking this link. https://www.youtube.com/watch?v=kXg467nVd_A
Wiring Diagram
STM32CubeIDE Settings
Enable USART1 asynchronous
Parameter Settings —> Basic Parameters —> Baud rate 9600
NVIC Settings —> USART1 global interrupt —> (Tick)
Additional code on top of STM32CubeIDE generated code
/* USER CODE BEGIN PV */ uint8_t rxData; /* USER CODE END PV */ /* USER CODE BEGIN 2 */ HAL_UART_Receive_IT(&huart1,&rxData,1); // Enabling interrupt receive /* USER CODE END 2 */ /* USER CODE BEGIN 4 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) if(huart->Instance==USART1) if(rxData==78) // Ascii value of 'N' is 78 (N for NO) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 0); > else if (rxData==89) // Ascii value of 'Y' is 89 (Y for YES) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 1); > HAL_UART_Receive_IT(&huart1,&rxData,1); // Enabling interrupt receive again > > /* USER CODE END 4 */