MSP432P401R实现HC05蓝牙模块主从机通信
对HC05蓝牙模块有什么不懂的可以看我这篇博客:HC05蓝牙模块(STM32)
一、进入AT模式更改参数
(一)连接电脑
USB转TTL和蓝牙模块连接好后,插上电脑。(这里仅用4根杜邦线连接即可)
进入AT模式的两种方法。
-
方法一:先按住按键不放,再给模块上电。此时LED 2S闪一次,进入AT模式。波特率固定为38400。
-
方法二:模块直接上电。此时LED灯快闪(1s两次)。再按下按键,模块也会进入AT指令,此时LED还是快闪。这个时候的波特率和自己设置的一样,默认为9600。1位停止位,无奇偶校验。
(二)进入AT模式更改参数
在使用HC05蓝牙模块进行主从机通信前需要更改以下参数
- 蓝牙角色
先使用AT命令查看蓝牙角色
AT+ROLE?
再将两个蓝牙分别改为一主一从
AT+ROLE=<Param>
Param:参数取值如下:
0——从角色(Slave)
1——主角色(Master)
2——回环角色(Slave-Loop)
默认值:0(从机)
更改将两个蓝牙角色分别改为一主一从,否则无法实现主从机通信
- 蓝牙密码
在实现主从机通信中,蓝牙的密码必须一致
操作和更改蓝牙角色一样
蓝牙密码默认为1234,建议改为其他密码,防止比赛时误连
查询密码
AT+PSWD?
设置密码
AT+PSWD=<Param>
对于其他参数,可改可不改,不改也没有影响
二、代码解析
(一)串口
在MSP432中蓝牙通信时我使用了串口A1
串口初始化
不懂MSP432P401R串口通信的可以看我的这篇博客:MSP432 串口通信
void uart1_init(uint32_t baudRate)
{
#ifdef EUSCI_A_UART_7_BIT_LEN
//固件库v3_40_01_02
//默认SMCLK 48MHz 比特率
const eUSCI_UART_ConfigV1 uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
312, // BRDIV = 312
8, // UCxBRF = 8
1, // UCxBRS = 1
EUSCI_A_UART_NO_PARITY, // No Parity
EUSCI_A_UART_LSB_FIRST, // MSB First
EUSCI_A_UART_ONE_STOP_BIT, // One stop bit
EUSCI_A_UART_MODE, // UART mode
EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
EUSCI_A_UART_8_BIT_LEN // 8 bit data length
};
eusci_calcBaudDividers((eUSCI_UART_ConfigV1 *)&uartConfig, baudRate); //配置波特率
#else
//固件库v3_21_00_05
//默认SMCLK 48MHz 比特率
const eUSCI_UART_Config uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
312, // BRDIV = 312
8, // UCxBRF = 8
1, // UCxBRS = 1
EUSCI_A_UART_NO_PARITY, // No Parity
EUSCI_A_UART_LSB_FIRST, // MSB First
EUSCI_A_UART_ONE_STOP_BIT, // One stop bit
EUSCI_A_UART_MODE, // UART mode
EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
};
eusci_calcBaudDividers((eUSCI_UART_Config *)&uartConfig, baudRate); //配置波特率
#endif
// 1.配置GPIO复用
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
MAP_UART_initModule(EUSCI_A1_BASE, &uartConfig); // 3.初始化串口
MAP_UART_enableModule(EUSCI_A1_BASE); // 4.开启串口模块
MAP_UART_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); // 5.开启串口相关中断
MAP_Interrupt_enableInterrupt(INT_EUSCIA1); // 6.开启串口端口中断
}
串口中断服务函数
// Uart1接收中断
void EUSCIA1_IRQHandler(void)
{
uint32_t status = MAP_UART_getEnabledInterruptStatus(BLUETOOTH_UART);
if (status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) //接收中断
{
MAP_UART_clearInterruptFlag(BLUETOOTH_UART, EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG); // 清除中断标志位
Bluetooth_Uart_Rx_Temp = MAP_UART_receiveData(BLUETOOTH_UART); // 临时接收
if (Bluetooth_Uart_Rx_Index < BLUETOOTH_UART_RX_LENGTH_MAX) // 接收缓冲是否溢出
{
SW_Timer_Tick = HAL_GetTick() + 20; // 软件定时复位20ms
Bluetooth_Uart_Rx_Buffer[Bluetooth_Uart_Rx_Index] = Bluetooth_Uart_Rx_Temp; // 放入缓存
Bluetooth_Uart_Rx_Index++; // 索引加1
}
else // 强制标记接收完成
{
SW_Timer_Tick = HAL_GetTick() - 1;
}
}
}
编写串口printf函数
注意:这里要引入#include "stdarg.h"
的头文件,因为va_list等的定义在该头文件中
//串口1,printf 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void printf_uart1(char *fmt, ...)
{
uint16_t i, j;
va_list ap;
va_start(ap, fmt);
vsprintf((char *)UART1_TX_BUF, fmt, ap);
va_end(ap);
i = strlen((const char *)UART1_TX_BUF); //此次发送数据的长度
for (j = 0; j < i; j++) //循环发送数据
{
MAP_UART_transmitData(EUSCI_A1_BASE, UART1_TX_BUF[j]);
}
}
(二)定时器32
不懂MSP432P401R串口通信的可以看我的这篇博客:MSP432 定时器32
这里的定时器32是用来定时20ms用来控制串口的接收数据
定时器32初始化
void Tim32_1_Int_Init(uint32_t aar, uint8_t psc)
{
MAP_Timer32_initModule(TIMER32_1_BASE, psc, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
MAP_Timer32_setCount(TIMER32_1_BASE, aar);
MAP_Timer32_enableInterrupt(TIMER32_1_BASE);
MAP_Timer32_startTimer(TIMER32_1_BASE, false); //连续计数模式 false
MAP_Interrupt_enableInterrupt(INT_T32_INT2);
}
定时器32服务函数
/* Timer32 ISR */
static vu32 uwTick = 0;
void T32_INT2_IRQHandler(void)
{
MAP_Timer32_clearInterruptFlag(TIMER32_1_BASE);
/*开始填充用户代码*/
uwTick++; // 1ms加1
/*结束填充用户代码*/
}
// 对外开发函数
u32 HAL_GetTick(void)
{
return uwTick;
}
(三)主函数
主机给从机发送消息使用printf_uart1("{1}");即可
注意:发送的数据必须是以“{”开头,以“}”结尾,否则从机接收数据就会报错
int main(void)
{
SysInit(); // 第3讲 时钟配置
uart0_init(115200); // 第7讲 串口配置
uart1_init(9600); // 第7讲 串口配置(蓝牙)
delay_init();
// 不分频,ARR为48000,周期为48000000 / 48000 = 1ms 作为时基
Tim32_1_Int_Init(48000, TIMER32_PRESCALER_1);
printf("[Log] Init Completed! \r\n");
printf("[Log] Uart1 接收数据的格式为 \"{\" + u8 + \"}\" \r\n");
MAP_Interrupt_enableMaster(); // 开启总中断
while (1)
{
// printf_uart1("{1}");
// delay_ms(1000);
Bluetooth_Check_Data_Task();
if (Bluetooth_Rx_Data_Analysis_State)
{
// 打印一下接收数据
printf("[Bluetooth Data] x1: %c\r\n", Bluetooth_Rx_Data[0]); //, Bluetooth_Rx_Data[1]);
printf("%c\r\n", Bluetooth_Rx_Data[0]); //, Bluetooth_Rx_Data[1]);
// 清除解析完成状态 清除缓存
Bluetooth_Rx_Data_Analysis_State = 0;
memset(Bluetooth_Rx_Data, 0, sizeof(Bluetooth_Rx_Data));
}
}
}
三、实验现象
文章在这里就结束了,最后我会附上完整工程,如有不懂的地方,欢迎评论区留言,我都会一 一解答