STM8驱动HC-05蓝牙模块
使用软件:IAR FOR STM8
编程方式:固件库
硬件配套:STM8S105C6T6实验板
1 配置蓝牙
使用 USB-TTL 模块与 HC-05 蓝牙模块连接(左为 USB 转 TTL,右为蓝牙模块):
- 3V3-->VCC
- TXD-->RXD
- RXD-->TXD
- GND-->GND
按下蓝牙模块的黑色小按钮的同时,连上电脑,这时蓝牙模块上的信号灯闪烁模式为 2s 的长闪烁,说明蓝牙进入 AT 模式,可以向它发送 AT 指令了。接着打开串口调试助手,波特率选择 38400,其他设置不用变。然后发送 AT 指令,每条指令发送成功后,调试助手会收到 OK 的信息。
部分 AT 指令如下(均以回车、换行结尾):
AT+NAME=Bluetooth-Mount256 // 蓝牙名称为Bluetooth-Mount256
AT+ROLE=0 // 蓝牙模式为从模式
AT+CMODE=0 // 蓝牙连接模式为任意地址连接模式
AT+PSWD="1234" // 蓝牙配对密码为1234(注:不加双引号会返回一个 ERROR:(1D))
AT+UART=115200,0,0 // 蓝牙通信串口波特率为1152,停止位1位,无校验位(以后正常模式都会采用这个波特率来进行通讯,AT 模式依然是 38400)
AT+RMAAD // 清空配对列表
查询指令为:
AT+VERSION? // 获得软件版本号
AT+NAME? // 获得设备名称
AT+PSWD? // 获得模块密码
AT+UART? // 获得串口参数
附上默认设置:
模块工作角色:从模式
串口参数:38400bits/s 停止位1位无校验位
配对码:1234
设备名称:HC-05
连接模式:任意蓝牙设备连接模式(恢复默认设置 AT指令:AT+ORGL)
拔下连接,再重新连接电脑,此时蓝牙模块上的信号灯闪烁模式为短闪烁,说明蓝牙模块进入正常模式,但未连接设备。要先通过手机蓝牙与搜索到蓝牙模块设备与蓝牙进行配对(在手机设置里),在蓝牙调试 app 里搜索到该设备进行连接即可,此时蓝牙模块的灯会变成间歇性闪烁(闪两下、停一会)。
第一步:
第二步:
备注:我试了这么多 app,目前只有 SPP 蓝牙串口 app 可以(这 app 广告多的一比),其他要么搜索不到要么连接超时。
接下来测试:在手机的调试助手发送字符,电脑的调试助手会收到;在电脑的调试助手发送字符,手机的调试助手会收到。
2 驱动代码
蓝牙驱动代码其实就是 UART 代码,如下所示:
2.1 uart.h
#ifndef __UART_H
#define __UART_H
#include "stm8s.h"
#include "stdio.h"
#ifdef _RAISONANCE_
#define PUTCHAR_PROTOTYPE int putchar (char c)
#define GETCHAR_PROTOTYPE int getchar (void)
#elif defined (_COSMIC_)
#define PUTCHAR_PROTOTYPE char putchar (char c)
#define GETCHAR_PROTOTYPE char getchar (void)
#else /* _IAR_ */
#define PUTCHAR_PROTOTYPE int putchar (int c)
#define GETCHAR_PROTOTYPE int getchar (void)
#endif /* _RAISONANCE_ */
void UART2_Config(void);
void UART2_SendByte(u8 data);
void UART2_SendStr(const unsigned char *p_str);
extern uint8_t buffer;
#endif /* __UART_H */
2.2 uart.c
重写 printf 函数,这样以后使用 printf 就可以输出信息了。
#include "UART.h"
uint8_t buffer;
void UART2_Config(void)
{
CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART2, ENABLE);
UART2_DeInit();
UART2_Init((u32)115200, UART2_WORDLENGTH_8D, UART2_STOPBITS_1, UART2_PARITY_NO , UART2_SYNCMODE_CLOCK_DISABLE , UART2_MODE_TXRX_ENABLE);
UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);
UART2_Cmd(ENABLE);
}
void UART2_SendByte(u8 data)
{
UART2_SendData8((unsigned char)data);
while (UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
}
void UART2_SendStr(const unsigned char *p_str)
{
while(*p_str != '\0')
{
UART2_SendByte(*p_str);
p_str++;
}
}
/**********************************printf*********************************************/
/**
* @brief Retargets the C library printf function to the UART.
* @param c Character to send
* @retval char Character sent
*/
PUTCHAR_PROTOTYPE
{
/* Write a character to the UART2 */
UART2_SendData8(c);
/* Loop until the end of transmission */
while (UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
return (c);
}
/**
* @brief Retargets the C library scanf function to the USART.
* @param None
* @retval char Character to Read
*/
GETCHAR_PROTOTYPE
{
#ifdef _COSMIC_
char c = 0;
#else
int c = 0;
#endif
/* Loop until the Read data register flag is SET */
while (UART2_GetFlagStatus(UART2_FLAG_RXNE) == RESET);
c = UART2_ReceiveData8();
return (c);
}
2.3 stm8s_it.c
这里实现的是接收中断的功能。
#include "stm8s_it.h"
#include "uart.h"
/**
* @brief UART2 RX interrupt routine.
* @param None
* @retval
* None
*/
INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
UART2_ClearITPendingBit(UART2_IT_RXNE);
buffer = UART2_ReceiveData8();
}
#endif /* STM8S105*/
3 简单应用:通过蓝牙控制 LED
一个很简单的测试程序:在手机上输入指令,告诉单片机需要让哪个 LED 工作,并在手机上显示哪个 LED 正在工作的信息。如果指令错误,则显示错误信息。放出主函数代码:
#include "stm8s.h"
#include "uart.h"
#include "led.h"
#include "timer.h"
void SystemInit_CLK(void);
void main(void)
{
SystemInit_CLK();
TIM_Init();
LED_Init();
UART2_Config();
buffer = 0x00;
__enable_interrupt();
/* Infinite loop */
while (1)
{
switch (buffer)
{
case '0':
LED0_REVERSE;
LED1_OFF; LED2_OFF; LED3_OFF;
printf("LED0 WORKING!");
break;
case '1':
LED1_REVERSE;
LED0_OFF; LED2_OFF; LED3_OFF;
printf("LED1 WORKING!");
break;
case '2':
LED2_REVERSE;
LED0_OFF; LED1_OFF; LED3_OFF;
printf("LED2 WORKING!");
break;
case '3':
LED3_REVERSE;
LED0_OFF; LED1_OFF; LED2_OFF;
printf("LED3 WORKING!");
break;
default:
LED0_OFF; LED1_OFF; LED2_OFF; LED3_OFF;
printf("Wrong!");
break;
}
TIMDelay_Nms(500);
}
}
void SystemInit_CLK(void)
{
CLK_DeInit();
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); // 16MHz
CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
CLK_HSICmd(ENABLE);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval : None
*/
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
蓝牙调试助手显示如下:
PS:不知道为什么,在单片机上发送字符串,手机上接收到的字符串是支离破碎的。