一、模塊來源
模塊實物展示:
資料鏈接:https://docs.ai-thinker.com/nb-iot
工作電壓:3.0V-3.6V
工作電流:IMAX = 170mA
模塊尺寸:14.4 x 24.7 MM
控制方式:串口
三、移植過程
我們的目標是在立創·CW32F030C8T6開發板上能夠完成無線傳輸的功能。首先要獲取資料,查看數據手冊應如何實現,再移植至我們的工程。
3.1查看資料
NBIOT模塊使用網絡是通過物聯網卡提供流量,物聯網卡請自行到淘寶購買。
說明
使用GPS定位時,不可在室內,室內很難定位。需要到室外進行定位。
其余請參考官方資料:https://docs.ai-thinker.com/nb-iot
3.2引腳選擇
使用串口2(串口2-TX=PA2,串口2-RX=PA3)
模塊接線圖
3.3移植至工程
移植步驟中的導入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為bsp_ec01g.c與bsp_ec01g.h。這里不再過多講述,移植完成后面修改相關代碼。
在文件bsp_ec01g.c中,編寫如下代碼。
/* * Change Logs: * Date Author Notes * 2024-06-24 LCKFB-LP first version */ #include "bsp_ec01g.h" #include "stdio.h" #include "string.h" #include "stdlib.h" unsigned char EC01G_RX_BUFF[EC01G_RX_LEN_MAX]; unsigned char EC01G_RX_FLAG = 0; unsigned int EC01G_RX_LEN = 0; unsigned char EC01G_RX_API_FLAG = 0; /* ATrn //測試設備是否存在 返回OK說明存在 AT+CFUN=1 //關閉飛行模式 返回OK 說明成功 AT+CEREG? //判斷是否附著網絡成功 返回+CEREG: 0,1 說明附著網絡成功 AT+HTTPCREATE=0,"http://116.62.81.138:80" //設置命令創建一個 http 或 https 客戶端實例 返回OK成功 AT+HTTPCON=0 //連接0號實例服務器 返回OK成功 AT+HTTPSEND=0,0,78,"/v3/weather/now.json?key=SIwiiHEWo6pPD42S5&location=beijing&language=en&unit=c" //向0號實例發送GET命令,地址長度為78 AT+HTTPDESTROY=0 //斷開連接 當出現 +HTTPERR: 0,11 時,需要斷開連接,再重新連接實例服務器 將API返回的數據,+HTTPRESPC: 后面的7B227。。。轉為字符串形式 +HTTPRESPH: 0,200,396,Date: Fri, 02 Jun 2023 03:35:05 GMT Content-Type: application/json; charset=utf-8 Content-Length: 260 Connection: keep-alive access-control-allow-origin: * etag: W/"104-BAVuIqnZSk8TcsNHuRGYESoLzao" x-powered-by: Express x-ratelimit-limit: 20;w=60 x-ratelimit-remaining: 19 x-ratelimit-reset: 60.000 x-request-id: F2S6NvFKYBEUQ0zTbqlB x-tenant-id: dbef859d-3503-45ff-ba2f-3e5f0f4de75d +HTTPRESPC: 0,0,260,520,7B22726573756C7473223A5B7B226C6F636174696F6E223A7B226964223A2257583446425858464B45344622 2C226E616D65223A224265696A696E67222C22636F756E747279223A22434E222C2270617468223A224265696A696E672C4265696A696E67 2C4368696E61222C2274696D657A6F6E65223A22417369612F5368616E67686169222C2274696D657A6F6E655F6F6666736574223A222B30 383A3030227D2C226E6F77223A7B2274657874223A2253756E6E79222C22636F6465223A2230222C2274656D7065726174757265223A2232 38227D2C226C6173745F757064617465223A22323032332D30362D30325431313A31343A33382B30383A3030227D5D7D */ /************************************************************ * 函數名稱:EC01G_USART_Init * 函數說明:連接EC01G的初始化 * 型 參:bund=串口波特率 * 返 回 值:無 * 備 注:無 *************************************************************/ void EC01G_USART_Init(unsigned int bund) { GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結構體 RCC_EC01G_GPIO_ENABLE(); // 使能GPIO時鐘 RCC_EC01G_USART_ENABLE(); // 使能UART時鐘 GPIO_InitStruct.Pins = GPIO_EC01G_TX; // GPIO引腳 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽輸出 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 輸出速度高 GPIO_Init(PORT_EC01G_GPIO, &GPIO_InitStruct); // 初始化 GPIO_InitStruct.Pins = GPIO_EC01G_RX; // GPIO引腳 GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉輸入 GPIO_Init(PORT_EC01G_GPIO, &GPIO_InitStruct); // 初始化 BSP_GPS_AF_UART_TX(); // UART_TX復用 BSP_GPS_AF_UART_RX(); // UART_RX復用 // 配置UART USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = bund; // 波特率 USART_InitStructure.USART_Over = USART_Over_8; // 配置USART的過采樣率。 USART_InitStructure.USART_Source = USART_Source_PCLK; // 設置時鐘源 USART_InitStructure.USART_UclkFreq = 64000000; //設置USART時鐘頻率(和主頻一致即可) USART_InitStructure.USART_StartBit = USART_StartBit_FE; //RXD下降沿開始 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位1 USART_InitStructure.USART_Parity = USART_Parity_No ; // 不使用校驗 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用流控 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收發模式 USART_Init(EC01G_USART, &USART_InitStructure); // 初始化串口2 // 優先級,無優先級分組 NVIC_SetPriority(EC01G_USART_IRQ, 0); // UARTx中斷使能 NVIC_EnableIRQ(EC01G_USART_IRQ); // 使能UARTx RC中斷 USART_ITConfig(EC01G_USART, USART_IT_RC, ENABLE); } /****************************************************************** * 函 數 名 稱:EC01G_USART_Send_Bit * 函 數 說 明:向EC01G模塊發送單個字符 * 函 數 形 參:ch=字符 * 函 數 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void EC01G_USART_Send_Bit(unsigned char ch) { // 發送一個字節 USART_SendData_8bit(EC01G_USART, (uint8_t)ch); // 等待發送完成 while( RESET == USART_GetFlagStatus(EC01G_USART, USART_FLAG_TXE) ){} } /****************************************************************** * 函 數 名 稱:EC01G_USART_send_String * 函 數 說 明:向EC01G模塊發送字符串 * 函 數 形 參:str=發送的字符串 * 函 數 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void EC01G_USART_send_String(unsigned char *str) { while( str && *str ) // 地址為空或者值為空跳出 { EC01G_USART_Send_Bit(*str++); } } //清除串口接收的數據 /****************************************************************** * 函 數 名 稱:Clear_EC01G_RX_BUFF * 函 數 說 明:清除EC01G發過來的數據 * 函 數 形 參:無 * 函 數 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void Clear_EC01G_RX_BUFF(void) { unsigned int i = EC01G_RX_LEN_MAX-1; while(i) { EC01G_RX_BUFF[i--] = 0; } EC01G_RX_LEN = 0; EC01G_RX_FLAG = 0; } /****************************************************************** * 函 數 名 稱:EC01G_Send_Cmd * 函 數 說 明:向EC01G模塊發送指令,并查看EC01G模塊是否返回想要的數據 * 函 數 形 參:cmd=發送的AT指令 ack=想要的應答 waitms=等待應答的時間 cnt=等待應答多少次 * 函 數 返 回:1=得到了想要的應答 0=沒有得到想要的應答 * 作 者:LC * 備 注:無 ******************************************************************/ char EC01G_Send_Cmd(char *cmd,char *ack,unsigned int waitms,unsigned char cnt) { Clear_EC01G_RX_BUFF(); //清除接收的數據 EC01G_USART_send_String((unsigned char*)cmd);//發送AT指令 while(cnt--) { //串口中斷接收EC01G應答 if( EC01G_RX_FLAG == 1 ) { //查找是否有想要的數據 if( strstr((char*)EC01G_RX_BUFF, ack) != NULL ) { return 1; } } //時間間隔 delay_ms(waitms); } return 0; } /****************************************************************** * 函 數 名 稱:EC01G_Init * 函 數 說 明:EC01G模塊初始化 * 函 數 形 參:無 * 函 數 返 回:無 * 作 者:LC * 備 注:ESP01S的默認波特率是9600 ******************************************************************/ void EC01G_Init(void) { EC01G_USART_Init(9600);//默認波特率為9600 } /****************************************************************** * 函 數 名 稱:EC01G_Seniverse_Init * 函 數 說 明:配置EC01G模塊連接心知天氣平臺 * 函 數 形 參:無 * 函 數 返 回:1=沒有檢測到設備 * 作 者:LC * 備 注: ATrn //測試設備是否存在 返回OK說明存在 AT+CFUN=1 //關閉飛行模式 返回OK 說明成功 AT+CEREG? //判斷是否附著網絡成功 返回+CEREG: 0,1 說明附著網絡成功 AT+HTTPCREATE=0,"http: //116.62.81.138:80" //設置命令創建一個 http 或 https 客戶端實例 返回OK成功 AT+HTTPCON=0 //連接0號實例服務器 返回OK成功 AT+HTTPSEND=0,0,78,"/v3/weather/now.json?key=SIwiiHEWo6pPD42S5&location=beijing&language=en&unit=c" //向0號實例發送GET命令,地址長度為78 AT+HTTPDESTROY=0 //斷開連接 當出現 +HTTPERR: 0,11 時,需要斷開連接,再重新連接實例服務器 ******************************************************************/ uint8_t EC01G_Seniverse_Init(void) { uint8_t ret = 0; uint8_t i = 0; // uint8_t send_buff[250]={0}; //測試設備是否存在 if( EC01G_Send_Cmd("ATrn", "OK", 1000,3) == 0 ) { return 1; } //關閉飛行模式 if( EC01G_Send_Cmd("AT+CFUN=1rn", "OK", 1000,3) == 0 ) { return 2; } //判斷是否附著網絡成功 if( EC01G_Send_Cmd("AT+CEREG?rn", "+CEREG: 0,1", 5000,3) == 0 ) { ret = EC01G_Send_Cmd("AT+CEREG?rn", "+CEREG: 0,1", 1000,3); if( ret == 0 ) { return 1; } } again: //如果之前有連接過,則斷開連接 EC01G_Send_Cmd("AT+HTTPDESTROY=0rn", "OK", 1000,10); if( EC01G_Send_Cmd("AT+ECDNS= api.seniverse.comrn", "error", 1000,3) == 1 ) { printf("當前域名解析服務器無法工作:%drn",__LINE__); } //創建一個 http客戶端實例 while( EC01G_Send_Cmd("AT+HTTPCREATE=0,"http://116.62.81.138:80"rn", "OK", 5000,3) == 0 ) { #if DEBUG printf("AT+HTTPCREATE FAILrn"); #endif i++; if( i >= 3 ) return 2; goto again; } i=0; //連接0號實例服務器 (默認0號服務器) while( EC01G_Send_Cmd("AT+HTTPCON=0rn", "OK", 5000,3) == 0 ) { #if DEBUG printf("AT+HTTPCON FAILrn"); #endif i++; if( i >= 3 ) return 3; goto again; } // //發送獲取天氣數據API // sprintf((char*)send_buff, "AT+HTTPSEND=0,0,%d,%srn", strlen(WEATHER_FACTS_API)-2, WEATHER_FACTS_API); // if( EC01G_Send_Cmd((char*)send_buff, "OK", 1000,3) == 0 ) // { // #if DEBUG // printf("AT+HTTPSEND FAILrn"); // // #endif // return 4; // } return 0; } /****************************************************************** * 函 數 名 稱:Hex_To_Text * 函 數 說 明:將16進制字符串轉為字符型字符串 * 函 數 形 參:hex=16進制字符串地址 hex_len= text=要保存的地址 * 函 數 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void Hex_To_Text(char *hex, char *text) { int string_length = strlen((char*)hex) / 2; int i = 0; // 將每兩個字符轉換為一個字節,并拷貝到轉換后的字符串中 for (i = 0; i < string_length; i++) { char HEX[3]; memcpy(HEX, &hex[i * 2], 2); HEX[2] = ''; text[i] = strtol(HEX, NULL, 16); } text[i]=''; } /****************************************************************** * 函 數 名 稱:Search_Data * 函 數 說 明:查找對應數據 * 函 數 形 參:original_data=原始數據 weather_data=要保存的數據 find_what查找的數據頭 * 函 數 返 回:0=查找失敗 1=查找成功 * 作 者:LC * 備 注:無 ******************************************************************/ uint8_t Search_Data(char *original_data, char * weather_data, char *find_what) { char *buff; uint16_t i = 0; if( strstr(original_data, find_what) != NULL ) { //找到內容開始的地址 buff = strstr(original_data, find_what); //過濾find_what的內容 buff += strlen(find_what); //找到'"'的下標 while( buff[i] != '"' ) { i++; } //從buff里復制長度為i的字符串到weather_data strncpy(weather_data, buff, i); //strncpy函數不會補零,需手動補上 weather_data[i+1] = ''; return 1; } return 0; } /****************************************************************** * 函 數 名 稱:Weather_Data_Analysis * 函 數 說 明:解析天氣數據格式。 * 函 數 形 參:original_data原始JSON格式數據 weather_data解析的數據保存地址 * 函 數 返 回:無 * 作 者:LC * 備 注:原始JSON格式數據見下方 {"results":[{"location":{"id":"WS10730EM8EV","name":"Shenzhen","country":"CN","path": "Shenzhen,Shenzhen,Guangdong,China","timezone":"Asia/Shanghai","timezone_offset": "+08:00"},"now":{"text":"Sunny","code":"0","temperature":"32"},"last_update":"2023-06-02T16:10:15+08:00"}]} ******************************************************************/ void Weather_Data_Analysis(char *original_data, WEATHER_DATA* weather_data) { //查找城市 Search_Data(original_data,weather_data-?>city,"name":""); //查找國家 Search_Data(original_data,weather_data->country,"country":""); //查找具體地址 Search_Data(original_data,weather_data->path,"path":""); //查找天氣狀態 Search_Data(original_data,weather_data->weather,"text":""); //查找天氣代碼 Search_Data(original_data,weather_data->weather_code,"code":""); //查找當前溫度 Search_Data(original_data,weather_data->temperature,"temperature":""); //查找更新時間 Search_Data(original_data,weather_data->last_update,"last_update":""); } /****************************************************************** * 函 數 名 稱:Get_Weather_Data * 函 數 說 明:獲取天氣數據 * 函 數 形 參:data=所以天氣數據保存的結構體地址 * 函 數 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void Get_Weather_Data(WEATHER_DATA* data) { int timeout = 10; //5秒的超時時間 unsigned char send_buff[250]={0}; char parse_buff[512]={0}; char *rev_buff = NULL; //整理天氣數據API sprintf((char*)send_buff, "AT+HTTPSEND=0,0,%d,%srn", strlen(WEATHER_FACTS_API)-2, WEATHER_FACTS_API); //發送指令 EC01G_USART_send_String((unsigned char*)send_buff);//發送AT指令 //接收數據 while( timeout-- ) { delay_ms(1000); if( EC01G_RX_API_FLAG == 1 ) { EC01G_RX_API_FLAG = 0; //如果接收正確 rev_buff = strstr((const char*)EC01G_RX_BUFF, "+HTTPRESPC:"); printf("rn===================api====================rn"); printf("%srn",rev_buff); printf("rn=======================================rn"); } } int i = 0; //過濾不需要的數據 rev_buff+=11; //過濾+HTTPRESPC: while( i < 4 )//過濾4個逗號 { if( *rev_buff == ',' ) { i++; } rev_buff++; } //將16進制字符串轉為字符型字符串 Hex_To_Text(rev_buff, parse_buff); printf("rn過濾后的數據:rn"); printf("==========================rn"); printf("%srn",parse_buff); printf("rn"); printf("==========================rn"); //解析數據保存到data里 Weather_Data_Analysis(parse_buff, data); } /****************************************************************** * 函 數 名 稱:EC01G_USART_IRQHandler * 函 數 說 明:連接EC01G的串口中斷服務函數 * 函 數 形 參:無 * 函 數 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void EC01G_USART_IRQHandler(void) { if(USART_GetITStatus(EC01G_USART,USART_IT_RC) != RESET) // 接收緩沖區不為空 { //接收數據 EC01G_RX_BUFF[ EC01G_RX_LEN++ ] = USART_ReceiveData(EC01G_USART); if(EC01G_RX_LEN > EC01G_RX_LEN_MAX ) EC01G_RX_LEN = 0; EC01G_RX_BUFF[EC01G_RX_LEN] = ''; //字符串結尾補 '' EC01G_RX_FLAG = 1; // 接收完成 if( EC01G_RX_BUFF[ EC01G_RX_LEN- 1 ] == 'C' && EC01G_RX_BUFF[ EC01G_RX_LEN- 2 ] == 'P' && EC01G_RX_BUFF[ EC01G_RX_LEN- 3 ] == 'S' ) { EC01G_RX_API_FLAG = 1; } //測試,查看接收到了什么數據 #if DEBUG printf("%c", EC01G_RX_BUFF[ EC01G_RX_LEN - 1 ]); #endif USART_ClearITPendingBit(EC01G_USART, USART_IT_RC); } } void HardFault_Handler(void) { }
在文件bsp_ec01g.h中,編寫如下代碼。
/* * Change Logs: * Date Author Notes * 2024-06-24 LCKFB-LP first version */ #ifndef _BSP_EC01G_H_ #define _BSP_EC01G_H_ #include "string.h" #include "board.h" //是否開啟串口0調試,查看WIFI回顯數據 #define DEBUG 1 /**************************** 心知天氣 ****************************/ //秘鑰(需要修改為你的密鑰!) #define API_KEY "SpUFyXp2YvP12yxQR" //要查詢的城市 (輸入城市拼音,免費版只支持部分城市) #define QUERIED_CITY "shenzhen" //天氣實況API "/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c" #define WEATHER_FACTS_FRONT ""/v3/weather/now.json?key=" #define WEATHER_FACTS_MIDDLE "&location=" #define WEATHER_FACTS_BACK "&language=en&unit=c"" //查詢天氣實況API #define WEATHER_FACTS_API ( WEATHER_FACTS_FRONT API_KEY WEATHER_FACTS_MIDDLE QUERIED_CITY WEATHER_FACTS_BACK) //未來天氣預報API "/v3/weather/daily.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c&start=0&days=5" #define FUTURE_WEATHER_FRONT ""/v3/weather/daily.json?key=" #define FUTURE_WEATHER_MIDDLE "&location=" #define FUTURE_WEATHER_BACK "&&language=en&unit=c&start=0&days=5"" //未來天氣預報API #define FUTURE_WEATHER_API ( FUTURE_WEATHER_FRONT API_KEY FUTURE_WEATHER_MIDDLE QUERIED_CITY FUTURE_WEATHER_BACK) //接收的數據保存地址 typedef struct{ char city[20]; //查詢的城市 char country[20]; //查詢的國家 char path[50]; //具體地址(市市省國,例:Shenzhen,Shenzhen,Guangdong,China) char weather[10]; //天氣狀態 char weather_code[5]; //天氣代碼 char temperature[5]; //溫度 char last_update[50]; //天氣數據更新時間 }WEATHER_DATA; /**************************** 串口配置 ****************************/ #define RCC_EC01G_GPIO_ENABLE() __RCC_GPIOA_CLK_ENABLE() // 串口TX的端口時鐘 #define RCC_EC01G_USART_ENABLE() __RCC_UART2_CLK_ENABLE() // 串口2的時鐘 #define BSP_GPS_AF_UART_TX() PA02_AFx_UART2TXD() // GPIO的引腳復用 #define BSP_GPS_AF_UART_RX() PA03_AFx_UART2RXD() // GPIO的引腳復用 #define PORT_EC01G_GPIO CW_GPIOA // GPIO的端口 #define GPIO_EC01G_TX GPIO_PIN_2 // 串口TX的引腳 #define GPIO_EC01G_RX GPIO_PIN_3 // 串口RX的引腳 #define EC01G_USART CW_UART2 // 串口2 #define EC01G_USART_IRQ UART2_IRQn // 串口2中斷 #define EC01G_USART_IRQHandler UART2_IRQHandler // 串口2中斷服務函數 #define EC01G_RX_LEN_MAX 4096 //串口接收最大長度 void EC01G_Init(void); uint8_t EC01G_Seniverse_Init(void); void Get_Weather_Data(WEATHER_DATA* data); #endif
四、案列:接入心知天氣平臺獲取天氣數據
1. 心知天氣獲取
第一次使用需要先注冊,進入官網:https://www.seniverse.com。
2. 登陸控制臺獲取私鑰(這里我注冊了3個 密鑰,隨便選擇了一個)
3. 根據安信可科技提供的資料,完成心知天氣平臺的接入。
AT指令發送步驟:
指令相關含義見資料【nb-iot系列模組AT指令集v1.0.pdf】
發送 | 成功則返回 | 說明 |
---|---|---|
ATrn | OK | 測試設備是否存在 |
--- | --- | --- |
AT+CFUN=1rn | OK | 關閉飛行模式(如果返回ERROR:10 說明沒有識別到物聯網卡) |
AT+CEREG?rn | +CEREG: 0,1 | 判斷是否附著網絡成功(不成功請注意NB天線是否接好) |
AT+HTTPCREATE=0,"http://116.62.81.138:80"rn | OK | 創建一個http客戶端實例 |
AT+HTTPCON=0rn | OK | 連接該實例(連接心知天氣平臺) |
AT+HTTPSEND=0,0,LEN,APIrn | OK | 向0號實例發送長度為LEN的API指令 |
API指令可上心知天氣官網查詢,這個貼兩個API指令。(可點擊超鏈接跳轉到相關網頁)
獲取天氣實況:https://seniverse.yuque.com/hyper_data/api_v3/nyiu3t
/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c
獲取未來5天天氣情況:https://seniverse.yuque.com/hyper_data/api_v3/sl6gvt
/v3/weather/daily.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c&start=0&days=5
API指令中,請將 your_api_key 替換成為你的私鑰。
4. 代碼移植
實現該步驟請確保完成了移植至工程目錄。
在 bsp_ec01g.h 中,將私鑰宏定義 API_KEY 修改為你自己的私鑰。并輸入要查詢的城市。
在main.c 中編輯以下代碼。
/* * Change Logs: * Date Author Notes * 2024-06-24 LCKFB-LP first version */ #include "board.h" #include "stdio.h" #include "bsp_uart.h" #include "bsp_ec01g.h" int32_t main(void) { WEATHER_DATA weather_data={0}; board_init(); uart1_init(115200); printf("Start... rn %s rn",WEATHER_FACTS_API); EC01G_Init(); EC01G_Seniverse_Init(); printf("rnrn Weather rnrn"); //獲取天氣數據,并保存到weather_data結構體里 Get_Weather_Data(&weather_data); printf("city = %srn", weather_data.city ); printf("country = %srn", weather_data.country ); printf("path = %srn", weather_data.path ); printf("weather = %srn", weather_data.weather ); printf("weather_code = %srn", weather_data.weather_code ); printf("temperature = %srn", weather_data.temperature ); printf("last_update = %srn", weather_data.last_update ); while(1) { delay_ms(100); } }
上電現象:
模塊移植成功案例代碼:
鏈接:https://pan.baidu.com/s/12gapOSbSv8IIJ07tkIzIPA?pwd=LCKF
提取碼:LCKF
審核編輯 黃宇
-
gps
+關注
關注
22文章
2900瀏覽量
166507 -
nbiot
+關注
關注
8文章
63瀏覽量
22724 -
CW32
+關注
關注
1文章
218瀏覽量
706
發布評論請先 登錄
相關推薦
評論