什么可以用手机蓝牙控制LED???#串口通信【下】

前言

  本篇博文介绍的是用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-08TXD连接51单片机的RXD
  • 将蓝牙模块HC-08RXD连接51单片机的TXD
  • 将蓝牙模块HC-08VCC连接51单片机的5V
  • 将蓝牙模块HC-08GND连接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-08TXD连接USBTTL转接器的RXD
  • 将蓝牙模块HC-08RXD连接USBTTL转接器的TXD
  • 将蓝牙模块HC-08VCC连接USBTTL转接器的5V
  • 将蓝牙模块HC-08GND连接USBTTL转接器的GND

6.3把USB转TTL转接器连接电脑通过单片机下载器修改蓝牙名称

  • 在单片机下载器中打开串口助手
  • 接收和发送缓冲区都设置为文本模式
  • 串口设置为相应串口,波特率为9600,校验位为无校验,停止位为1位
  • *在发送缓冲区发送AT+NAME=* * 即可修改蓝牙名字
  • 特别注意在修改蓝牙名字时,不用用手机端蓝牙助手连接蓝牙模块,不然会修改失败。

在这里插入图片描述

结束语

  很高兴您能看到这里,点个赞再走呗。谢谢您啦!!!

最近更新

  1. TCP协议是安全的吗?

    2024-02-01 11:36:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-01 11:36:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-01 11:36:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-01 11:36:03       20 阅读

热门阅读

  1. Flask 之 SQLAlchemy

    2024-02-01 11:36:03       33 阅读
  2. Rust - 变量

    2024-02-01 11:36:03       32 阅读