系列博文:
(1)安卓手机与蓝牙模块联合调试(一)——蓝牙模块的串口通讯
(2)安卓手机与蓝牙模块联合调试(二)—— 单片机蓝牙控制LED灯亮灭(上)
(3)安卓手机与蓝牙模块联合调试(三)—— 单片机蓝牙控制LED灯亮灭(下)
本教程的项目地址:1989Jiangtao/BluetoothSCM: 安卓手机通过蓝牙与单片机通信-发送指令/接收数据
继续承接上两篇文章,这一篇会写下使用STC89单片机编程,蓝牙接收数据,控制LED灯的亮灭。
安卓手机与蓝牙模块联合调试(二)—— 单片机蓝牙控制LED灯亮灭(上)
安卓手机与蓝牙模块联合调试(一)——蓝牙模块的串口通讯
一个USB转串口下载器(CH340),蓝牙模块(先用HC-05做本次调试,下次一并讲CC2541),一块含有STC89单片机的最小板(这里我用的是自己闲时画的一块小板,含红外和OLED显示屏,还有一颗RGB灯),来个全家福。
此次开发编译工具使用KEIL,keil需要大家自行下载安装和破解。
程序下载使用STC官方的下载工具,附上下载链接:http://www.stcmcudata.com/STCISP/stc-isp-15xx-v6.86O.zip
其实简单来讲,蓝牙传输数据依据的就是串口通讯,如果你搞明白了单片机的串口通讯,那么编程就变得相当简单了。下面带大家开始撸代码,这一段的话仅针对单片机初级选手而言,老鸟不喜勿喷。
先教新手偷个懒,如何使用STC-ISP来直接下载串口代码。直接上图了。
这样下载后代码是可以直接运行的,下面我来个截图,主要是我的板子上接的是P2口,8个LED灯,直接用指示灯来指示收到的数据。
因此我在拷贝下来的代码中又改了些地方,主要是用来做指示灯的指示用的,也给大家截个图。
这个是STC-ISP自带的程序,大家可以研究下,这里的SBUF表示的是收到的数据。我就偷个懒直接改了下,主要演示用。下面看下实际的效果,由于不能上传视频,就只能用图片来做说明了。还是通过蓝牙串口发送指令,这次是直接发送的16进制指令,STC单片机接收后,通过P2口指示灯来输出显示发送的指令值。
上面我是直接偷懒了 ,下面带大家撸代码了,单片机串口的代码其实网上有很多可以参考的,下面上代码。
/****************************************
** 蓝牙串口接收数据
**
** 作者:江涛
** 时间:2018/08/31
** 描述:串口发送数据兼用OLED显示
****************************************/
#include "STC89C5xRC_RDP.h"
#include "string.h" // 要使用字符串对比函数,需要引入该头文件
#include "OLED.h" // OLED显示屏头文件
// 定义系统时钟和串口波特率
#define FOSC 11059200L // 系统时钟
#define BAUD 9600 // 串口波特率
/******变量声明*********/
char RECEIVED_CMD[10] ; // 暂定为10字节的指令
char RECEIVED_INDEX ; // 数组指示索引,当接收到一个数据之后,索引会跟随增加
unsigned char flag = 0 ; // 数据接收的标志位
/******命令常量*******/
code const char* LED_ON = "ON\r\n" ;
code const char* LED_OFF = "OFF\r\n" ;
/*******函数声明*********/
void Init_UART(); // 初始化串口
void UART_SendData(char dat); // 串口发送数据
void UART_SendStr(char* str); // 串口发送字符串
/*******程序入口*********/
void main()
{
Init_UART(); // 串口初始化
// LCD_Init(); // OLED 初始化
// LCD_CLS(); // 清屏
//
// LCD_P8x16Str(0 , 0 , "CODE:");
while(1)
{
if(flag) // 接收数据完毕一次,就会进入中断一次
{
flag = 0 ; // 将标志位还原,使得串口又可以重新接收数据
UART_SendStr(RECEIVED_CMD); // 接收到的数据通过串口发送回去
// LCD_P8x16Str(6*8 , 0 , RECEIVED_CMD); // 显示接收代码
// P2 = ~P2 ; // 翻转P2口的灯,用来测试接收到了数据
if(strcmp(RECEIVED_CMD , LED_ON) == 0)
{
P2 = 0xFF ; // P2口全亮
}
else if(strcmp(RECEIVED_CMD , LED_OFF) == 0)
{
P2 = 0x00 ; // P2口全灭
}
// 用完之后要记得数组清零处理
RECEIVED_INDEX = 0 ; // 数组指引复位
memset(RECEIVED_CMD,0,10); // 清0数组
}
}
}
/******************
** 初始化串口
*******************/
void Init_UART()
{
SCON = 0x50; //设置8位数据位
TMOD = 0x20; //8位自动重载
TH1 = TL1 = -(FOSC/12/32/BAUD); //设置重载值
TR1 = 1; //使能时钟
ES = 1; //使能串口中断
EA = 1; //开中断开关
}
/********************
** 串口中断处理
*********************/
void UART_Isr() interrupt 4 using 1
{
// 串口接收中断处理
if(RI)
{
RI = 0 ; // 清除中断标志位
RECEIVED_CMD[RECEIVED_INDEX] = SBUF ; // 保存串口接收的数据
if(RECEIVED_CMD[RECEIVED_INDEX] == 0x0A ){ // 遇到了结束符号
flag = 1 ; // 接收结束,到循环中处理接收的数据
}else {
RECEIVED_INDEX ++ ; // 继续接收数据
}
}
// 串口发送中断处理
if(TI)
{
TI = 0 ; // 清发送中断标志位
}
}
/**************************
** 通过串口发送一位数据
***************************/
void UART_SendData(char dat)
{
ES = 0 ; // 串口工作的时候禁止中断
SBUF = dat ; // 待发送的数据放到SBUF中
while(!TI) ; // 等待发送完毕
TI = 0 ; // 清TI中断
ES = 1 ; // 打开中断
}
/*****************************
** 通过串口发送字符串
******************************/
void UART_SendStr(char *str)
{
do
{
UART_SendData(*str);
}while(*str ++ != '\0' ); // 一直到字符串结束
}
本来是有一个OLED显示的,为了方便大家理解,我直接把OLED部分去掉了,代码中定义了两个命令,LED_ON 和LED_OFF, 注意事项,如果你是直接拷贝的话应该是不能运行的。因为安卓的换行对应的只有“\n”,所以拷贝后应该把命令换成如下格式,安卓调试助手才能识别开关灯的命令。
/******命令常量*******/
code const char* LED_ON = "ON\n" ;
code const char* LED_OFF = "OFF\n" ;
看下运行后的效果,
好了,至此第一阶段单片机和蓝牙的通讯部分已经基本搞定,其实主要就是单片机的串口通讯的应用,下面的文章将围绕开发一个自己的安卓蓝牙应用为主要内容展开。