日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 嵌入式云IOT技術圈
[導讀]本文基于TOS的AT框架,實現(xiàn)了一個基于MX+開發(fā)板的demo,用于控制之前搭的智能小車。

本節(jié)基于TOS的AT框架,我實現(xiàn)了一個基于MX+開發(fā)板的demo,用于控制之前搭的智能小車,效果如下,詳細源碼及實驗例程請參考文末碼云倉庫鏈接:

動手智能小車記(5)-坦克底盤硬件模塊大雜燴

1、什么是AT指令?

在嵌入式開發(fā)過程中,我們有時候要使用一些通信模組,比如藍牙、WIFI、4G、NBIOT等等,這些模組內(nèi)部固件已經(jīng)將協(xié)議棧封裝好了,然后模組硬件向外部提供了標準的串口,這樣通過與模組的串口相連接,就可以與模組進行通信;一般情況下,廠商都會提供模組的使用手冊,只要照著流程去操作模組就可以正常通信了,如下圖所示,這是一個MCU、藍牙模組、手機之間的通信案例:

2、為什么要有AT框架?

一般情況下,在一些物聯(lián)網(wǎng)產(chǎn)品的項目上可能這樣的需求,比如:

常規(guī)的一些傳感器設備,需要監(jiān)測環(huán)境溫度、濕度等等這樣的情況:

  • 實現(xiàn)數(shù)據(jù)上傳

共享單車、智能門鎖

  • 實現(xiàn)開鎖的邏輯

等等。。。

這些需求看起來就非常簡單,比如我就用ESP8266+一個后臺服務器來實現(xiàn)這樣的需求吧,只要后臺提供好API接口,那么這類簡單的需求分分鐘搞定,完全沒有任何難度,在應用程序上編寫好模組的驅動接口和通信邏輯就可以了。

但是,如果換一個呢??再換一個呢?有可能實現(xiàn)同樣的需求,我們還要去實現(xiàn)不一樣的驅動流程,這是不是顯得很麻煩?基于這樣的問題誕生,于是各個廠商分別提出了對應的AT框架思維,那么這種AT框架思維具體是什么樣的呢?以驅動ESP8266為例,一般有以下幾種模式:

  • AP模式
  • STA模式
  • AP+STA模式

以STA模式為例,最后要和云端服務器進行對接,我們首先要完成初始化流程,一般要發(fā)以下幾個指令:

  • AT+RESTORE\r\n 模組復位

  • ATE0\r\n 關閉回顯

  • AT+CWMODE=1\r\n 設置多連接

  • AT+CIPMODE=0\r\n 關閉透傳模式

  • AT+CIPMUX=1\r\n 開始多連接模式

  • AT+CWJAP="TOS","12345678"\r\n 連接熱點

這樣就基本完成了模組的初始化流程,初始化完畢以后,就可以進入數(shù)據(jù)傳輸?shù)牧?,連接服務器,然后開啟透傳模式,進入透傳模式,然后就可以把數(shù)據(jù)直接傳送到后臺了,此時還可以讀取后臺的消息,當我們不需要需要模組的時候,還可以將模組掉電;所以,我們可以在這個基礎上把這個驅動流程框架化,即是擁有初始化、連接服務器、發(fā)送、接收、關閉等等這些接口。

3、TencetOS tiny AT框架

在TencentOS tiny中,內(nèi)部就集成了一套簡單易用的AT框架,哪怕是不一樣的指令,我們也只需要填充對應的方法,然后注冊到框架上,就可以順利與模組進行通信了,以下是TencentOS tiny AT框架的基本組成圖:

上圖來源于汪兄講解的PPT

對于應用開發(fā)者來說,我們最關注的是SAL interface、也就是網(wǎng)絡適配框架,只要模組注網(wǎng)成功,那么在這一層,我們不需要具體去關注模組到底是怎么用AT指令去通信的,我們只需要調用SAL interface的socket、connect、send、recv、close等等接口完成我們與后臺的通信或者與別的通信方式的邏輯即可,但是調用SAL接口口還需要去與各個模組進行適配。

typedef?struct?sal_module_st?{
????int?(*init)(void);

????int?(*get_local_mac)(char?*mac);

????int?(*get_local_ip)(char?*ip,?char?*gw,?char?*mask);

????int?(*parse_domain)(const?char?*host_name,?char?*host_ip,?size_t?host_ip_len);

????int?(*connect)(const?char?*ip,?const?char?*port,?sal_proto_t?proto);

????int?(*send)(int?sock,?const?void?*buf,?size_t?len);

????int?(*recv_timeout)(int?sock,?void?*buf,?size_t?len,?uint32_t?timeout);

????int?(*recv)(int?sock,?void?*buf,?size_t?len);

????int?(*sendto)(int?sock,?char?*ip,?char?*port,?const?void?*buf,?size_t?len);

????int?(*recvfrom)(int?sock,?void?*buf,?size_t?len);

????int?(*recvfrom_timeout)(int?sock,?void?*buf,?size_t?len,?uint32_t?timeout);

????int?(*close)(int?sock);
}?sal_module_t;

對于怎么去綁定(適配)模組和SAL interface,在此之前那我們還需要完成AT framework與HAL(uart)的適配,然后提供SAL interface需要的接口,注冊上去,這樣我們就可以在SAL上愉快的進行操作了,接下來AT框架具體是怎么解析每個AT指令我們就不需要特別去關心了,感興趣的可以去研究一下tos_at.c、tos_at.h這兩個文件。

在TencentOS tiny SDK中,騰訊官方已經(jīng)提供了一些熱門模組的操作例程,比如esp8266,它是怎么與SAL interface完成適配的呢?如下:

上圖來源于戴兄講解的PPT


這樣的話,我們就可以調用TOS提供的SAL接口進行通信了,如下,在sal_module_wrapper.h中查看,詳細實現(xiàn)在sal_module_wrapper.c:

/**
?*?@brief?Convert?domain?to?ip?address.
?*
?*?@attention?None
?*
?*?@param[in]???host_name???domain?name?of?the?host
?*?@param[out]??host_ip?????ip?address?of?the?host
?*?@param[out]??host_ip_len?ip?address?buffer?length
?*
?*?@return??errcode
?*/
int?tos_sal_module_parse_domain(const?char?*host_name,?char?*host_ip,?size_t?host_ip_len);

/**
?*?@brief?Connect?to?remote?host.
?*
?*?@attention?None
?*
?*?@param[in]???ip??????ip?address?of?the?remote?host
?*?@param[in]???port????port?number?of?the?remote?host
?*?@param[in]???proto???protocol?of?the?connection(TCP/UDP)
?*
?*?@return??socket?id?if?succuss,?-1?if?failed.
?*/
int?tos_sal_module_connect(const?char?*ip,?const?char?*port,?sal_proto_t?proto);

/**
?*?@brief?Send?data?to?the?remote?host(TCP).
?*
?*?@attention?None
?*
?*?@param[in]???sock????socket?id
?*?@param[in]???buf?????data?to?send
?*?@param[in]???len?????data?length
?*
?*?@return??data?length?sent
?*/
int?tos_sal_module_send(int?sock,?const?void?*buf,?size_t?len);

/**
?*?@brief?Receive?data?from?the?remote?host(TCP).
?*
?*?@attention?None
?*
?*?@param[in]???sock????socket?id
?*?@param[in]???buf?????data?buffer?to?hold?the?data?received
?*?@param[in]???len?????data?buffer?length
?*
?*?@return??data?length?received
?*/
int?tos_sal_module_recv(int?sock,?void?*buf,?size_t?len);

/**
?*?@brief?Receive?data?from?the?remote?host(TCP).
?*
?*?@attention?None
?*
?*?@param[in]???sock????socket?id
?*?@param[in]???buf?????data?buffer?to?hold?the?data?received
?*?@param[in]???len?????data?buffer?length
?*?@param[in]???timeout?timeout
?*
?*?@return??data?length?received
?*/
int?tos_sal_module_recv_timeout(int?sock,?void?*buf,?size_t?len,?uint32_t?timeout);

/**
?*?@brief?Send?data?to?the?remote?host(UDP).
?*
?*?@attention?None
?*
?*?@param[in]???sock????socket?id
?*?@param[in]???ip??????ip?address?of?the?remote?host
?*?@param[in]???port????port?number?of?the?remote?host
?*?@param[in]???buf?????data?to?send
?*?@param[in]???len?????data?length
?*
?*?@return??data?length?sent
?*/
int?tos_sal_module_sendto(int?sock,?char?*ip,?char?*port,?const?void?*buf,?size_t?len);

/**
?*?@brief?Receive?data?from?the?remote?host(UDP).
?*
?*?@attention?None
?*
?*?@param[in]???sock????socket?id
?*?@param[in]???buf?????data?buffer?to?hold?the?data?received
?*?@param[in]???len?????data?buffer?length
?*
?*?@return??data?length?received
?*/
int?tos_sal_module_recvfrom(int?sock,?void?*buf,?size_t?len);

/**
?*?@brief?Receive?data?from?the?remote?host(UDP).
?*
?*?@attention?None
?*
?*?@param[in]???sock????socket?id
?*?@param[in]???buf?????data?buffer?to?hold?the?data?received
?*?@param[in]???len?????data?buffer?length
?*?@param[in]???timeout?timeout
?*
?*?@return??data?length?received
?*/
int?tos_sal_module_recvfrom_timeout(int?sock,?void?*buf,?size_t?len,?uint32_t?timeout);

/**
?*?@brief?Close?the?connection.
?*
?*?@attention?None
?*
?*?@param[in]???sock????socket?id
?*
?*?@return??errcode
?*/
int?tos_sal_module_close(int?sock);

但是你以為這就完了嗎?為了和Posix API無差異化調用,TencentOS tiny官方開發(fā)人員開發(fā)了一套近似于通用網(wǎng)絡操作接口,就類似操作一個文件一樣open、read、write、close,這不就更簡單了嘛?我們來一睹為快:

tos_at_socket.h

#ifndef??_TOS_AT_SOCKET_H_
#define??_TOS_AT_SOCKET_H_

#include?"tos_at_socket_lib.h"
#include?"tos_at_socket_types.h"

#define?AF_INET?????????????0

#define?AF_INET6????????????1

#define?AF_UNIX?????????????2

/*?Provides?sequenced,?reliable,?bidirectional,?connection-mode?byte?streams,?and?may?provide?a?transmission?mechanism?for?out-of-band?data.?*/
#define?SOCK_STREAM?????????0

/*?Provides?datagrams,?which?are?connectionless-mode,?unreliable?messages?of?fixed?maximum?length.?*/
#define?SOCK_DGRAM??????????1

/*?Peeks?at?an?incoming?message.?The?data?is?treated?as?unread?and?the?next?recv()?or?similar?function?shall?still?return?this?data.?*/
#define?MSG_PEEK????????????0x01

/*?Requests?out-of-band?data.?The?significance?and?semantics?of?out-of-band?data?are?protocol-specific.?*/
#define?MSG_OOB?????????????0x02

/*?On?SOCK_STREAM?sockets?this?requests?that?the?function?block?until?the?full?amount?of?data?can?be?returned.?The?function?may?return?the?smaller?amount?of?data?if?the?socket?is?a?message-based?socket,?if?a?signal?is?caught,?if?the?connection?is?terminated,?if?MSG_PEEK?was?specified,?or?if?an?error?is?pending?for?the?socket.?*/
#define?MSG_WAITALL?????????0x04

int?socket(int?domain,?int?type,?int?protocol);

int?connect(int?socket,?const?struct?sockaddr?*address,?socklen_t?address_len);

int?recv(int?socket,?void?*buffer,?size_t?length,?int?flags);

int?recvfrom(int?socket,?void?*?buffer,?size_t?length,?int?flags,?struct?sockaddr?*address,?socklen_t?*address_len);

int?send(int?socket,?const?void?*buffer,?size_t?length,?int?flags);

int?sendto(int?socket,?const?void?*message,?size_t?length,?int?flags,?const?struct?sockaddr?*dest_addr,?socklen_t?dest_len);

int?shutdown(int?socket,?int?how);

int?read(int?socket,?void?*buffer,?size_t?length);

int?close(int?socket);

int?write(int?socket,?const?void?*buffer,?size_t?length);

#endif?/*?_TOS_AT_SOCKET_H_?*/

只要注冊框架等流程完成以后,模組注網(wǎng)成功,后面就可以直接這樣常規(guī)操作了:

void?network_demo(void)
{
????int?recv_len?=?-1;
????int?fd,?rc,?cnt?=?0;

????struct?sockaddr_in?addr;

????bzero(&addr,?sizeof(addr));
????addr.sin_family?=?AF_INET;
????addr.sin_addr.s_addr?=?inet_addr(SERVER_IP);
????addr.sin_port?=?htons(SERVER_PORT);

????fd?=?socket(AF_INET,?SOCK_STREAM,?0);

????if?(fd?????{
????????printf("socket?failed\n");
????????return;
????}

????rc?=?connect(fd,?(struct?sockaddr?*)&addr,?sizeof(addr));

????if?(rc?????{
????????printf("connect?failed\n");
????????close(fd);
????????return;
????}
?
? while(1)
? {
?? //調用send發(fā)送數(shù)據(jù)
?? //調用recv接收并處理數(shù)據(jù)
? }
?
? close(fd);
}

基于TencentOS tiny AT框架的基礎上,我編寫了一個基于MX+開發(fā)板的控制小車例程,源碼已更新到碼云個人倉庫。

個人碼云倉庫地址:

https://gitee.com/morixinguan

我還將之前做的一些項目以及練習例程在近期內(nèi)全部上傳完畢,與大家一起分享交流:

全文參考資料

騰訊物聯(lián)網(wǎng)終端操作系統(tǒng)SDK文檔.pdf

騰訊物聯(lián)網(wǎng)終端操作系統(tǒng)開發(fā)指南.pdf

TencentOS tiny技術講解與開發(fā)實踐PPT.pdf

云加社區(qū)沙龍(騰訊物聯(lián)網(wǎng)操作系統(tǒng)TencentOS tiny架構解析與實踐).pdf

公眾號粉絲福利時刻

這里我給大家申請到了福利,本公眾號讀者購買小熊派開發(fā)板可享受9折優(yōu)惠,有需要購買小熊派以及騰訊物聯(lián)網(wǎng)開發(fā)板的朋友,淘寶搜索即可,跟客服說你是公眾號:嵌入式云IOT技術圈 的粉絲,立享9折優(yōu)惠!

往期精彩

TencentOS tiny RTOS快速入門

網(wǎng)紅騰訊物聯(lián)網(wǎng)開發(fā)板終極開箱評測,讓我們一睹為快!

Linux進程間通信(中)之信號、信號量實踐

Linux進程間通信(下)之共享內(nèi)存實踐

STM32硬核DIY機械鍵盤|藍牙USB雙模|燈控

覺得本次分享的文章對您有幫助,隨手點[在看]并轉發(fā)分享,也是對我的支持。

免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉