使用的是HC-06模块

HC-06默认的波特率是9600,8位数据为,1位停止位,无校验位
在使用串口助手调试的时候,需要勾选自动换行,这里选用的友善串口助手

修改蓝牙的AT指令可以查看蓝牙芯片手册,AT指令

如果是上电长亮说明是直接进入了一个AT模式和配对模式,可以使用手机搜索到蓝牙模块,配对上,但是手机里面的蓝牙系统是连接不上HC-06的,需要额外下载一个蓝牙串口,在蓝牙串口连接上模块之后,模块的指示灯常亮,这时可以进行通信

2020.3.11


在经过12号一天对LCD12864液晶显示屏的后,继续HC-06蓝牙模块的使用

  • 目的:手机连接蓝牙模块控制LED的亮灭

蓝牙模块和单片机之间的通信是UART串口方式,使用的是圣芯的HC89S003F4单片机,连接好蓝牙模块和单片机,手机发送信息给蓝牙模块,蓝牙模块将接收到的信息通过UART转发给单片机

Android 蓝牙连接后读写 蓝牙模块读取数据_Android 蓝牙连接后读写


只需要在单片机里面处理接受到的信号就可以了,所以说非常的简单

接下来是代码

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显示的代码