一、HC08重要参数
- 蓝牙4.0,BLE,主从一体;
- 模块上电后,启动需要150ms;
- 默认波特率:9600;
- 模块未连接时,为AT指令模式,连接后为串口透传模式;
- 空中速率:1Mbps;? (与HC05, HC06等不同, 不能直接与之通信);
- 通信距离:80米; (空旷);
- 工作电流:主机未连21mA,已连9mA; 从机未连8.5mA, 已连9mA; 睡眠0.4uA;?
- 主从关系:两模块必须一主一从,才能连接;
二、AT命令解释
- 指令结尾,无需添加换行符;
- 指令修改,立即生效,掉电不丢失;
- 指令修改,成功时,统一返回OK,查看信息类指令除外;
- 指令修改,不成功,不返回任何信息;
三、STM32代码操作
1.操作重点
- ?开发板用杜邦线连接HC-08,4线:VCC, GND, TX, RX;
- 使用UART与HC08通信, 波特率使用HC08默认的9600;
- 发送AT指令,无需换行符结尾;
- 只要一条AT指令,设置HC08为主、从机模式,就能自动连接;
- 模块名称不重要,也不用密码;
- ?连接前:AT模式,蓝灯闪烁;连接后:数据透传模式,不再接受AT命令,蓝灯常亮;
- 主机和从机的代码一样的,只是一个设置为主机,一个设置为从机;
2.头文件配置
/*****************************************************************************
** 移植配置
****************************************************************************/
#define HC08_UARTx USART3
#define HC08_ROLE 0 // 主从模式,0=slave, 1=master;与手机APP互连必须配置为从机模式
/*****************************************************************************
** 全局变量
****************************************************************************/
typedef struct
{
uint8_t flag_UARTConnect; // 标记:与开发板间的通信是否正常; 0=失败, 1=成功
uint8_t flag_TargetConnect; // 标记:与目标设备通信是否正常;0=失败, 1=成功
}xHC08_TypeDef;
extern xHC08_TypeDef xHC08; // 声明为全局变量,方便记录信息、状态
/*****************************************************************************
** 声明全局函数
****************************************************************************/
void HC08_Init(void); // 初始化串口及中断优先、AT参数配置级;
void HC08_SendData(uint8_t* data, uint16_t cnt); // 发送指定长度的数据;
void HC08_SendString(char* strTemp); // 发送字符串;
3.GPIO初始化代码
GPIO_InitTypeDef GPIO_InitStructure;
// 时钟使能
RCC->APB1ENR |= RCC_APB1ENR_USART3EN; // 使能USART1时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // 使能GPIOA时钟
// GPIO_TX引脚配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // TX引脚,配置为复用推挽工作模式
GPIO_Init (GPIOB, &GPIO_InitStructure);
// GPIO_RX引脚配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ; // RX引脚,配置为浮空输入工作模式
GPIO_Init (GPIOB, &GPIO_InitStructure);
4.UART初始化代码
NVIC_InitTypeDef NVIC_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 中断配置
NVIC_InitStructure .NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure .NVIC_IRQChannelPreemptionPriority=2 ; // 抢占优先级
NVIC_InitStructure .NVIC_IRQChannelSubPriority = 2; // 子优先级
NVIC_InitStructure .NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
//USART 初始化设置
USART_DeInit(USART3);
USART_InitStructure.USART_BaudRate = baudrate; // 串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 使能收、发模式
USART_Init(USART3, &USART_InitStructure); // 初始化串口
USART_ITConfig(USART3, USART_IT_TXE , DISABLE );
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 使能接受中断
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); // 使能空闲中断
USART_Cmd(USART3, ENABLE); // 使能串口, 开始工作
5.HC08发送数据代码
// 发送AT指令,或字符串
void HC08_SendString(char* strTemp)
{
HC08_SendData((uint8_t *)strTemp, strlen(strTemp));
}
// 发送指定长度的数据
void HC08_SendData(uint8_t* dataBuf, uint16_t cnt)
{
while(cnt--)
{
while((HC08_UARTx->SR & 0X40)==0); // 等待上一次串口数据发送完成
HC08_UARTx->DR = *dataBuf; // 写DR,串口将的发送数据
dataBuf++;
}
}
6.HC08接收数据代码
void USART3_IRQHandler(void)
{
static uint8_t cnt=0;
static uint8_t RxTemp[256];
// 接收中断
if(USART3->SR & (1<<5))
{
RxTemp[cnt++] = USART3->DR ; // 读取数据寄存器值;注意:读取DR时自动清零中断位;
}
// 空闲中断, 用于配合接收中断,可判断一帧数据接收完成
if(USART3->SR & (1<<4)) // 检查IDLE中断标志
{
memcpy(xUSART.USART3RecivedBuffer , RxTemp , 256); // 临时数据转存为全局数据, 等待处理,注意:复制的是整个数组,包括0值,以方便字符串数据
xUSART.USART3RecivedFlag = 1; // 标记;外部程序通过检查xUSARTFlag.USART_2_Recived是否等于1, 可判断是否有新一帧数据
xUSART.USART3RecivedCNT = cnt;
cnt=0;
memset(RxTemp ,0, 256); // 临时数据空零,准备下一次的接收
USART3 ->SR; USART3 ->DR; // 清零IDLE中断标志位!! 序列清零,顺序不能错!!
/********************************************************************************
方式1:可在这里调用外部函数,处理接收到数据(不推荐)
方式2:可在外部判断USARTxRecivedFla==1,然后处理数据区xUSART.USARTxRecivedBuffer
禁 止:不可在中断里调用printf等不可重入函数!!!
示 例: 下面这一行代码, 只作示例, 输出到上位机以观察所收到的最新一帧数据, 可删除
*********************************************************************************/
USART1_printf((char*)xUSART.USART3RecivedBuffer); // 这行代码只作示例,输出USART3收到的最新一帧数据,可删除
}
}
7.数据处理
// 本函数为main函数中的while函数
while(1) // while函数死循环,不能让main函数运行结束,否则会产生硬件错误
{
// Scheduler_Run(); // 任务轮询器; 如要使用, 清除while中其它函数(移到Scheduler文件中去), 以保证计时的准确
System_DelayMS(100); // 上面已初始化SysTick, 可直接使用delay_ms()、delay_us()
LED_RED_TOGGLE; // 红色LED 每0.5秒闪灭一次,以监察系统正常工作
if(xUSART.USART1RecivedFlag==1) // 判断上位机(USART1)是否收到新的数据
{
HC08_SendString((char *)xUSART.USART1RecivedBuffer); // 如果收到新数据,就从蓝牙发送出去
xUSART.USART1RecivedFlag=0; // 处理完了,标记清0,不然下一个while循环又会重复操作
}
// 处理HC08收到的数据
if(xUSART.USART3RecivedFlag==1) // 判断蓝牙HC08(USART3)是否收到新的数据
{
if(xUSART.USART3RecivedBuffer[0]=='0') { LED_BLUE_OFF;} // 判断收到的数据
if(xUSART.USART3RecivedBuffer[0]=='1') { LED_BLUE_ON;}
if(xUSART.USART3RecivedBuffer[0]=='3') { LED_BLUE_TOGGLE;}
xUSART.USART3RecivedFlag=0; // 处理完了,标记清0,不然下一个while循环又会重复操作
}
}
四、源代码下载
需要代码的兄弟,可通过以下方式下载代码:
1:CSDN资源:https://download.csdn.net/download/zhouml_msn/20664466
2:Q群文件夹:887199504
互相学习,欢迎指正!~
|