使用的是HC-06模块
HC-06默认的波特率是9600,8位数据为,1位停止位,无校验位
在使用串口助手调试的时候,需要勾选自动换行,这里选用的友善串口助手
修改蓝牙的AT指令可以查看蓝牙芯片手册,AT指令
如果是上电长亮说明是直接进入了一个AT模式和配对模式,可以使用手机搜索到蓝牙模块,配对上,但是手机里面的蓝牙系统是连接不上HC-06的,需要额外下载一个蓝牙串口,在蓝牙串口连接上模块之后,模块的指示灯常亮,这时可以进行通信
2020.3.11
在经过12号一天对LCD12864液晶显示屏的后,继续HC-06蓝牙模块的使用
- 目的:手机连接蓝牙模块控制LED的亮灭
蓝牙模块和单片机之间的通信是UART串口方式,使用的是圣芯的HC89S003F4单片机,连接好蓝牙模块和单片机,手机发送信息给蓝牙模块,蓝牙模块将接收到的信息通过UART转发给单片机
只需要在单片机里面处理接受到的信号就可以了,所以说非常的简单
接下来是代码
main.c
#define ALLOCATE_EXTERN
#include "lcd12864.H"
#include "public.h"
#include "time.h"
#include "bt.h"
void main(void)
{
WDTCCR = 0x00;
CLKSWR = 0x51; //选择内部高频RC为系统时钟,内部高频RC 2分频,Fosc=16MHz
CLKDIV = 0x01; //Fosc 1分频得到Fcpu,Fcpu=16MHz
Lcd12864_Init();
Timer_Init();
Bt_Init();
Lcd_Init();
LCD_Clear();
EA = 1; //使能总中断
while (1)
{
Rx_Proc();
}
}
bt.c
#include "time.H"
#include "lcd12864.H"
xdata uint8_t RecBuff[15] = {0};
xdata uint8_t RxCount = 0;
bit Rx_Done = 0;
bit Rx_Start = 0;
/**
* @name Bt_Init[蓝牙初始化]
*/
void Bt_Init(void)
{
/*LDE初始化*/
P2M1 = P2M1&0xF0|0x08; //P22设置为推挽输出
LED = 1;
P2M0 = P2M0&0x0F|0x80; //P21设置为推挽输出
P0M1 = P0M1&0x0F|0x20; //P03设置为上拉输入
TXD_MAP = 0x21; //TXD映射P21
RXD_MAP = 0x03; //RXD映射P03
T4CON = 0x06; //T4工作模式:UART1波特率发生器
/*
T4计数+1时间 = T4时钟/T4分频/16
波特率+1信号时间 = 1/9600(波特率)---[9600波特率是每秒传输9600个0/1电平信号]
初值 = T4计数+1时间/波特率+1信号时间
*/
TH4 = 0xFF;
TL4 = 0x98; //波特率9600
SCON2 = 0x02; //8位UART,波特率可变
SCON = 0x10; //允许串行接收
IE |= 0X10; //使能串口中断
}
/**
* @name
*/
void UART1_Rpt(void) interrupt UART1_VECTOR
{
if(SCON & 0x01) //判断接收中断标志位
{
if (rx_timeout.flag) //超时
return;
else
{
rx_timeout.start = 1; //开启超时
rx_timeout._10ms = 10; //重置定时器时间
Rx_Start = 1; //开始接收
}
RecBuff[RxCount++] = SBUF;//转存8位串口接收数据
if(RxCount >= 15)
{
SCON &=~ 0x10; //失能UART1接收
Rx_Done = 1;
}
SCON &=~ 0x01; //清除接收中断标志位
}
}
/**
* @name Rx_Proc[接收包处理]
*/
void Rx_Proc(void)
{
if (Rx_Start == 0)
return;
if (rx_timeout.flag) //接收超时,相当于接收完成,需要对接收准备复原
{
rx_timeout.flag = 0;
RxCount = 0;
Rx_Done = 1;
SCON &=~ 0x10; //失能UART1接收
Rx_Start = 0;
}
if(Rx_Done)
{
LCD_Clear();
if (strcmp((uint8_t*)RecBuff,"ON")==0)
{
LCD_Display_Words(0, 0, "开灯:");
LCD_Display_Words(0, 3, RecBuff);
P2_2 = 0;
}
else if (strcmp((uint8_t*)RecBuff,"OFF")==0)
{
LCD_Display_Words(0, 0, "关灯:");
LCD_Display_Words(0, 3, RecBuff);
P2_2 = 1;
}
else
{
LCD_Display_Words(0, 0, "未知命令:");
LCD_Display_Words(0, 5, RecBuff);
}
Rx_Done = 0;
RxCount = 0; //接收指针复位
memset(RecBuff, 0, sizeof(RecBuff));
SCON |= 0x10; //允许串行接收
}
}
这里面的接收采用的是一个10ms的超时检测,在收到第一个字节后开始10ms超时检测,10ms后没有收到字节认为接收完成,同时结合LCD显示
bt.h
#ifndef _BT_H_
#define _BT_H_
#include "public.h"
#define LED P2_2
extern xdata uint8_t RecBuff[15];
void Bt_Init(void);
void Rx_Proc(void);
#endif
time.c[粗糙软定时器]
#include "time.h"
xdata RX_TIMEOUT rx_timeout;
/**
* @name Timer_Init[定时器初始化]
*/
void Timer_Init(void)
{
TCON1 = 0x00; //Tx0定时器时钟为Fosc
TMOD = 0x00; //16位重装载定时器/计数器
TH0 = (65536-1333) / 256; //256是0xFF,大于0xFF的都是256的商
TL0 = (65536-1333) % 256; //T0定时时间1ms
IE |= 0x02; //打开T0中断
TCON |= 0x10; //使能T0
rx_timeout.flag = 0;
}
/**
* @name 定时器中断
*/
void TIMER0_Rpt(void) interrupt TIMER0_VECTOR
{
if (rx_timeout.start)
rx_timeout._10ms--;
if (rx_timeout._10ms == 0)
{
rx_timeout.flag = 1;
rx_timeout._10ms = 10;
rx_timeout.start = 0;
}
}
time.h
#ifndef _TIME_H_
#define _TIME_H_
#include "public.h"
typedef struct{
uint8_t _10ms;
uint8_t flag:1;
uint8_t start:1;
}RX_TIMEOUT;
extern xdata RX_TIMEOUT rx_timeout;
void Timer_Init(void);
#endif
基本上代码就是这样了,LCD显示的代码