
In the previous guid (here), we took a look at HM-10 module and how to connect it to STM32F4. In this guide, we shall use this module in full duplex to control LED and send strings from STM32F4 to a phone.
In this guide, we shall cover the following:
- Library development.
- Code.
- Results.
7. Library development:
We start off by creating new source and header file with name of hm_10.c and hm_10.h respectively.
Within the header file, include header guard:
#ifndef HM_10_H_ #define HM_10_H_ #endif /* HM_10_H_ */
Declare the following enums which handle the baudrate:

typedef enum
{
Buad9600=0,
Buad19200=1,
Baud38400=2,
Baud57666=3,
Baud115200=4
}HM10_BuadRate_Typedef;Another enum to handle role as master or slave:

In my case (0 means slave and 1 means master):
typedef enum
{
Slave=0,
Master=1
}HM10_Role_Typedef;
Also, set of functions that needed:
void setBuadRate(HM10_BuadRate_Typedef baud); void setRole(HM10_Role_Typedef role); void setName(char *c); void FactoryReset(); void moduleReset();
Hence, the header file as following:
#ifndef HM_10_H_
#define HM_10_H_
#include "stdint.h"
typedef enum
{
Buad9600=0,
Buad19200=1,
Baud38400=2,
Baud57666=3,
Baud115200=4
}HM10_BuadRate_Typedef;
typedef enum
{
Slave=0,
Master=1
}HM10_Role_Typedef;
void setBuadRate(HM10_BuadRate_Typedef baud);
void setRole(HM10_Role_Typedef role);
void setName(char *c);
void FactoryReset();
void moduleReset();
#endif /* HM_10_H_ */
Now, in the source code, include the following header files:
#include "hm_10.h" #include "hm_10_uart.h" #include "stdio.h" #include "led.h"
Declare a character array to handle the AT command:
static char AT_Array[20];
Volatile variable to store the incoming data from UART:
volatile char uart1_rec;
Set buadrate function will take the enum of buadrate as argument:
void setBuadRate(HM10_BuadRate_Typedef baud)
{
sprintf(AT_Array,"AT+BAUD%d\r\n",baud);
hm10_write_at_command(AT_Array);
}By sending for example (AT_BAUD0), it will set the buadrate to 9600.
To set the role function, it will take role enum as argument:
void setRole(HM10_Role_Typedef role)
{
sprintf(AT_Array,"AT+ROLE%d\r\n",role);
hm10_write_at_command(AT_Array);
}
Set name function will set the name of the module and takes string as argument:
void setName(char *c)
{
sprintf(AT_Array,"AT+NAME%s\r\n",c);
hm10_write_at_command(AT_Array);
}To factory reset the module (default state):

void FactoryReset()
{
sprintf(AT_Array,"AT+RENEW\r\n");
hm10_write_at_command(AT_Array);
}To restart the module (exit AT mode):

void moduleReset()
{
sprintf(AT_Array,"AT+RESET\r\n");
hm10_write_at_command(AT_Array);
}
Since the UART is used in interrupt mode to receive the character, we shall declare a callback function as weak:
Declaring a function as weak it, you can override it in another source file without any issue:
__WEAK void HC_12_Callback(unsigned char ch)
{
if (ch == '1')
{
led_toggle();
}
}
void USART1_IRQHandler (void)
{
if(USART1->SR & USART_SR_RXNE){
uart1_rec=USART1->DR;
HC_12_Callback(uart1_rec);
USART1->SR &= ~USART_SR_RXNE;}
}
In the main.c file:
#include "hm_10_uart.h"
#include "led.h"
#include "time_base.h"
#include "exti.h"
#include "hm_10.h"
uint32_t previousTicks;
int main()
{
Ticks_Init(16000000);
PC13_EXTI_Init();
led_init();
hm10_uart_init(9600,16000000);
FactoryReset();
delay(100);
moduleReset();
delay(100);
while(1)
{
if(get_Ticks()-previousTicks>=1000)
{
hm10_write_string("Hello from STM32F411RE Nucleo-64\r\n");
previousTicks=get_Ticks();
}
}
}
8. Code:
You may download the code from here:
9. Results:
Happy coding 🙂
Add Comment