实验任务:开机检测 HC05 蓝牙模块是否存在,如果检测不成功,则报错。检测成功之后,显示模块的主从状态,并显示模块是否处于连接状态, DS0 闪烁,提示程序运行正常。按 KEY0 按键,可以开启/关闭自动发送数据(通过蓝牙模块发送);按 KEY1 按键可以切换模块的主从状态。蓝牙模块接收到的数据,将直接显示在 LCD 上(仅支持 ASCII 字符显示)。
HC05模块
图中是正点原子的hc05的引脚连接,普通某宝上掏的hc05 key---en led----state相连接(相关资料自己找)
main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
//#include "usmart.h"
#include "usart3.h"
#include "hc05.h"
#include "string.h"
//主从
void HC05_Role_Show(void)
{
if(HC05_Get_Role()==1)LCD_ShowString(30,140,200,16,16,"ROLE:Master");
else LCD_ShowString(30,140,200,16,16,"ROLE:Slave ");
}
//连接
void HC05_Sta_Show(void)
{
if(HC05_LED)LCD_ShowString(120,140,120,16,16,"STA:Connected "); //连接成功
else LCD_ShowString(120,140,120,16,16,"STA:Disconnect"); //未连接
}
int main(void)
{
u8 t;
u8 key;
u8 sendmask=0;
u8 sendcnt=0;
u8 sendbuf[20];
u8 reclen=0;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
LED_Init();
KEY_Init();
LCD_Init();
POINT_COLOR=RED;
LCD_ShowString(30,30,200,16,16,"ALIENTEK STM32F1 ^_^");
LCD_ShowString(30,50,200,16,16,"HC05 BLUETOOTH COM TEST");
LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
delay_ms(1000);
while(HC05_Init())
{
LCD_ShowString(30,90,200,16,16,"ATK-HC05 Error!");
delay_ms(500);
LCD_ShowString(30,90,200,16,16,"Please Check!!!");
delay_ms(100);
}
LCD_ShowString(30,90,210,16,16,"KEY1:ROLE KEY0:SEND/STOP");
LCD_ShowString(30,160,200,16,16,"Send:");
LCD_ShowString(30,180,200,16,16,"Receive:");
POINT_COLOR=BLUE;
HC05_Role_Show();
delay_ms(100);
USART3_RX_STA=0;
while(1)
{
key=KEY_Scan(0);
if(key==KEY1_PRES)//按下key1
{
key=HC05_Get_Role();
if(key!=0xff)
{
key=!key; //状态取反
if(key==0)HC05_Set_Cmd("AT+ROLE=0");
else HC05_Set_Cmd("AT+ROLE=1");
HC05_Role_Show();
HC05_Set_Cmd("AT+RESET"); //复位ATK-HC05模块
delay_ms(200);
}
}
else if(key==KEY0_PRES) //按下key0
{
sendmask=!sendmask; //发送/停止发送
if(sendmask==0)LCD_Fill(30+40,160,240,160+16,WHITE);
}else delay_ms(10);
if(t==50)
{
if(sendmask)
{
sprintf((char*)sendbuf,"ALIENTEK HC05 %d\r\n",sendcnt);
LCD_ShowString(30+40,160,200,16,16,sendbuf);
u3_printf("ALIENTEK HC05 %d\r\n",sendcnt);
sendcnt++;
if(sendcnt<99)sendcnt=0;
}
HC05_Sta_Show();
t=0;
LED0=!LED0;
}
//接收数据
if(USART3_RX_STA&0x8000)
{
LCD_Fill(30,200,240,320,WHITE);
reclen=USART3_RX_STA&0x7fff;
USART3_RX_BUF[reclen]=0; //加入结束符
if(reclen==9||reclen==8) //控制DS1检测
{
//这两句控制led1关和亮
if(strcmp((const char*)USART3_RX_BUF,"+LED1 ON")==0)LED1=0; //打开LED1
if(strcmp((const char*)USART3_RX_BUF,"+LED1 OFF")==0)LED1=1;//关闭LED1
}
LCD_ShowString(30,200,209,119,16,USART3_RX_BUF);//显示接收到的数据
USART3_RX_STA=0;
}
t++;
}
}
main中while循环判断key0和key1,实现相关功能,
sprintf((char*)sendbuf,"ALIENTEK HC05 %d\r\n",sendcnt);这句话中sprint的语法和printf很像,printf是讲结果送到屏幕,sprintf是将结果送到字符串。与printf相比,sprintf多了一个需要传送到的字符串的变量的名称。
举一个例子如下:
#include<stdio.h>
main() {
char strA[20];
printf("This is a string.\n");
sprintf(strA,"This is a string.\n");
printf("%s",strA);
}
程序最后加入如检测ds1的代码,手机助手连接蓝牙后进行手机输入,单片机进行反馈。
hc05.h的代码简单说一下查询当前主从状态的代码HC05_Get_Role
//查角色
u8 HC05_Get_Role(void)
{
u8 retry=0x0a;
u8 temp,t;
while(retry--)
{
HC05_KEY=1;
delay_ms(5);
u3_printf("AT+ROLE?\r\n");
for(t=0;t<15;t++)//次循环用于等待hc05相应
{
delay_ms(10);
if(USART3_RX_STA&0X8000)break;
}
HC05_KEY=0;
if(USART3_RX_STA&0x8000)
{
temp=USART3_RX_STA&0x7fff;
USART3_RX_STA=0;
if(temp==13&&USART3_RX_BUF[0]=='+')//接收到正确的应答了
{
temp=USART3_RX_BUF[6]-'0';
break;
}
}
}
if(retry==0)temp=0xff;
return temp;
}
拉高拉低key进入退出at模式if判断串口三的数据将数据的存在buf里面,将数据的大小放在STA里面,正长回应是
+ ROLE:<Param>/r/n |
OK/r/n |
加上回车换行是13个,temp判断是否是13长度,并判断第一个是啥字符
我们得到的是ASCII,必须减掉‘0’的ASCII值才能得到数字。
hc05初始化中 GPIO_SetBits()函数
- 实现功能:控制某个GPIO引脚的输出电平(拉高 / 拉低)
- GPIO_SetBits 拉高引脚输出电平
- GPIO_ResetBits 拉低引脚输出电平