• 联盛德W801系列9-wifi和4G模块(air724ug)并存使用MQTT总结


    第一次在产品中使用iot功能,完全没有经验,可能会存在很多bug,请各位大侠不吝赐教,指点一二。

    1.air724ug-AT版本的使用

    1.1 air724简介

    我这次使用的是合宙的air724ug模组,成品是飞思创的FS-MCore-A724UG。
    实物图片:
    在这里插入图片描述
    这个成品有2个软件版本:

    1.(AT)
    AT版本是直接使用合宙的AT指令。
    2.(YunDTU)
    YunDTU版本功能完善,覆盖绝大多数应用场景,用户只需通过简单的配置,即可实现产品联网。支持 TCP Client、UDP Client、MQTT、HTTP、阿里云、OneNET、百度云、腾讯云和华为云等多种工作模式,并支持 HTTP、FTP 他升级以及 FOTA 自升级。
    以MQTT应用为例,说明一下如何通过简单配置,使用YunDTU功能:
    下面的配置界面提供了MQTT通信所需要的全部配置,不过只能有一个订阅主题和一个发布主题,配置好之后,上电就会自动连接MQTT服务器,此时设备只管接收消息和发布消息。
    在这里插入图片描述

    我用的是AT版本。在优信电子购买,店家提供了详细的资料,包括STM32使用AT指令的例程。

    1.2 模块上电上报信息

    模块插上中国移动SIM卡,通电后,通过SIM卡,注册网络后会从网络自动获取并激活一个PDP上下文。下面是串口观察到的打印信息:
    在这里插入图片描述

    1.3 AT指令使用流程

    AT指令必须以回车符(0x0D)结束,以回车+换行(0xA)结束也行。
    在这里插入图片描述

    1.4 MQTT相关的AT指令中关于双引号"的处理

    多数指令关于双引号是可有可无的,例如设置订阅主题的指令:
    可以有双引号括住订阅主题:

    AT+MSUB="/subtop/1",0
    
    • 1

    也可以不用双引号:

    AT+MSUB=/subtop/1,0
    
    • 1

    唯一的例外就是发布消息的指令 AT+MPUB 中的消息部分,一定要双引号。
    在这里插入图片描述
    我们一般发送消息使用json格式,比如{“name”:“tom”},这个消息放到AT指令该怎样表示呢?一般的话,我们用C语言字符串表达方法是这样(发布主题可以不用双引号):

    char * strPub="AT+MPUB=/pubtopic/1,0,0,\"{\"name\":\"tom\"}\"\r\n";
    
    • 1

    上面的表达方法是无法正确被AT指令解析的。C语言的双引号使用转义字符反斜杠+双引号来表示,json内嵌的双引号只能使用反斜杠字符+十六进制表示,而C语言字符串中反斜杠需要两个反斜杠表示。
    在这里插入图片描述
    上面4个红框要被 \\22 替代,要写成下面这样,才能准确地被AT指令正确解析:

    char * strPub="AT+MPUB=/pubtopic/1,0,0,\"{\\22name\\22:\\22tom\\22}\"\r\n";
    
    • 1

    2.通过AT指令控制air724的代码详解

    2.1 发送AT指令的函数

    /** 发送AT指令并等待应答
     *
     * 指定尝试的次数和每次发送后等待应答的时间
     * 
     * @param tryTimes 	尝试次数
     * @param cmdStr 	AT命令字符串
     * @param replyStr 	期望应答字符串
     * @param waitTime 	每次发送后等待应答的时间
     *
     * @retval 0-没有接收到期望的字符串
     * @retval 1-成功接收到期望的字符串
     */
    int		SendATCmdAndWaitReply(int tryTimes,const char * cmdStr, const char* replyStr,int waitTime)
    {
    	int rx_len,ret;
    	u32	lastTime;
    	//	1.尝试的次数
    	for(int i=0;i<tryTimes;i++){
    		if(cmdStr != NULL)		
    			tls_uart_write(LTE_4G_COM,(u8 *) cmdStr,strlen(cmdStr));
    		
    		//	2.记录发送时的时间戳,并做100ms的延时
    		lastTime = xTaskGetTickCount();
    		vTaskDelay(50);  //	一个时间片是2ms	,这里就是100ms	
    		do{
    			rx_len = tls_uart_try_read(LTE_4G_COM,1);
    			vTaskDelay(10);
    			if(rx_len > 0){
    				rx_len = tls_uart_try_read(LTE_4G_COM,1);
    				memset(demo_uart3->rx_buf,0,100);
    				
    				//	如果接收到的数据量大于接收缓存 (256 bytes),数据丢弃
    				//	因为串口中断的缓存有4K Byte,但是demo_uart3->rx_buf的空间只给了256 Byte
    				if(rx_len >= DEMO_UART3_RX_BUF_SIZE){
    					do{
    						rx_len = 200;
    						ret = tls_uart_read(LTE_4G_COM, (u8 *) demo_uart3->rx_buf, rx_len);
    					}while(ret > 100);
    					continue;
    				}
    			//	3.判断接收的数据是否有期望的字符串	
    				ret = tls_uart_read(LTE_4G_COM, (u8 *) demo_uart3->rx_buf, rx_len); 
    				printf("%s\r\n",demo_uart3->rx_buf);
    				if(ret > 2){
    					demo_uart3->rx_buf[ret] = 0;
    					if(strstr(demo_uart3->rx_buf,replyStr) != NULL){
    						printf("find %s\n",replyStr);
    						return 1;						
    					}
    				}
    			}
    		//	4.在等待的时间内,每20ms查询一次串口;超时则重新发送AT指令
    		}while((xTaskGetTickCount()-lastTime )< waitTime);
    		
    	}
    	//	5.如果执行到这里,说明失败了
    	printf("wait %s fail\n",replyStr);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    2.2 控制air724模块的状态机流程

    在这里插入图片描述
    状态机的状态码 :

    enum _Stat_4G{
    	Stat4G_WaitReady=0,
    	Stat4G_CloseEcho=1,		//	1.关闭回显命令
    	Stat4G_CGREG,			// 	2.查询网络状态
    	Stat4G_CGATT,			//	3.查询是否附着上数据网络
    	Stat4G_CSTT,			//	4.设置接入点 APN,可无参数
    	Stat4G_CIICR,			//	5.激活移动场景
    	Stat4G_CIFSR,			//	6.获取IP地址
    	
    	Stat4G_Mconfig,			//	7.设置MQTT接入密码
    	Stat4G_Mipstart,		//	8.设置MQTT服务器IP 或域名
    	Stat4G_Mconnect,		//	9.设置 心跳时间
    	
    	Stat4G_Msub,			//	10.设置 订阅主题
    	Stat4G_MQuerySubMsg,	//	11.在这里等待消息,死循环
    	Stat4G_4GIdle,			//	12.有了wifi,4G关闭电源
    	Stat4G_4GPowerReset,	//	13.出现错误,关闭电源50ms后再次上电,进入重连状态   WaitReady
    	
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    状态机相关源码(使用W801的串口3控制4G模块):

    const char * StrNect="NECT";		//	命令 ipstart 的应答
    const char * StrAct="ACK";			//	命令 connect 的应答    订阅消息成功后的应答
    const char * StrReady="READY";
    const char * StrSMS="SMS";
    const char * StrOK="OK";
    const char * Strdot=".";
    const char * StrATE0="ATE0\r\n";
    const char * StrGREG="AT+CGREG?\r\n";	// 	2.查询网络状态
    const char * StrGATT="AT+CGATT?\r\n";//	3.查询是否附着上数据网络
    const char * StrCSTT="AT+CSTT\r\n";	//	4.设置接入点 APN,可无参数
    const char * StrIICR="AT+CIICR\r\n";	//	5.激活移动场景
    const char * StrIFSR="AT+CIFSR\r\n";
    const char * StrMconnectQry="AT+MCONNECT=?\r\n";
    stat4G = Stat4G_WaitReady;
        for (;;)
        {
    		ticks20ms++;
    		if(ticks20ms > 50*20){
    			ticks20ms = 0;
    		//	0.不知道4G模块有没有MQTT的心跳,这里使用查询MQTT状态来模拟心跳
    			if(Stat4G_MQuerySubMsg == stat4G){
    				tls_uart_write(LTE_4G_COM,(u8 *) StrMconnectQry,strlen(StrMconnectQry));				
                    printf("PING\n");
    			}
    		}
    		//	1.	20ms运行一次
    		vTaskDelay(10);  
    		//	有2种消息
    		if(xQueueReceive(demo_uart3->demo_uart_q,&(cmdmsg),0)){
    			//	消息1.  4G模块处于断电状态,如果 wifi断开了,重连一次失败,会发送重启4G的消息
    			if((cmdmsg == DEMO_MSG_4G_RESTART)){			
    				tls_gpio_write(POWER_4G_CTRL_PIN,1);
    				stat4G = Stat4G_WaitReady;
    			//	消息2.	本来4G模块处于正常通信中 ,wifi连上网络了,优先使用wifi,要断开4G电源,任务进入空闲等待
    			}else if(cmdmsg == DEMO_MSG_4G_ENTER_IDLE){
    				tls_gpio_write(POWER_4G_CTRL_PIN,0);
    				stat4G = Stat4G_4GIdle;
    			}
    		}
            switch ( stat4G)
            {
            case Stat4G_WaitReady:
                    printf("wait %s\n",StrSMS);
    			if(SendATCmdAndWaitReply(60,NULL,StrSMS,1000)){
    				stat4G++;
    				vTaskDelay(5*1000);
    			}else{
    				stat4G = Stat4G_4GPowerReset;				
    			}  
    
            break;
            case Stat4G_CloseEcho://	1.关闭回显命令
                    printf("StrATE0\n");
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrATE0,StrOK,500)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
            break;
    		
            case Stat4G_CGREG:// 	2.查询网络状态 --OK
                    printf("%s\n",StrGREG);
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrGREG,StrOK,500)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
            break;
            case Stat4G_CGATT:	//	3.查询是否附着上数据网络
                    printf("%s\n",StrGATT);
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrGATT,StrOK,500)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
            break;
            case Stat4G_CSTT:	//	4.设置接入点 APN,可无参数
                    printf("%s\n",StrCSTT);
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrCSTT,StrOK,500)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
            break;
            case Stat4G_CIICR:	//	5.激活移动场景 StrIICR
                    printf("%s\n",StrIICR);
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrIICR,StrOK,500)){
    				stat4G++;
    			}
            break;
            case Stat4G_CIFSR:	//	6.获取IP地址
                    printf("%s\n",StrIFSR);
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrIFSR,Strdot,500)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
            break;
    			
            case Stat4G_Mconfig:	//	7.设置MQTT接入密码
                    printf("set MQTT ID,pwd\n");
    			sprintf(Buf,StrMconfig,MAC2STR(g_macBuf));
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,Buf,StrOK,1000)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
                break;
            case Stat4G_Mipstart:	//	8.设置MQTT服务器IP 或域名
                    printf("set MQTT server\n");
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrMipstart,StrNect,1000)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
                break;
            case Stat4G_Mconnect:	//	9.设置 心跳时间
                    printf("set heart beat\n");
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,StrMconnect,StrAct,2000)){
    				stat4G++;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
                break;	
            case Stat4G_Msub:		//	10.设置 订阅主题
                    printf("set sub topic\n");
    				sprintf(Buf,StrMsubTop,MAC2STR(g_macBuf));
    			if(SendATCmdAndWaitReply(TRY_TIME_MAX,Buf,StrAct,1000)){
    				stat4G++;
    				g_internetStat = internetStat_4GConnect;
    			}else{
    				SendATCmdAndWaitReply(2,StrRESET,StrOK,200);
    				stat4G = Stat4G_WaitReady;
    			}
                break;
            case Stat4G_MQuerySubMsg:	//	查询消息 -- 大部分时间在这里		 				
    			rx_len = tls_uart_try_read(LTE_4G_COM,1);
    			if(rx_len > 0){
    				vTaskDelay(5);
    				rx_len = tls_uart_try_read(LTE_4G_COM,1);
    				//	如果接收到的数据量大于接收缓存 (256 bytes),数据丢弃
    				if(rx_len >= DEMO_UART3_RX_BUF_SIZE){
    					do{
    						rx_len = 200;
    						ret = tls_uart_read(LTE_4G_COM, (u8 *) demo_uart3->rx_buf, rx_len);
    					}while(ret > 100);
    					continue;
    				}
    				ret = tls_uart_read(LTE_4G_COM, (u8 *) demo_uart3->rx_buf, rx_len); 
    				demo_uart3->rx_buf[ret] = 0;
    					printf("Msg: %s\n",demo_uart3->rx_buf);
    				//	处理订阅数据
    					char *p = NULL;//, *q = NULL;
    					
    					p = strstr(demo_uart3->rx_buf, "byte,");
    					if (p != NULL)
    					{
    						p = p+5;					
    
    						rx_len  =p  - demo_uart3->rx_buf;	//	json数据首地址相对于整串数据的偏移量
    						if((ret -rx_len) < 50)	{			//	json数据的长度不应该大于50
    							mqtt_msg_process(p);
    						}
    					}
    					异常情况判断
    					p = strstr(demo_uart3->rx_buf, "ERROR");
    					if(p != NULL){
    						stat4G = Stat4G_4GPowerReset;
    						break;
    					}
    					p = strstr(demo_uart3->rx_buf, "DEACT");
    					if(p != NULL){
    						stat4G = Stat4G_4GPowerReset;
    						break;//
    					}
    			}
                break;
    		case Stat4G_4GIdle:			
    			break;
    		case Stat4G_4GPowerReset:			
    			tls_gpio_write(POWER_4G_CTRL_PIN,0);
    			vTaskDelay(25);  
    			tls_gpio_write(POWER_4G_CTRL_PIN,1);
    			stat4G = Stat4G_WaitReady;
    			break;
            default:
                break;
            }	
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197

    3. wifi和4G并存策略

    一开机,同时启动wifi连接(没有配过网就进入配网)和4G连接;如果wifi连上了,就切断4G电源;wifi断线后重连一次失败(观察过 W801从wifi断线到重连失败的时间约22秒),启动4G连接。

    3.1wifi断网后,启动4G模块,如果W801的MQTT已经启动,则要关闭W801的MQTT心跳:

    在下图的代码块1中,发送4G重启消息,关闭W801的MQTT心跳。
    在这里插入图片描述

    在状态机中查询到重启消息,4G模块通电并启动连接:

    代码块1:

        case NETIF_WIFI_JOIN_FAILED:
    		//	已经连上wifi后,又断网,重连1次都失败后,启动4G
    		if(internetStat_WifiConnect == g_internetStat){
    				g_internetStat = internetStat_TryWifi;				
    				if(demo_uart3 != NULL)
    					tls_os_queue_send(demo_uart3->demo_uart_q, (void *) DEMO_MSG_4G_RESTART, 0);
    					
    				if(flagMqttIsStart ){   
    					tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_STOP_TIMER, 0);	
    				}
    			printf("WIFI_JOIN_FAILED,start 4G\n");
    		}else{
    			printf("NETIF_WIFI_JOIN_FAILED,%d\n",failTimes);
    		}
            break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在《wm_mqtt_demo.c》的函数 mqtt_demo_task 增加 MQTT_DEMO_CMD_STOP_TIMER 的消息处理:

    static void mqtt_demo_task(void *p)
    {
        int ret;
        void *msg;
        struct tls_ethif *ether_if = tls_netif_get_ethif();
    
        if (ether_if->status)    {
            wm_printf("sta ip: %v\n", ether_if->ip_addr.addr);
            tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_START, 0);
        }
    
        for ( ; ; )
        {
            ret = tls_os_queue_receive(mqtt_demo_task_queue, (void **)&msg, 0, 0);
            if (!ret)
            {
                switch((u32)msg)
                {
                case MQTT_DEMO_CMD_START:
                    do  {
                        ret = mqtt_demo_init();
                        if (ret)
                            break;
                        tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_LOOP, 0);
                    }
                    while (0);
                    break;
                case MQTT_DEMO_CMD_HEART:
                    wm_printf("send heart ping\r\n");
                    mqtt_ping(&mqtt_demo_mqtt_broker);
                    break;
                case MQTT_DEMO_CMD_LOOP:
                    mqtt_demo_loop();
                    break;
    			case MQTT_DEMO_CMD_STOP_TIMER:
                    wm_printf("delete heart timer\r\n");
    				tls_os_timer_stop(mqtt_demo_heartbeat_timer);
                default:
                    break;
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    3.2 air724正常工作中,wifi连上网,需要关闭4G模块的电源,并使4G模块任务进入空转

    上图的代码块2就是wifi连上了网络产生的事件,此时要发送4G模块进入空转的消息 DEMO_MSG_4G_ENTER_IDLE 。并启动W801的MQTT任务(如果已经启动过,只需要重连MQTT)
    代码块2:

    	//	此时要切断4G电源,告诉4G任务进入等待
    		if((internetStat_4GConnect == g_internetStat)
    			||(internetStat_Try4G == g_internetStat)
    			||(internetStat_TryWifi == g_internetStat)
    			||(internetStat_WifiOneshot == g_internetStat)){
    			if(demo_uart3 != NULL)
    				tls_os_queue_send(demo_uart3->demo_uart_q, (void *) DEMO_MSG_4G_ENTER_IDLE, 0);
    			printf("JOIN_SUCCESS when 4G connect,4G off\n");
    		//	启动 wifi MQTT
    		if(flagMqttIsStart == 0){
    			mqtt_demo();
    			flagMqttIsStart = 1;
    		}else{
    			tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_START, 0);
    			printf("wifi mqtt retart\n");
    		}
    		g_internetStat = internetStat_WifiConnect;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4G模块的任务查询到 DEMO_MSG_4G_ENTER_IDLE 消息后,关闭4G电源,进入空转:
    在这里插入图片描述

    4.切断air724电源后,串口引脚会有漏电流,使得4G模块的电源灯微亮

    针对这种情况,切断4G模块电源后,要把串口引脚稍作处理,可以有2种方法:

    1.引脚配置为输出模式,然后输出低电平;
    2.配置为输出,浮空。

    不知道那种好,我使用了第二种。上图的程序修改为:

    		if(xQueueReceive(demo_uart3->demo_uart_q,&(cmdmsg),0)){
    			//	消息1.  4G模块处于断电状态,如果 wifi断开了,重连一次失败,会发送重启4G的消息
    			if((cmdmsg == DEMO_MSG_4G_RESTART)){	
    				wm_uart3_tx_config(WM_IO_PA_05);
    				wm_uart3_rx_config(WM_IO_PA_06);
    				tls_gpio_write(POWER_4G_CTRL_PIN,1);
    				stat4G = Stat4G_WaitReady;
    			//	消息2.	本来4G模块处于正常通信中 ,wifi连上网络了,优先使用wifi,要断开4G电源,任务进入空闲等待
    			}else if(cmdmsg == DEMO_MSG_4G_ENTER_IDLE){
    				tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPT5_GPIO);	//	关闭电源时,把IO口设置为输入高阻				
    				tls_gpio_cfg(WM_IO_PA_05, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
    				tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPT5_GPIO);	//	关闭电源时,把IO口设置为输入高阻				
    				tls_gpio_cfg(WM_IO_PA_06, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
    				tls_gpio_write(POWER_4G_CTRL_PIN,0);
    				stat4G = Stat4G_4GIdle;
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    C++——类与对象(上)
    牛客网之SQL100题(6)--时间、日期
    【ubuntu】 Linux(ubuntu)创建python的虚拟环境
    第P7周—咖啡豆识别(1)
    wps和office可以同时装吗?
    17.(开发工具篇Gitlab)如何在Gitlab配置ssh key
    find 命令这 7 种高级用法
    CSS(ellipsis) 用百分比宽度将字符串溢出部分显示为省略号
    FATFS介绍及相关参数计算
    selenium上传文件时打开指定本地文件路径
  • 原文地址:https://blog.csdn.net/hwd00001/article/details/127536019