600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 51单片机之串口通信 WiFi模块 蓝牙模块 4G模块

51单片机之串口通信 WiFi模块 蓝牙模块 4G模块

时间:2023-02-23 14:56:08

相关推荐

51单片机之串口通信 WiFi模块 蓝牙模块 4G模块

目录

串口通信

全双工通信(打电话)

TTL电平

UART

串口相关的寄存器

串口的工作模式

蓝牙模块HC-08

HC-08的AT指令​编辑

WiFi模块ESP8266

配置WiFi模块作为客户端连入当前局域网

配置WiFi模块作为服务器

​编辑

4G模块EC03-DNC4

配置4G模块

串口通信

串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方 式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简 单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成 本,特别适用于远距离通信,但传送速度较慢

设备之间的一种通信的方式(数据交互)数据只能一位一位的进行传输全双工通信数据传输速度较慢

全双工通信(打电话)

通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A)。指A→B的同时B→A,是瞬时同步的。通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A)。指A→B的同时B→A,是瞬时同步的。

TTL电平

TTL是Transistor-Transistor Logic,即晶体管-晶体管逻辑的简称,它是计算机处理器控制的设备 内部各部分之间通信的标准技术。TTL电平信号应用广泛,是因为其数据表示采用二进制规定, +5V等价于逻辑”1”,0V等价于逻辑”0”。

UART

通用异步收发器(UART)也是一种串口通信协议,通过异步来发送/接收数据,USB转TTL就是使用UART的一种模块。

工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。

两个UART设备之间通信的时候不需要时钟线,这时候就需要在两个UART设备上指定相同的传输速率(波特率),以及数据格式(起始位、数据位、奇偶检验位、停止位),也就是遵循相同的协议。

起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。数据位:数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位),扩展BCD码(8位)。先发送最低位,最后发送最高位,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。奇偶校验位:计算数据位中“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性,校验方式:

停止位:一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。

总之,使用UART串口协议传输数据时,需要规定双方的传输速率(波特率)一致,数据格式(起始位,数据位,奇偶校验为、停止位)也要保持一致。例如传递字符a时,字符a的一帧信息由起始位、数据位(字符a)、奇偶校验位(可选)、停止位组成。

串口相关的寄存器

串口数据缓冲寄存器(SUBF寄存器)

SUBF寄存器有两个缓冲器,分别是只读寄存器和只写寄存器,写SBUF操作完待发送数据的加载,读SBUF操作获得已接收到的数据想要从SUBF寄存器读取数据时:char data = SBUF;想要向SUBF寄存器的写入数据时:SBUF = data;

电源控制寄存器PCON

LVDF(B5):低电压检测标志位,同时也是低电压检测中断请求标志位

GF1、GF0:两个通用工作标志位,用户可以自由使用

PD:掉电模式设定位,PD=0:单片机处于正常工作状态,PD=1:单片机进入掉电模式可由外部中断或硬件复位模式唤醒,进入掉电模式后,外部晶振停振,CPU、定时器、串行口全部停止工作,只有外部中断工作。在该模式下,只有硬件复位和上电能够唤醒单片机。

IDL:空闲模式设定位,IDL=0:单片机处于正常工作状态,IDL=1:单片机进入空闲(Idle)模式,除CPU不工作外,其余仍继续工作,在空闲模式下。

串行控制寄存器SCON

对于位TI和位RI:

IE寄存器

IP寄存器、IPH寄存器

串口的工作模式

工作模式1:

完成一帧信息的发送后,硬件置位TI,即TI = 1,向主机请求中断处理。完成一帧信息的接收后,会判断是否满足RI = 0以及SM2 = 0或接收到的停止位为1这两个条件,如果满足,则这帧信息装入SBUF寄存器,停止位进入SCON寄存器的RB8,然后硬件置位RI,即RI = 1。波特率可变:

工作模式2:

完成一帧信息的发送后,硬件置位TI,即TI = 1,向主机请求中断处理。完成一帧信息的接收后,会判断是否满足RI = 0以及SM2 = 0,接收到的第9位数据位RB8 = 1或SM2 = 1,接收到的第9位数据位RB8 = 1这两个条件,如果满足,则这帧信息装入SBUF寄存器,停止位进入SCON寄存器的RB8,然后硬件置位RI,即RI = 1。波特率不可变:

工作模式3:

完成一帧信息的发送后,硬件置位TI,即TI = 1,向主机请求中断处理。完成一帧信息的接收后,会判断是否满足RI = 0以及SM2 = 0,接收到的第9位数据位RB8 = 1或SM2 = 1,接收到的第9位数据位RB8 = 1这两个条件,如果满足,则这帧信息装入SBUF寄存器,停止位进入SCON寄存器的RB8,然后硬件置位RI,即RI = 1。波特率可变:

PC机串口调试助手(STC-ISP)发送字符o时让51单片机的蜂鸣器叫,发送字符c时让51单片机的蜂鸣器停止叫。

#include "reg52.h"#include <intrins.h>sfr AUXR = 0x8E;sbit buzzer = P1^2;char cmd;void Delay1000ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);}void uartInit(){AUXR = 0x01;PCON &= 0x7F; //配置波特率正常SCON = 0x50; //配置串口选择工作方式1,允许串口接收数据//配置定时器1为8位自动重装模式TMOD &= 0x0F;TMOD |= 0x20;//给定时器1,9600波特率初值TH1 = 0xFD; //定时器1初值TL1 = 0xFD; //定时器1重装值ET1 = 0; //不允许定时器1产生中断TR1 = 1; //开启定时器1EA = 1; //开启总中断ES = 1; //开启串口中断}void sendByte(char mydata){SBUF = mydata; //向串口发送一帧信息while(!TI); //等待硬件置位TI = 0; //TI软件清0 }void sendString(char *str){while(*str != '\0'){sendByte(*str);str++;}}void main(){buzzer = 1;uartInit();while(1){sendString("jiangxiaoya\r\n"); //发送心跳包,确保串口通信没有中断Delay1000ms();}}void myUart() interrupt 4{//接收数据后,RI硬件置位产生的中断if(RI){RI = 0; //RI软件清0cmd = SBUF; //获取从pc端接收到的数据if(cmd == 'o'){buzzer = 0;}if(cmd == 'c'){buzzer = 1;}}//接收数据后,TI硬件置位产生的中断if(TI); }

PC机串口调试助手(STC-ISP)发送字符串open时让51单片机的蜂鸣器叫,发送字符串close时让51单片机的蜂鸣器停止叫。

#include "reg52.h"#include <intrins.h>sfr AUXR = 0x8E;sbit buzzer = P1^2;char cmd[12] ;void Delay1000ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);}void uartInit(){AUXR = 0x01;PCON &= 0x7F; //配置波特率正常SCON = 0x50; //配置串口选择工作方式1,允许串口接收数据//配置定时器1为8位自动重装模式TMOD &= 0x0F;TMOD |= 0x20;//给定时器1,9600波特率初值TH1 = 0xFD; //定时器1初值TL1 = 0xFD; //定时器1重装值ET1 = 0; //不允许定时器1产生中断TR1 = 1; //开启定时器1EA = 1; //开启总中断ES = 1; //开启串口中断}void sendByte(char mydata){SBUF = mydata; //向串口发送一帧信息while(!TI); //等待硬件置位TI = 0; //TI软件清0 }void sendString(char *str){while(*str != '\0'){sendByte(*str);str++;}}void main(){buzzer = 1;uartInit();while(1){sendString("jiangxiaoya\r\n"); //发送心跳包,确保串口通信没有中断Delay1000ms();}}void myUart() interrupt 4{static int i = 0;//接收数据后,RI硬件置位产生的中断if(RI){RI = 0; //RI软件清0//获取从pc端接收到的数据cmd[i] = SBUF;i++;if(i == 12){i = 0;}//strstr():字符串包含函数,不包含返回NULLif(strstr(cmd,"en") != NULL){buzzer = 0;i = 0;memset(cmd,'\0',12);}if(strstr(cmd,"os") != NULL){buzzer = 1;i = 0;memset(cmd,'\0',12);}}//接收数据后,TI硬件置位产生的中断if(TI); }

蓝牙模块HC-08

HC-08模块直接接线使用即可,可以使用STC-ISP软件发送AT指令:AT+NAME=名字,来修改蓝牙名字,跟STC-ISP里的串口助手使用方法一样。

HC-08的AT指令

WiFi模块ESP8266

wifi模块通过usb转ttl接入pc端,通过安信可串口调试助手修改esp8266的波特率,让它跟单片机的通信速度保持一致。

连接后发送AT指令修改esp8266波特率:

AT+RST ,重启esp8266AT ,检测esp8266的通信功能是否正常AT+UART=9600,8,1,0,0 ,修改波特率

esp8266的上网模式:

配置WiFi模块作为客户端连入当前局域网

AT+CWMODE=1 ,配置esp8266为客户端AT+CWJAP="WiFi名字","WiFi密码" ,esp8266连接WiFiAT+CIFSR ,查看当前IP地址

架设TCP服务器,往期博文《Linux网络编程》有TCP服务器的源码

AT+CIPSTART="TCP","IP地址",端口号 ,esp8266作为客户端,连入当前IP地址架设的TCP服务器AT+CIPMODE=1 ,开启透传模式AT+CIPSEND ,出现>后可以与服务器互相传输数据+++ ,退出透传模式

上述AT指令对应的响应

用51单片机使用esp8266作为客户端连入服务器

#include "reg52.h"#include <intrins.h>#include <string.h>sfr AUXR = 0x8E;sbit buzzer = P1^2;char mybuf[24];//相关AT指令char RESET[] = "AT+RST\r\n"; //重启esp8266code char LJWL[] = "AT+CWJAP=\"haozige\",\"123456789000\"\r\n"; //连接WiFicode char LJFWQ[] = "AT+CIPSTART=\"TCP\",\"192.168.97.198\",8880\r\n"; //连接TCP服务器char TCMS[] = "AT+CIPMODE=1\r\n"; //开启透传模式char SJCS[] = "AT+CIPSEND\r\n"; //开启数据传输int AT_OK_flag = 0;int AT_CONNECT_NET_flag = 0;void Delay500ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);}void Delay1000ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);}void Delay5000ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 36;j = 5;k = 211;do{do{while (--k);} while (--j);} while (--i);}void uartInit(){AUXR = 0x01;PCON &= 0x7F; //配置波特率正常SCON = 0x50; //配置串口选择工作方式1,允许串口接收数据//配置定时器1为8位自动重装模式TMOD &= 0x0F;TMOD |= 0x20;//给定时器1,9600波特率初值TH1 = 0xFD; //定时器1初值TL1 = 0xFD; //定时器1重装值ET1 = 0; //不允许定时器1产生中断TR1 = 1; //开启定时器1EA = 1; //开启总中断ES = 1; //开启串口中断}void sendByte(char mydata){SBUF = mydata; //向串口发送一帧信息while(!TI); //等待硬件置位TI = 0; //TI软件清0 }void sendString(char *str){while(*str != '\0'){sendByte(*str);str++;}}void main(){int mark = 0;buzzer = 1;uartInit();Delay5000ms(); //等待esp8266上电sendString(LJWL); while(!AT_CONNECT_NET_flag); //等待WiFi连接成功//while(!AT_OK);AT_OK_flag = 0;sendString(LJFWQ);while(!AT_OK_flag); //等待esp8266连接TCP服务器AT_OK_flag = 0;sendString(TCMS);while(!AT_OK_flag); //等待esp8266开启透传模式AT_OK_flag = 0;sendString(SJCS);while(!AT_OK_flag); //等待esp8266与tcp开启数据传输while(1){sendString("jiangxiaoya\r\n"); //发送心跳包,确保串口通信没有中断Delay1000ms();}}void myUart() interrupt 4{static int i = 0;char tmp;//接收数据后,RI硬件置位产生的中断if(RI){RI = 0; //RI软件清0//获取从pc端接收到的数据tmp = SBUF;if(tmp == 'W' || tmp == 'O' || tmp == 'L' || tmp == 'F'){i = 0;}mybuf[i] = tmp;i++;//连接wifi成功后,esp8266会返回WIFI GT IPif(mybuf[0] == 'W' && mybuf[1] == 'I'){AT_CONNECT_NET_flag = 1;memset(mybuf,'\0',24);}//esp8266连接TCP服务器或者其他AT指令,esp8266会返回OKif(mybuf[0] == 'O' && mybuf[1] == 'K'){AT_OK_flag = 1;memset(mybuf,'\0',24);}//TCP服务器发送数据给esp8266的灯控指令//开if(mybuf[0] == "L" && mybuf[1] == "1"){buzzer = 0;memset(mybuf,'\0',24);}//关if(mybuf[0] == "L" && mybuf[1] == "2"){buzzer = 1;memset(mybuf,'\0',24);}//WiFi连接失败后,会返回FALLif(mybuf[0] == 'F' && mybuf[1] == 'A'){for(i=0;i<5;i++){buzzer = 0;Delay500ms();buzzer = 1;Delay500ms();}sendString(RESET);memset(mybuf,'\0',24);}if(i == 24){i = 0;}}//接收数据后,TI硬件置位产生的中断if(TI); }

配置WiFi模块作为服务器

AT+CWMODE=2 ,配置esp8266为服务器AT+CIPMUX=1 ,开启多路连接,允许多个客户端连接,0为单连接AT+CIPSERVER=1 ,开启esp8266服务器(端口号为333)以该esp8266服务器的IP地址架设客户端,往期博文《Linux网络编程》有TCP客户端的源码

AT+CIPSEND=0,4 ,服务器往客户端发送4个字节数据

上述AT指令对应的响应

用51单片机使用esp8266架设服务器

#include "reg52.h"#include <intrins.h>#include <string.h>sfr AUXR = 0x8E;sbit buzzer = P1^2;char mybuf[24];//相关AT指令char LYMS[] = "AT+CWMODE=2\r\n"; //配置esp8266为路由模式char DLLJ[] = "AT+CIPMUX=1\r\n"; //配置esp8266多路连接char JLFWQ[] = "AT+CIPSERVER=1\r\n"; //建立esp8266服务器char FSSJ[] = "AT+CIPSEND=0,11\r\n"; //向客户端发送数据char AT_OK_flag = 0;char AT_CONNECT_NET_flag = 0;char Client_Connect_Net_flag = 0;void Delay500ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);}void Delay1000ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);}void Delay5000ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 36;j = 5;k = 211;do{do{while (--k);} while (--j);} while (--i);}void uartInit(){AUXR = 0x01;PCON &= 0x7F; //配置波特率正常SCON = 0x50; //配置串口选择工作方式1,允许串口接收数据//配置定时器1为8位自动重装模式TMOD &= 0x0F;TMOD |= 0x20;//给定时器1,9600波特率初值TH1 = 0xFD; //定时器1初值TL1 = 0xFD; //定时器1重装值ET1 = 0; //不允许定时器1产生中断TR1 = 1; //开启定时器1EA = 1; //开启总中断ES = 1; //开启串口中断}void sendByte(char mydata){SBUF = mydata; //向串口发送一帧信息while(!TI); //等待硬件置位TI = 0; //TI软件清0 }void sendString(char *str){while(*str != '\0'){sendByte(*str);str++;}}void main(){int mark = 0;buzzer = 1;uartInit();Delay5000ms(); //等待esp8266上电sendString(LYMS); while(!AT_OK_flag); //等待esp8266设置路由模式AT_OK_flag = 0;sendString(DLLJ);while(!AT_OK_flag); //等待esp8266设置多路连接AT_OK_flag = 0;sendString(JLFWQ);while(!Client_Connect_Net_flag); //等待esp8266建立服务器AT_OK_flag = 0;while(1){sendString(FSSJ); //发送心跳包,确保串口通信没有中断Delay1000ms();Delay1000ms();sendString("jiangxiaoya");Delay1000ms();Delay1000ms();}}void myUart() interrupt 4{static int i = 0;char tmp;//接收数据后,RI硬件置位产生的中断if(RI){RI = 0; //RI软件清0//获取从pc端接收到的数据tmp = SBUF;if(tmp == 'W' || tmp == 'O' || tmp == 'L' || tmp == '0'){i = 0;}mybuf[i] = tmp;i++;//esp8266设置路由模式等其他AT指令,esp8266会返回OKif(mybuf[0] == 'O' && mybuf[1] == 'K'){AT_OK_flag = 1;memset(mybuf,'\0',24);}//esp8266建立服务器,esp8266会返回0,CONNECTif(mybuf[0] == '0' && mybuf[2] == 'C' ){Client_Connect_Net_flag = 1;memset(mybuf, '\0' , 24);}//esp8266服务器发送数据给客户端的灯控指令//开if(mybuf[0] == "L" && mybuf[1] == "1"){buzzer = 0;memset(mybuf,'\0',24);}//关if(mybuf[0] == "L" && mybuf[1] == "2"){buzzer = 1;memset(mybuf,'\0',24);}if(i == 24){i = 0;}}//接收数据后,TI硬件置位产生的中断if(TI); }

4G模块EC03-DNC4

配置4G模块

进入AT指令模式:不勾选新行发送指令 +++ 后,勾选新行任意发一条AT指令(不要发AT+REBT,该AT指令为重启4G模块)AT+UARTEX ,查询当前4G模块的波特率AT+UART=9600,NONE ,修改当前当前4G模块的波特率为9600AT+HEARTINFO , 查询当前心跳包的数据AT+HEARTINFO=jiangxiaoya ,修改当前心跳包的数据AT+HEARTM ,查询当前心跳包时间AT+HEARTM=time ,修改当前心跳包的时间,心跳时间为1~65535s,0为关闭心跳包

用本地IP地址架设TCP服务器,往期博文《Linux网络编程》有TCP服务器的源码

借助花生壳软件,使用刚刚架设的服务器的IP地址和端口号进行内网穿透

使用内网穿透映射的地址架设客户端(获取服务器的IP地址和端口号),往期博文《Linux网络编程》有TCP客户端的源码

从架设的服务器任意发送一条信息到架设的客户端获取服务器的IP地址和端口号,来供4G模块使用(IP地址:103.46.128.53,端口号:10146)

AT+SOCK=TCPC,IP地址,端口号 ,连接架设的服务器,连接成功后,4G模块就会往架设的服务器发送心跳包,也就是说,架设的服务器能够与4G模块进行通信,且数据能通过串口交互到pc端的安信可调试助手,即能与单片机进行通信。

4G模块与51单片机进行通信,发送字符串:open让蜂鸣器叫,发送字符串:close让蜂鸣器不叫

#include "reg52.h"#include <intrins.h>#include <string.h>#define SIZE 12sfr AUXR = 0x8e;sbit buzzer = P1 ^ 2;char cmd[SIZE];void Delay1000ms() //@11.0592MHz{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);}void UartInit(void) // 9600bps@11.0592MHz{PCON &= 0x7F; //波特率不倍速SCON = 0x50; // 8位数据,可变波特率AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12TAUXR &= 0xFE; //串口1选择定时器1为波特率发生器TMOD &= 0x0F; //清除定时器1模式位TMOD |= 0x20; //设定定时器1为8位自动重装方式TL1 = 0xFD; //设定定时初值TH1 = 0xFD; //设定定时器重装值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1EA = 1; //允许总中断ES = 1; //允许串口中断}void main(){buzzer = 1;UartInit();while(1);}void Uart_Handler() interrupt 4{static int i = 0; char tmp;//接收数据后,RI硬件置位产生的中断if(RI){RI = 0; //RI软件清0//获取从pc端接收到的数据tmp = SBUF;if(tmp == ':'){i = 0;}cmd[i++] = tmp;if(i == SIZE){i = 0;}if(cmd[0] == ':' && cmd[1] == 'o' && cmd[2] == 'p'){buzzer = 0;i = 0;memset(cmd, '\0', SIZE);}if(cmd[0] == ':' && cmd[1] == 'c' && cmd[2] == 'l'){buzzer = 1;i = 0;memset(cmd, '\0', SIZE);}}if(TI);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。