什么可以用手机蓝牙控制LED???#串口通信【下】
- 前言
- 预备知识
- 1.小白玩串口控制的ASSII避坑
- 1.1问题引入
- 1.2解决问题
- 2.串口支持单词型指令控制
- 2.1实现串口支持单词型指令控制的核心思路
- 2.2利用字符数组来承接单词型指令
- 2.3利用strstr函数来查找指令并执行
- 2.4完整程序代码
- 2.5补充知识
- 3.串口原理协议概念收尾
- 3.1串行口工作模式1:8位UART,波特率可变
- 3.2串行口工作模式1:8位UART,波特率可变时序图
- 3.3串口结构框图
- 4.通过手机蓝牙控制LED
- 4.1向单片机中烧入串口支持单词型指令控制代码
- 4.2将蓝牙模块HC-08连接单片机
- 4.3通过蓝牙串口助手小程序连接蓝牙模块
- 4.4在发送对话框发送开灯即可打开LED灯,发送关闭即可关闭LED灯。
- 5.HC-08蓝牙模块
- 5.1蓝牙模块简介
- 5.2 HC-08蓝牙串口通信模块接线
- 6.AT指令修改蓝牙名字
- 6.1 AT指令表
- 6.2将USB转TTL转接器与蓝牙模块HC-08连接
- 6.3把USB转TTL转接器连接电脑通过单片机下载器修改蓝牙名称
- 结束语
前言
本篇博文介绍的是用51单片机的串口通信【下】,包含小白玩串口控制的ASSII避坑,串口支持单词型指令控制,串口原理协议概念收尾,通过手机蓝牙控制LED,HC-08蓝牙模块,AT指令修改蓝牙名字。看到这篇博文的朋友,可以先赞再看吗?
预备知识
一、数学分数计算。
二、数字电子时序图
三、数字电子中与或运算
四、计算机中的进制转换
五、C变量
六、基本输入输出
七、流程控制
八、函数
九、指针
十,字符串
如果以上知识不清楚,请自行学习后再来浏览。如果我有没例出的,请在评论区写一下。谢谢啦!
1.小白玩串口控制的ASSII避坑
1.1问题引入
如果要用1控制开灯,0控制关灯。那么是直接改判断条件还是怎么做呢?
1.2解决问题
- 显然是不行的,直接用1开灯,0关灯单片机上是没有任何反应的。因为中的是文本模式发送。
- 尝试改到HEX模式呢?
实验后观察可以开灯,也可以关灯
这是为什么呢?我们想一想,在C语言中为什么int
型和char
型是可以互通的呢?其实是因为ASSII
码的存在。也就是说计算机在处理文本时是用ASSII
码来处理,所以在代码为1开灯0关灯
时在文本模式下输入1开灯0关灯不执行,是因为代码下的1和0不是文本下的1和0的ASSII码
。若要实现在文本模式下输入1开灯0关灯,那么就要在代码内写49和48来控制开关灯,因为49是1的ASSII码,48是0的ASSII码。
当使用HEX模式时,在计算机中把16进制的1和二进制的1是互通的,
也就是此时输入1能被单片机识别并执行开灯。
- ASSI码对照表
2.串口支持单词型指令控制
2.1实现串口支持单词型指令控制的核心思路
利用字符数组来承接单词型指令
利用strstr函数来查找指令并执行
2.2利用字符数组来承接单词型指令
- 将接收电脑开关灯的指令变量定义为一个大小为32的字符数组,并用宏定义定义出大小为32
#define SIZE 32
char LEDStatus[SIZE];
- 在串口中断函数中定义一个静态变量,因为在多次函数调用中只被执行一次初始化
static int i = 0;
- 让SBUF寄存器的数据赋给LEDStatus[i]的第i个元素,并入让i自增。为了方便一个字符一个字符的存入字符数组
LEDStatus[i] = SBUF;
i++; //数组标号增加,方便存放字符串
2.3利用strstr函数来查找指令并执行
- 选用
strstr
字符查找函数是因为:如果选用strcmp
字符串比较函数,必须一致才成立,但在传送字符串是会把字符顺序搞乱。所以使用查找函数来查找,查找函数只需要查找含有相应字符即可,不必顺序一致。 - 使用strstr函数必须包含头文件
string.h
#include "string.h"
- 在if判断内将i软件置零,使用memset函数将LEDStatus变量清零
i = 0; //清零是为了方便存放下一次指令
memset(LEDStatus,'\0',SIZE); //字符串清零函数,实参为清零的字符串变量,清理成什么字符,清理的大小或数量
2.4完整程序代码
#include "reg52.h"
#include "string.h"
#define SIZE 32
sfr AUXR = 0x8e; //声明AUXR寄存器地址
sbit LED1 = P3^7; //使用位定义声明LED1
//建立接收电脑开关灯的指令变量
char LEDStatus[SIZE];
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit(void) //自己配
{
//配置串口工作方式为方式1,从只收不发改为能收能发
SCON = 0x50;
//配置辅助寄存器,减少电磁辐射,稳定晶振频率
AUXR = 0x01;
//设置定时器工作方式为定时器1的8位自动重装
TMOD &= 0x0F;
TMOD |= 0x20;
//设置串口波特率为9600,0误差
TH1 = 0xFD;
TL1 = 0xFD;
//打开定时器1
TR1 = 1;
//打开总中断
EA = 1;
//打开串口中断
ES = 1;
}
void sendByte(char data_mas)
{
SBUF = data_mas;
while(!TI);
TI = 0; //一定要软件置零,不然会出现乱序
}
void sendString(char *str)
{
while(*str != '\0')
{
sendByte(*str);
str++;
}
}
void main()
{
//初始化灯的状态
LED1 = 1;
//初始化串口,配置波特率
UartInit();
//每延时1秒向电脑发送数据a
while(1)
{
Delay1000ms();
sendString("一起来学串口通信!!!\r\n"); //\r\n 为串口中的换行,缺一不可
//怎么知道PC发了数据:由手册可知RI位为接受中断标志位,所以用查询的方法来判断RI是否等于1来开关灯
}
}
void UART_handler() interrupt 4
{
//定义一个静态整型变量,在多次函数调用中只被执行一次初始化
static int i = 0;
//在串口中段函数中可以对发送接收中断标志进行处理
if(RI == 1)
{
RI = 0; //必须软件置零
LEDStatus[i] = SBUF;
i++; //数组标号增加,方便存放字符串
//如果用开灯指令开灯,关灯指令关灯
if(strstr(LEDStatus,"开灯")) //运用C语言字符串知识,使用的是字符串查找函数,查找到即返回1
{
LED1 = 0;
i = 0; //清零是为了方便存放下一次指令
memset(LEDStatus,'\0',SIZE); //字符串清零函数,实参为清零的字符串变量,清理成什么字符,清理的大小或数量
}
if(strstr(LEDStatus,"关灯"))
{
LED1 = 1;
i = 0;
memset(LEDStatus,'\0',SIZE);
}
}
if(TI);
}
2.5补充知识
- 在字符串中是支持中文的,计算机内部会把中文转换为相应的编码,方便使用
3.串口原理协议概念收尾
3.1串行口工作模式1:8位UART,波特率可变
当软件设置SCON的SM0、SM1为“01”时,串行通信则以模式1工作。此模式为8位UART格式,**一帧信息为10
位:1
位起始位,8
位数据位(低位在先)和1
位停止位。**波特率可变,即可根据需要进行设置。TxD(TxD/P3.1)
为发送信息,RxD(RxD/P3.0)
为接收端接收信息,串行口为全双工接受/发送串行口。
3.2串行口工作模式1:8位UART,波特率可变时序图
3.3串口结构框图
4.通过手机蓝牙控制LED
4.1向单片机中烧入串口支持单词型指令控制代码
#include "reg52.h"
#include "string.h"
#define SIZE 32
sfr AUXR = 0x8e; //声明AUXR寄存器地址
sbit LED1 = P3^7; //使用位定义声明LED1
//建立接收电脑开关灯的指令变量
char LEDStatus[SIZE];
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit(void) //自己配
{
//配置串口工作方式为方式1,从只收不发改为能收能发
SCON = 0x50;
//配置辅助寄存器,减少电磁辐射,稳定晶振频率
AUXR = 0x01;
//设置定时器工作方式为定时器1的8位自动重装
TMOD &= 0x0F;
TMOD |= 0x20;
//设置串口波特率为9600,0误差
TH1 = 0xFD;
TL1 = 0xFD;
//打开定时器1
TR1 = 1;
//打开总中断
EA = 1;
//打开串口中断
ES = 1;
}
void sendByte(char data_mas)
{
SBUF = data_mas;
while(!TI);
TI = 0; //一定要软件置零,不然会出现乱序
}
void sendString(char *str)
{
while(*str != '\0')
{
sendByte(*str);
str++;
}
}
void main()
{
//初始化灯的状态
LED1 = 1;
//初始化串口,配置波特率
UartInit();
//每延时1秒向电脑发送数据a
while(1)
{
Delay1000ms();
sendString("一起来学串口通信!!!\r\n"); //\r\n 为串口中的换行,缺一不可
//怎么知道PC发了数据:由手册可知RI位为接受中断标志位,所以用查询的方法来判断RI是否等于1来开关灯
}
}
void UART_handler() interrupt 4
{
//定义一个静态整型变量,在多次函数调用中只被执行一次初始化
static int i = 0;
//在串口中段函数中可以对发送接收中断标志进行处理
if(RI == 1)
{
RI = 0; //必须软件置零
LEDStatus[i] = SBUF;
i++; //数组标号增加,方便存放字符串
//如果用开灯指令开灯,关灯指令关灯
if(strstr(LEDStatus,"开灯")) //运用C语言字符串知识,使用的是字符串查找函数,查找到即返回1
{
LED1 = 0;
i = 0; //清零是为了方便存放下一次指令
memset(LEDStatus,'\0',SIZE); //字符串清零函数,实参为清零的字符串变量,清理成什么字符,清理的大小或数量
}
if(strstr(LEDStatus,"关灯"))
{
LED1 = 1;
i = 0;
memset(LEDStatus,'\0',SIZE);
}
}
if(TI);
}
4.2将蓝牙模块HC-08连接单片机
- 将蓝牙模块
HC-08
的TXD
连接51
单片机的RXD
。 - 将蓝牙模块
HC-08
的RXD
连接51
单片机的TXD
。 - 将蓝牙模块
HC-08
的VCC
连接51
单片机的5V
。 - 将蓝牙模块
HC-08
的GND
连接51
单片机的GND
。
4.3通过蓝牙串口助手小程序连接蓝牙模块
- 微信小程序搜索HCBLE串口助手
- 打开HCBLE串口助手
- 点击附近设备
- 找到HC-08的设备并点击连接。
- 在弹出的页面中可以看到单片机发送的字符。也可以发送字符给单片机。
4.4在发送对话框发送开灯即可打开LED灯,发送关闭即可关闭LED灯。
5.HC-08蓝牙模块
5.1蓝牙模块简介
- 蓝牙模块,又叫做蓝牙串口模块
- 串口透传技术
透传即透明传送,是指在数据的传输过程中,通过无线的方式这组数据不发生任何形式的改变,仿佛传输过程是透明的一样,同时保证传输的质量,原封不动地到了最终接收者手里。
- 以太网,蓝牙,Zigbee, GPRS 等模块玩法一样,对嵌入式程序员来说,不需要关心通讯模块内部数据及协议栈工作原理,只要通过串口编程获得数据即可
- HC-08蓝牙串口通信模块为一对一连接透传,主从机一体。(用户可根据需求,用AT指令切换模块主从)
- HC-08的参数
5.2 HC-08蓝牙串口通信模块接线
6.AT指令修改蓝牙名字
6.1 AT指令表
6.2将USB转TTL转接器与蓝牙模块HC-08连接
- 将蓝牙模块
HC-08
的TXD
连接USB
转TTL
转接器的RXD
。 - 将蓝牙模块
HC-08
的RXD
连接USB
转TTL
转接器的TXD
。 - 将蓝牙模块
HC-08
的VCC
连接USB
转TTL
转接器的5V
。 - 将蓝牙模块
HC-08
的GND
连接USB
转TTL
转接器的GND
。
6.3把USB转TTL转接器连接电脑通过单片机下载器修改蓝牙名称
- 在单片机下载器中打开串口助手
- 接收和发送缓冲区都设置为文本模式
- 串口设置为相应串口,波特率为9600,校验位为无校验,停止位为1位
- *在发送缓冲区发送AT+NAME=* * 即可修改蓝牙名字
- 特别注意在修改蓝牙名字时,不用用手机端蓝牙助手连接蓝牙模块,不然会修改失败。
结束语
很高兴您能看到这里,点个赞再走呗。谢谢您啦!!!