串口与4g模块

news/2024/10/18 14:23:00/

1.认识4G模块

1、接线与插卡:EC03-DNC4G通信模块,生产的公司是EBYTE(亿佰特)。官网上有软件和用户手册下载地址。

  • 保证插卡不插错,一是使用SIM卡卡套,二是方向保证正确。如图位置是SIM卡状态灯,只有插对位置,在4G模块上电几秒钟完成初始化后这盏灯才会亮。
  • 一会儿进入测试之前需要把电源、天线、SIM卡、串口线等硬件接好。
  • 注:一定要有micro型号的卡套,一会是用手机提供热点给电脑连接,所以最好有双sim卡。

 2、翻阅用户手册:

  1. 供电电压
  2. 功能特点
    1. Socket其实就是在调用TCP,我们使用TCP其实走的就是Socket。
    2. 4G模块还支持MQTT协议。
  3. 硬件参数:波特率默认是115200bps。
  4. 工作情况
  5. AT指令集:省略“AT+”
  6. REBT重启模块REGINFO设置/查询自定义注册包信息(ASCII)UARTTS设置/查询串口打包长度、打包间隔
    VER查询版本号REGINFONEW设置/查询自定义注册包信息(16 进制)MODBUS设置/查询odbusTCP/RTU 转换功能
    INFO查询设备信息HEARTMOD设置/查询心跳包模式MTCPID设置/查询odbusTCP 事件标识符
    EXAT退出AT 指令模式HEARTINFO设置/查询自定义心跳包信息(ASCII)NETHEAD设置/查询网络T指令头
    RESTORE恢复出厂设置HEARTINFONEW设置/查询自定义心跳包信息(16 进制)MQTTMODE设置/查询QTT模式
    UART设置/查询串口参数HEARTM设置/查询心跳包时间MQTT_ADDRESS设置/查询物联网平台地址、端口
    UARTCLR设置/查询模块连接前是否清除串口缓存SHORTM设置/查询短连接时间MQTT_CONNECT设置/查询接入物联网平台的参数
    IMEI查询模块IMEICREG查询是否注册到网络MQTT_SUBSCRIBE_TOPIC设置/查询订阅消息的topic、消息等级
    LINKSTA查询SOCK 连接状态CSQ查询信号强度MQTT_PUBLISH_TOPIC设置/查询发布消息的topic、消息等级
    LINKSTA1查询SOCK1 连接状态CPIN查询IM 卡状态MQTT_ALIAUTH设置/查询阿里云三要素
    SOCK设置/查询SOCK 参数POTOCOL查询设置是否开启协议传输APN查询设置APN信息
    SOCK1设置/查询SOCK1 参数UARTEX设置/查询串口参数9600,8,N,1)APN_ENABLE查询设置APN使能
    REGMOD设置/查询注册包模式ICCID查询SIM卡的ICCID 号(集成电路卡识别码)
    1. 注:如果AT指令后面有“=”,那么“=”后面就是要配置的参数

 

 

 

 

2.4G模块AT指令测试

0、指令格式和指令错误码:

  1. AT指令的格式如上,其中CMD就是我们的指令字符;[op]就是等号,用来配置参数。
  2. <CR><LF>,其中CR(carriage return)表示回车,LF(line feed)表示换行。
  3. 无效的AT指令有5种。
  4. 成功的AT指令发送后,4G模块一般会显示"+OK",如果4G模块对AT指令的响应信息中有“=”,那么“=”后面的就是查询到的信息。

1、进入AT指令模式:不同于ESP8266模块一上电就进入AT指令模式,4G模块上电后默认是处于透传工作模式(默认是没有进入AT指令模式的),我们进入AT指令模式需要两步。

  1. 发送“+++”指令(不发送新行)
  2. 在发送“+++”指令的3s内发送除了重启指令之外的任意AT指令,才能完全进入AT指令模式,比如发送AT+CSQ

2、查看电话卡的ICCID:AT+ICCID

  • 我的4G模块响应的是:“+OK=89860085111556043395”

3、修改4G模块波特率:

  1. 发送指令:AT+UART=9600,NONE  (9600代表波特率,NONE代表没有奇偶校验位,EVEN是偶校验,ODD是奇校验)
    1. 设置成功,4G模块会响应“+OK”
  2. 成功后立即重启:AT+REBT (重启以后关闭PC上的串口助手,然后修改波特率为9600即可,此时4G模块重新进入透传工作模式)
    1. 重启成功,4G模块会响应“+OK”

局域网通信和公网通信:

  1. 局域网通信模式:我们之前在用ESP8266时,用的是局域网通信模式,我们将8266安置在51单片机上,让单片机和PC联入同一个局域网,局域网随机给这两个设备分配IP地址,我们让8266以客户端模式或者以服务器模式工作,通过建立起客户端与服务器的连接,最后51单片机就能与PC在特定的连接通道上实现数据的交互。
  2. 公网通信模式:公网通信没办法识别局域网的IP地址(因为世界上有很多相同的IP地址,比如有很多个192.168.252.201),这时候需要将我们的PC的IP地址映射成公网的IP地址,专门的名词称为“内网IP穿透”,内网穿透能够为局域网的设备提供一个外网可访问的地址和端口。
  3. 借助的工具:“花生壳”
    1. 对于普通的应用场景和学习来说,花生壳就够用了,下载方式是百度进入花生壳官网。
    2. 体验版就是限制了带宽和每个月的流量。

 PC上的公网通信测试

  1. 先在PC上打开一个网络调试助手,建立一个局域网下的TCP服务器(设置本地主机地址和端口号)
  2. 运行花生壳软件,在内网穿透 / 自定义映射中进行映射(设置内网主机和内网端口),保存后会显示连接成功。 
  3. 再在PC上打开另一个网络调试助手,建立一个局域网下的TCP客户端,连接刚才映射的TCP服务器(设置本地主机地址和远程主机地址,其中远程主机地址就是刚才花生壳软件生成的IP地址)
  4. 让客户端与服务器进行交互。

 

  • 此时对于TCP服务器来说,它不区分自己是局域网下的设备还是公网下的设备,也就是说相对于局域网通信来说,这个TCP服务器多了一条走公网的数据通信途径。
  • 如果家里的路由器买的比较贵,具备内网穿透功能,可以直接设置,将设备的IP地址和端口号设置成外网可访问的地址和端口。
  • TCP客户端每次连接TCP服务器时,TCP客户端后面的端口号是随机分配的。
  • 在建立TCP服务器后,如果让电脑断开局域网络,这个TCP服务器实际上还存在,但是已经不能从TCP客户端接受信息了,所以提前测试TCP服务器能否接收到透传信息是很有必要的。

4、查询心跳包信息:有两种指令可用。初次查询到的是默认的心跳包信息。

  1. 方式1:AT+HEARTINFO
    • 我的4G模块响应的是“+OK=Smart-H”
  • 方式2:AT+HEARTINFONEW
    • 我的4G模块响应的是“+OK=1,Smart-H” (这里1表示心跳包数据的格式是ASCII码,0代表HEX格式)

5、设置心跳包信息:

  1. 方式1:AT+HEARTINFO=<data>  (参数data是40字节以内的ASCII码心跳包数据)
    1. 设置成功,4G模块会响应“+OK”
  2. 方式2:AT+HEARTINFONEW=<type>,<data>  (参数type有两种可选,1表示ASCII码格式,0代表HEX格式,当心跳包类型为ASCII 码时,data是40 字节之内的数据,当心跳包类型为EX 时,内容必须是合法的HEX 格式且长度必须是偶数。)
    1. 心跳包我设置成了c52NO1,设置成功,4G模块会响应“+OK”

6、查询心跳包时间间隔:AT+HEARTM

  • 查询成功,4G模块会响应“+OK=<time>”  (参数time的范围在0~65535s,其中0代表关闭)

7、设置心跳包时间间隔:AT+HEARTM=<time>   (参数time的范围在0~65535s,其中0代表关闭)

  • 我这里设置了3s,设置成功,4G模块会响应“+OK”

8、设置预连接的Socket服务器:AT+SOCK=TCPC,73n8f47741.goho.co,32864 (其中73n8f47741.goho.co是公网的IP地址,由花生壳获得,32864是动态端口号)

  • 配置成功,4G模块会响应“+OK”
  • 注意:4g模块的AT指令模式是纯配置,至于这种配置是否生效,还要重启4g模块才能确定,所以现在只是预连接阶段,并不是真正代表连接上服务器,此时4g模块也总是在响应“+OK”

9、配置成功,重启生效:AT+REBT

  • 先配置,重启后才运行,不重启的话就一直在AT指令模式,重启后才能进入透传工作模式。
  • 重启之后,检查一下4G模块的指示灯,第四盏黄色的灯亮说明SIM卡初始化正常,第一盏绿色的灯亮说明4G模块已经连接上公网下的TCP服务器。一切就绪后(这个过程可能有点慢),就能在PC上的网络调试助手上看到发送来的心跳包以及透传数据。

预热(4g小车):

  • 目标:手机app控制小车运动
  • 特点:手机用4G,51单片机也用4G。4G模块比蓝牙和wifi模块牛逼,因为突破了地域的限制,可以远距离传送。
  • 方法:自己用Linux搭建一个TCP服务器,用于数据的自动中转,当手机app发送指令给TCP服务器,TCP服务器再自动将数据中转给4G模块,实现手机控制小车。

3.4G网络控制LED

1、确认单片机要发送的AT指令:

  1. 进入AT指令模式(两步)
  2. 查询SIM卡的ICCID号
  3. 设置心跳包信息
  4. 设置心跳包时间间隔
  5. 连接Socket服务器
  6. 重启生效
  7. 波特率是提前用电脑通过AT指令给4g模块配置好的,用9600

2、单片机处理4g模块响应信息:

AT指令配置成功的关键字眼及标志位

进入AT指令模式

设置心跳包信息

设置心跳包时间间隔

连接Socket服务器

重启生效

成功:“+OK”成功:“+OK”成功:“+OK”成功:“+OK”成功:“+OK”
成功标志位: AT_OK_Flag成功标志位: AT_OK_Flag成功标志位: AT_OK_Flag成功标志位: AT_OK_Flag成功标志位: AT_OK_Flag
透传有效指令的关键字眼灯控指令
亮灯:“:op”
灭灯:“:cl”

3、通过硬件来窥探4g模块配置:无,配置阶段都响应+OK,没有实际意义。

4、白盒测试和黑盒测试不一致:

    用如下第一个代码(实际上是不可行的)进行白盒测试,尽管通过了白盒测试(用串口模拟发送4g模块原本对AT指令的响应信息后,51单片机发送下一条AT指令,4g模块都有反应),但是用这个代码进行黑盒测试时,发现了如下问题:

  1. 单片机无法正常发送AT指令,导致程序卡死在空循环体。
  2. 4g模块不依赖于单片机指令,自动去生效上一次用PC配置好的AT指令,最后两盏灯都亮。第一盏灯亮后,TCP服务器能够接收到4g模块的心跳包。
  3. 无法用透传控制led。

分析可能的原因

  • 白盒测试正常,说明不是“重新上电后,4g模块在生效上次的配置信息的时候拒绝接受信息,最终导致51单片机卡死在空循环体中”导致的。
  • 可能的原因是:重新上电后,4g模块默认处在透传工作模式,会自动去生效上次用PC配置好的AT指令。但我们的程序强行让4g模块进入AT指令模式,所以我们可以在白盒测试时观察到4g模块的响应信息,但是在黑盒测试中,4g模块这部分的响应信息貌似没有通过串口被51单片机接收。

不可行的代码:4g控制led

  • 代码心得
    • 4g模块上电后的初始化时间有点久的,所以我这里给它了3s的上电时间(3s也是个大概,因为4g模块上电后四盏指示灯都会亮,初始化完毕后指示灯才灭掉,所以最准确的是看4g模块上所有指示灯熄灭的时间)。如果不给上电初始化的延时,那么在白盒测试时就无法在串口助手上看见4g模块的任何响应信息。这是因为这部分指令因为4g模块还在做上电初始化而被忽略了。
    • 不用让单片机发送心跳包,因为4g模块自己会自动发送。
  1. 思路:
    宏定义:
    1. 定义符号常量len,用它代表用于接收SBUF中缓冲字符串的全局数组的长度: #define len 12
    全局变量:
    1. sfr指令直接找到AUXR寄存器: sfr AUXR = 0X8E;    //因为AUXR没有在reg52.h中声明
    2. “设置4g模块进入AT指令模式的操作”: char _4g_ATmode1[] 	= "+++";char _4g_ATmode2[] 	= "AT+CSQ\r\n";
    3. “设置4g模块心跳包数据的AT指令”: char _4g_heartInfo[] = "AT+HEARTINFONEW=1,c52NO1\r\n";
    4. “设置4g模块心跳包时间间隔的AT指令”: char _4g_heartTime[] = "AT+HEARTM=3\r\n";
    5. “设置4g模块重新上电后准备连接的公网TCP服务器的AT指令”: code char _4g_linkSocket[] = "AT+SOCK=TCPC,73n8f47741.goho.co,32864\r\n";
    6. “设置4g模块重新上电的AT指令”: char _4g_restart[] = "AT+REBT\r\n"
    7. 定义wifi模块响应AT指令"OK"的标志位: char AT_OK_Flag = 0;
    //AT_OK_Flag的传递路线为:SBUF ——> 串口中断(中断4)——> API2: _4gModule_Client_Config();
    8. 定义一个用于接收串口中缓冲区字符串的全局数组serial_buffer: char serial_buffer[len];  
    //serial_buffer的传递路线为:SBUF ——> 串口中断(中断4)——> 临时字符变量temp
    1. 一上电先让指示灯D5和D6灭: ledD5 = ledD6 = 1;
    2. 调用API1. 初始化串口: UartInit();
    3. 调用API5. 软件延时3s,给4g模块上电初始化预留时间: Delay1000ms();Delay1000ms();Delay1000ms();
    4. 调用API2. 配置4g模块并让其重新启动: _4gModule_Client_Config();
    5. while死循环,防止程序自行结束
    中断: 
    中断4: 封装串口中断的中断服务程序, void Uart_Routine()   interrupt 44.1 定义一个静态全局区的静态变量,用来表示数组serial_buffer的下标: static int i = 0;4.2 定义一个临时字符变量temp,用于检测关键字眼,保证我们的字符串是从字符数粗的第0位开始存放的。char temp;4.3 中断处理程序中,对于接收中断的响应,判据是RI == 14.3.1 在接受到1字节数据后,程序复位RI: RI = 0;4.3.2 串口缓冲区接收到的字符先存放在临时变量temp中: temp = SBUF;4.3.3 从数据缓冲寄存器SBUF中读到字符后,根据我们提前设计好的关键字眼,关心四件事:"+OK"的'O'、 "cmd:op"的':',判据是temp=='O' || temp==':'4.3.3.1 如果是,那么需要从头开始存放: i = 0;4.3.3.2 否则,那么什么也不做,继续往下执行4.3.4 将temp的值保存在数组serial_buffer的第i个元素中:serial_buffer[i] = temp;4.3.5 偏移数组下标: i++;4.3.6 判断字符数组serial_buffer是否存满了,判据是 i == len //内在逻辑:由于serial_buffer长度的限制,当字符串超过len时,我们需要覆盖掉原先的字符4.3.6.1 如果是,那么需要从头开始存放: i = 0;4.3.6.2 否则,那么什么也不做,继续往下执行4.3.7 通过字符数组的第0位和第1位捕捉关键字眼,判断wifi模块是否响应"OK",判据是serial_buffer[0]=='O' && serial_buffer[1]=='K'4.3.7.1 如果是,令标志位为1: AT_OK_Flag = 1;有效指令后清空字符数组: memset(serial_buffer,'\0',len);4.3.7.2 否则,那么什么也不做,继续往下执行4.3.8 通过字符数组的第0位和第2位捕捉关键字眼,判断wifi模块是否收到透传数据":open",判据是serial_buffer[0]==':' && serial_buffer[1]=='o' && serial_buffer[2]=='p'4.3.8.1 如果是,点亮D5: ledD5 = 0;有效指令后清空字符数组: memset(serial_buffer,'\0',len);4.3.8.2 否则,如果wifi模块收到透传数据"+IPD,0,n:close"熄灭D5: ledD5 = 1;有效指令后清空字符数组: memset(serial_buffer,'\0',len);4.4 中断处理程序中,对于发送中断的响应,判据是TI == 1暂时不做任何事情
    /* 一级函数:f1、f2、f4、f5 */
    f1. 封装初始化串口的API: void UartInit(void);f1.1 禁用ALE信号: AUXR = 0X01;f1.2 让串口以方式1工作(8位UART,可变波特率),并让REN使能允许串口接收: SCON = 0x50;f1.3 让定时器1以8位重载工作模式工作:TMOD &= 0xDF;TMOD |= 0x20;f1.4 根据波特率为9600,波特率不翻倍,设置定时器1的初值:TH1 = 0xFD;TL1 = 0xFD;f1.5 定时器开始数数: TR1 = 1;f1.6 开启串口中断:EA = 1;ES = 1;
    2. “设置4g模块进入AT指令模式的操作”: char _4g_ATmode1[] 	= "+++";char _4g_ATmode2[] 	= "AT+CSQ\r\n";
    3. “设置4g模块心跳包数据的AT指令”: char _4g_heartInfo[] = "AT+HEARTINFONEW=1,c52NO1\r\n";
    4. “设置4g模块心跳包时间间隔的AT指令”: char _4g_heartTime[] = "AT+HEARTM=3\r\n";
    5. “设置4g模块重新上电后准备连接的公网TCO服务器的AT指令”: code char _4g_linkSocket[] = "AT+SOCK=TCPC,73n8f47741.goho.co,32864\r\n";
    6. “设置4g模块重新上电的AT指令”: char _4g_restart[] = "AT+REBT\r\n"
    f2. 封装配置wifi模块以客户端模式工作的API: void wifiModule_Server_Config();f2.1 设置4g模块进入AT指令模式:调用API4,通过串口发送对应AT指令: sendString(_4g_ATmode1);调用API5. 软件延时1s: Delay1000ms();调用API4,通过串口发送对应AT指令: sendString(_4g_ATmode2);空循环体等待,直到wifi模块响应"OK": while(!AT_OK_Flag);为了不影响下一个条指令响应,复位标志位: AT_OK_Flag = 0;f2.2 设置4g模块心跳包数据:调用API4,通过串口发送对应AT指令: sendString(_4g_heartInfo);空循环体等待,直到wifi模块响应"OK": while(!AT_OK_Flag);为了不影响下一个条指令响应,复位标志位: AT_OK_Flag = 0;f2.3 设置4g模块心跳包时间间隔:调用API4,通过串口发送对应AT指令: sendString(_4g_heartTime);空循环体等待,直到wifi模块响应"OK": while(!AT_OK_Flag);为了不影响下一个条指令响应,复位标志位: AT_OK_Flag = 0;f2.4 设置4g模块重新上电后准备连接的公网TCP服务器:调用API4,通过串口发送对应AT指令: sendString(_4g_linkSocket);空循环体等待,直到wifi模块响应"OK": while(!AT_OK_Flag);为了不影响下一个条指令响应,复位标志位: AT_OK_Flag = 0;f2.5 设置4g模块重新上电,让上述指令生效:调用API4,通过串口发送对应AT指令: sendString(_4g_restart);空循环体等待,直到wifi模块响应"OK": while(!AT_OK_Flag);
    f4. 封装给PC发送字符串的API: void sendString(char *str); //形参是字符串的地址f4.1 定义一个字符指针变量p用来保存字符串首地址: char *p = str;f4.2 while循环,控制循环的变量是*p,当*p != '\0' 时,进入循环,进行单个字符的发送f4.2.1 通过指针间接访问字符串字符,再调用API3. 发送单个字符: sendByte(*p);f4.2.2 修改循环变量p的值,让指针p偏移: p++;
    f5. 封装软件延时1s的API,用于每隔1秒发送心跳包,以及串口初始化后的短暂休眠: void Delay1000ms();
    /* 二级函数:f3 */
    f3. 封装定时给PC发送一个字符的API: void sendByte(char data_msg);  //形参是字符值f3.1 往SBUF寄存器中写入字符data_msg: SBUF = data_msg;f3.2 根据串口发送中断触发位TI,利用空循环体暂停程序: while(!TI);f3.3 程序复位TI: TI = 0;

  2. 代码:
    #include "reg52.h"
    #include "intrins.h"
    #include <string.h>#define len 12
    sfr AUXR = 0x8E;
    char serial_buffer[len];
    char _4g_ATmode1[] 			= "+++";
    char _4g_ATmode2[] 			= "AT+CSQ\r\n";
    char _4g_heartInfo[] 		= "AT+HEARTINFONEW=1,c52NO1\r\n";
    char _4g_heartTime[] 		= "AT+HEARTM=3\r\n";
    code char _4g_linkSocket[]  = "AT+SOCK=TCPC,73n8f47741.goho.co,32864\r\n";
    char _4g_restart[] 			= "AT+REBT\r\n";
    char AT_OK_Flag = 0;			//关键字眼+OK的标志位,用1代表AT指令响应成功,0代表AT指令响应失败/* API1. 初始化串口 */
    void UartInit(void); 
    /* API2. 配置4g模块以客户端模式工作 */
    void _4gModule_Client_Config(); 
    /* API3. 通过串口给PC发送一个字符 */
    void sendByte(char data_msg); 
    /* API4. 通过串口给PC发送一个字符串 */
    void sendString(char *str); 
    /* API5. 用于串口初始化后的短暂休眠 */
    void Delay1000ms();void main()
    {ledD5 = ledD6 = 1;//灭状态灯UartInit();Delay1000ms();//给4g模块上电时间Delay1000ms();Delay1000ms();_4gModule_Client_Config();while(1){}
    }void Uart_Routine() interrupt 4
    {static int i = 0;//静态变量,被初始化一次char temp;/* 中断处理程序中,对于接收中断的响应 */if(RI)//中断处理函数中,对于接收中断的响应{RI = 0;//清除接收中断标志位temp = SBUF;if(temp == 'O' || temp == ':'){i = 0;}serial_buffer[i] = temp;i++;if(i == len) i = 0;//4g模块响应值的判断if(serial_buffer[0] == 'O' && serial_buffer[1] == 'K'){AT_OK_Flag	= 1;memset(serial_buffer, '\0', len);}//灯控指令if(serial_buffer[0] == ':' && serial_buffer[1] == 'o' && serial_buffer[2]=='p'){ledD5 = 0;//点亮D5memset(serial_buffer, '\0', len);}else if(serial_buffer[0] == ':' && serial_buffer[1] == 'c' && serial_buffer[2]=='l'){ledD5 = 1;//熄灭D5memset(serial_buffer, '\0', len);}}/* 中断处理程序中,对于发送中断的响应 */if(TI == 1){// 暂时不做任何事情}
    }void UartInit(void)		//9600bps@11.0592MHz
    {AUXR = 0x01;SCON = 0x50;	//8位UART,允许串口接收TMOD &= 0xDF;TMOD |= 0x20;	//定时器8位重载工作模式TH1 = 0xFD;TL1 = 0xFD;		//9600波特率初值TR1 = 1;		//启动定时器EA = 1;ES = 1;			//开启串口中断
    }void _4gModule_Client_Config()
    {sendString(_4g_ATmode1);Delay1000ms();sendString(_4g_ATmode2);while(!AT_OK_Flag);AT_OK_Flag = 0;sendString(_4g_heartInfo);while(!AT_OK_Flag);AT_OK_Flag = 0;	sendString(_4g_heartTime);while(!AT_OK_Flag);AT_OK_Flag = 0;	sendString(_4g_linkSocket);while(!AT_OK_Flag);AT_OK_Flag = 0;	sendString(_4g_restart);while(!AT_OK_Flag);
    }void sendByte(char data_msg)
    {SBUF = data_msg;while(!TI);TI = 0;
    }void sendString(char *str)
    {char *p = str;while(*p != '\0'){sendByte(*p);p++;}
    }void Delay1000ms()		//@11.0592MHz
    {unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
    }

正确的代码:4g控制led

  1. 思路:删去上面的与AT指令有关的语句和函数、删去等待4g模块初始化完成的那3s的软件延时。
  2. 代码:
    #include "reg52.h"
    #include <string.h>#define len 12
    sfr AUXR = 0x8E;
    sbit ledD5 = P3^7;
    char serial_buffer[len];/* API1. 初始化串口 */
    void UartInit(void); void main()
    {ledD5 = 1;//灭状态灯UartInit();while(1){}
    }void Uart_Routine() interrupt 4
    {static int i = 0;//静态变量,被初始化一次char temp;/* 中断处理程序中,对于接收中断的响应 */if(RI)//中断处理函数中,对于接收中断的响应{RI = 0;//清除接收中断标志位temp = SBUF;if(temp == ':'){i = 0;}serial_buffer[i] = temp;i++;if(i == len) i = 0;//灯控指令if(serial_buffer[0] == ':' && serial_buffer[1] == 'o' && serial_buffer[2]=='p'){ledD5 = 0;//点亮D5memset(serial_buffer, '\0', len);}else if(serial_buffer[0] == ':' && serial_buffer[1] == 'c' && serial_buffer[2]=='l'){ledD5 = 1;//熄灭D5memset(serial_buffer, '\0', len);}}/* 中断处理程序中,对于发送中断的响应 */if(TI == 1){// 暂时不做任何事情}
    }void UartInit(void)		//9600bps@11.0592MHz
    {AUXR = 0x01;SCON = 0x50;	//8位UART,允许串口接收TMOD &= 0xDF;TMOD |= 0x20;	//定时器8位重载工作模式TH1 = 0xFD;TL1 = 0xFD;		//9600波特率初值TR1 = 1;		//启动定时器EA = 1;ES = 1;			//开启串口中断
    }


http://www.ppmy.cn/news/71903.html

相关文章

【数据结构】二叉树进阶题目练习

文章目录 二叉树创建字符串二叉树的分层遍历1二叉树的分层遍历2给定一个二叉树, 找到该树中两个指定节点的最近公共祖先二叉树搜索树转换成排序双向链表二叉树展开为链表根据一棵树的前序遍历与中序遍历构造二叉树根据一棵树的中序遍历与后序遍历构造二叉树二叉树的前序遍历 非…

Hadoop学习全程记录——hive入门

hive是Facebook的产品&#xff0c;很不错。 官方文档&#xff1a;http://wiki.apache.org/hadoop/Hive/GettingStarted有很详细说明。 基本上根据文档能对hive快速入门。在使用过程中可能会出现以下问题&#xff1a; 当执行下面命令时&#xff1a; Java代码 $ $HIVE_HOME/bin…

虚拟机虚拟环境中安装dirmap并更改Bin目录

在 Red Hat Enterprise Linux 8 中安装 dirmap 可以按照以下步骤进行&#xff1a; 激活虚拟环境&#xff1a;打开终端或命令提示符&#xff0c;并导航到虚拟机的工作目录。输入命令来激活虚拟环境。具体的命令取决于您使用的虚拟环境管理工具&#xff0c;例如 virtualenv 或 c…

香农信息论的基本理论探究

摘要&#xff1a;信息是自从人类出现以来就存在于这个世界上了&#xff0c;天地万物&#xff0c;飞禽走兽&#xff0c;以及人类的生存方式都离不开信息的产生和传播。人类每时每刻都在不停的接受信息&#xff0c;传播信息&#xff0c;以及利用信息。从原来的西汉时期的造纸&…

云厂商纷纷降价开启新一轮价格大战,行业竞争加剧未来何从?

5月16日晚间&#xff0c;腾讯云和移动云两大云服务商相继宣布对旗下多款核心产品进行降价。其中&#xff0c;腾讯云降价幅度最高达40%&#xff0c;移动云部分产品直降60%。 而就在20天前4月26日阿里云2023合作伙伴大会上&#xff0c;阿里巴巴CEO张勇率先宣布启动“史上最大规模…

基于SpringBoot的人事管理系统的设计与实现

背景 人事管理管理方面的任务繁琐,以至于公司每年都在人事管理这方面投入较多的精力却效果甚微,人事管理系统的目标就是为了能够缓解人事管理工作方面面临的压力,让人事管理方面的工作变得更加高效准确。 系统架构 考虑到实际生活中在人事管理方面的需要以及对该系统认真的分…

MNN-YOLOv8 c++ 推理+交叉编译

使用 https://github.com/wangzhaode/yolov8-mnn.git 进行图片检测推理 1,下载MNN 2,ubuntu编译MNN cd MNN\ mkdir build && cd build && cmake .. -DMNN_BUILD_OPENCV=ON -DMNN_IMGCODECS=ON && make -j8 3,新建CLion共享动态库工程 新建src,includ…

RK系列(RK3568)SATA MSATA调试和无法识别问题

SOC:RK3568 Linux:kernel-4.19 Android:12 芯片资源介绍 RK3568 资源 速率 支持 PM 芯片扩展 PHY 复用 SATA0