www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]超詳細(xì)總結(jié),值得一看!


微信公眾號:morixinguan
關(guān)注可了解更多的教程。問題或建議,請公眾號留言;
如果你覺得本文對你有幫助,歡迎贊賞


▲長按圖片保存可分享至朋友圈


大彩科技是專注做串口屏的廠家,網(wǎng)址如下:

http://www.gz-dc.com/

指令格式如下:

一般情況下,采用的是CRC格式校驗的指令。

處理指令方面,大彩提供了一個例程,主要用一個隊列來維護(hù)。

數(shù)據(jù)結(jié)構(gòu):

 1#define QUEUE_MAX_SIZE?128 /*!< 指令接收緩沖區(qū)大小,根據(jù)需要調(diào)整,盡量設(shè)置大一些*/  2typedef struct _QUEUE  3{  4 qsize?_head; //隊列頭  5 qsize?_tail; //隊列尾  6 qdata?_data[QUEUE_MAX_SIZE]; //隊列數(shù)據(jù)緩存區(qū)  7}QUEUE;  8  9static QUEUE?que?=?{0,0,0}; //指令隊列 10static uint32?cmd_state?= 0; //隊列幀尾檢測狀態(tài) 11static qsize?cmd_pos?= 0; //當(dāng)前指令指針位置 

操作隊列的接口有:

 1/*!  2 *??\brief??清空指令數(shù)據(jù)  3 */  4extern void queue_reset(void);  5  6/*!  7 *?\brief??添加指令數(shù)據(jù)  8 *?\detial?串口接收的數(shù)據(jù),通過此函數(shù)放入指令隊列  9 *??\param??_data?指令數(shù)據(jù) 10 */ 11extern void queue_push(qdata?_data); 12 13/*! 14 *??\brief??從指令隊列中取出一條完整的指令 15 *??\param??cmd?指令接收緩存區(qū) 16 *??\param??buf_len?指令接收緩存區(qū)大小 17 *??\return??指令長度,0表示隊列中無完整指令 18 */ 19extern qsize queue_find_cmd(qdata?*cmd,qsize?buf_len);

隊列清空的實現(xiàn)很簡單,只要把隊列頭和隊隊列尾檢查狀態(tài)、當(dāng)前指針的位置置為0即可,實現(xiàn)如下:

1void queue_reset() 2{ 3 que._head?=?que._tail?= 0; 4 cmd_pos?=?cmd_state?= 0; 5}

添加指令數(shù)據(jù)操作,其實就是入隊的操作,也就是把數(shù)據(jù)源源不斷的放到隊列的緩存區(qū)中去:

1void?queue_push(qdata?_data) 2{ 3 qsize pos =?(que._head+1)%QUEUE_MAX_SIZE; 4 if(pos!=que._tail)//非滿狀態(tài) 5 { 6 que._data[que._head]?=?_data; 7 que._head?= pos; 8 } 9}

從指令隊列中取出一條完整的指令其實就是出隊操作,先將數(shù)據(jù)出隊,然后根據(jù)指令格式幀進(jìn)行分割處理。

 1//從隊列中取一個數(shù)據(jù)  2static void queue_pop(qdata*?_data)  3{  4 if(que._tail!=que._head)//非空狀態(tài)  5 {  6 *_data?=?que._data[que._tail];  7 que._tail?=?(que._tail+1)%QUEUE_MAX_SIZE;  8 }  9} 10 11qsize queue_find_cmd(qdata?*buffer,qsize?buf_len) 12{ 13 qsize?cmd_size?= 0; 14 qdata?_data?= 0; 15 while(queue_size()>0) 16 { 17 //取一個數(shù)據(jù) 18 queue_pop(&_data); 19 20 if(cmd_pos==0&&_data!=CMD_HEAD)//指令第一個字節(jié)必須是幀頭,否則跳過 21 continue; 22 23 if(cmd_pos//防止緩沖區(qū)溢出 24 buffer[cmd_pos++]?=?_data; 25 26 cmd_state?=?((cmd_state<<8)|_data);//拼接最后4個字節(jié),組成一個32位整數(shù) 27 28 //最后4個字節(jié)與幀尾匹配,得到完整幀 29 if(cmd_state==CMD_TAIL) 30 { 31 cmd_size?=?cmd_pos; //指令字節(jié)長度 32 cmd_state?= 0; //重新檢測幀尾巴 33 cmd_pos?= 0; //復(fù)位指令指針 34 35#if(CRC16_ENABLE) 36 //去掉指令頭尾EE,尾FFFCFFFF共計5個字節(jié),只計算數(shù)據(jù)部分CRC 37 if(!CheckCRC16(buffer+1,cmd_size-5))//CRC校驗 38 return 0; 39 40 cmd_size?-= 2;//去掉CRC16(2字節(jié)) 41#endif 42 43 return cmd_size; 44 } 45 } 46 47 return 0;//沒有形成完整的一幀 48}

那么具體在哪里入隊呢?在大彩提供的例程中,入隊操作是在串口中斷服務(wù)函數(shù)中進(jìn)行的:

1void USART1_IRQHandler(void) 2{ 3 if (USART_GetITStatus(USART1,?USART_IT_RXNE)?!=?RESET) 4 { 5 uint8_t data?=?USART_ReceiveData(USART1); 6 queue_push(data); 7 } 8}

在這期間主要發(fā)生兩個操作:

1、串口通過中斷接收一個字節(jié)

2、將接收到的每一個字節(jié)放入隊列緩存區(qū)中

那么又具體怎么知道串口屏給我回復(fù)的指令呢,然后發(fā)生一系列動作呢?

這時候,程序里需要有一個while(1),源源不斷的等待queue_find_cmd函數(shù)給我們做取數(shù)據(jù),完成拼接指令的過程。

 1....  2while(1)  3{  4 size?=?queue_find_cmd(cmd_buffer,CMD_MAX_SIZE); //從緩沖區(qū)中獲取一條指令   5 if(size>0)//接收到指令  6 {  7 ProcessMessage((PCTRL_MSG)cmd_buffer,?size);//指令處理  8 }  9} 10....

cmd_buffer在這里就是一條完整的指令,再將這條完整的指令傳入ProcessMessage函數(shù),對指令進(jìn)行處理,其中將數(shù)據(jù)強(qiáng)轉(zhuǎn)為PCTRL_MSG這個數(shù)據(jù)結(jié)構(gòu),主要為:

 1typedef struct  2{  3 uint8 cmd_head; //幀頭  4  5 uint8 cmd_type; //命令類型(UPDATE_CONTROL)   6 uint8 ctrl_msg; //CtrlMsgType-指示消息的類型  7 uint8 screen_id_high; //產(chǎn)生消息的畫面ID  8 uint8 screen_id_low;  9 uint8 control_id_high; //產(chǎn)生消息的控件ID 10 uint8 control_id_low; 11 uint8 control_type; //控件類型 12 13 uint8 param[256];//可變長度參數(shù),最多256個字節(jié) 14 15 uint8 cmd_tail[4]; //幀尾 16}CTRL_MSG,*PCTRL_MSG;

在這里接收到的cmd_buffer里的指令是把頭尾去掉的,這時候我們明白了,接收過來的指令需要賦給它一定的含義,于是看ProcessMessage函數(shù)的實現(xiàn):

 1/*!  2 *??\brief??消息處理流程,此處一般不需要更改  3 *??\param?msg?待處理消息  4 *??\param?size?消息長度  5 */  6void?ProcessMessage(?PCTRL_MSG?msg,?uint16?size?)  7{  8 uint8?cmd_type?=?msg->cmd_type;//指令類型  9 uint8?ctrl_msg?=?msg->ctrl_msg; //消息的類型 10 uint8?control_type?=?msg->control_type;//控件類型 11 uint16?screen_id?=?PTR2U16(&msg->screen_id_high);//畫面ID 12 uint16?control_id?=?PTR2U16(&msg->control_id_high);//控件ID 13 uint32?value?=?PTR2U32(msg->param);//數(shù)值 14 15 switch(cmd_type) 16 { 17 case NOTIFY_TOUCH_PRESS://觸摸屏按下 18 case NOTIFY_TOUCH_RELEASE://觸摸屏松開 19 NotifyTouchXY(cmd_buffer[1],PTR2U16(cmd_buffer+2),PTR2U16(cmd_buffer+4)); 20 break; 21 case NOTIFY_WRITE_FLASH_OK://寫FLASH成功 22 NotifyWriteFlash(1); 23 break; 24 case NOTIFY_WRITE_FLASH_FAILD://寫FLASH失敗 25 NotifyWriteFlash(0); 26 break; 27 case NOTIFY_READ_FLASH_OK://讀取FLASH成功 28 NotifyReadFlash(1,cmd_buffer+2,size-6);//去除幀頭幀尾 29 break; 30 case NOTIFY_READ_FLASH_FAILD://讀取FLASH失敗 31 NotifyReadFlash(0,0,0); 32 break; 33 case NOTIFY_READ_RTC://讀取RTC時間 34 NotifyReadRTC(cmd_buffer[1],cmd_buffer[2],cmd_buffer[3],cmd_buffer[4],cmd_buffer[5],cmd_buffer[6],cmd_buffer[7]); 35 break; 36 case NOTIFY_CONTROL: 37 { 38 if(ctrl_msg==MSG_GET_CURRENT_SCREEN)//畫面ID變化通知 39 { 40 NotifyScreen(screen_id); 41 } 42 else 43 { 44 switch(control_type) 45 { 46 case kCtrlButton: //按鈕控件 47 NotifyButton(screen_id,control_id,msg->param[1]); 48 break; 49 case kCtrlText://文本控件 50 NotifyText(screen_id,control_id,msg->param); 51 break; 52 case kCtrlProgress: //進(jìn)度條控件 53 NotifyProgress(screen_id,control_id,value); 54 break; 55 case kCtrlSlider: //滑動條控件 56 NotifySlider(screen_id,control_id,value); 57 break; 58 case kCtrlMeter: //儀表控件 59 NotifyMeter(screen_id,control_id,value); 60 break; 61 case kCtrlMenu://菜單控件 62 NotifyMenu(screen_id,control_id,msg->param[0],msg->param[1]); 63 break; 64 case kCtrlSelector://選擇控件 65 NotifySelector(screen_id,control_id,msg->param[0]); 66 break; 67 case kCtrlRTC://倒計時控件 68 NotifyTimer(screen_id,control_id); 69 break; 70 default: 71 break; 72 } 73 } 74 } 75 break; 76 default: 77 break; 78 } 79}

這里學(xué)習(xí)到了一個編程的小技巧,將數(shù)據(jù)強(qiáng)轉(zhuǎn)為一個結(jié)構(gòu)體,再利用結(jié)構(gòu)體的偏移特性來獲得數(shù)據(jù)。
這個函數(shù)的作用就顯而易見了,通過一條指令得知當(dāng)前使用的是什么控件等等。。。

發(fā)送指令就很簡單了,其實就是直接給串口發(fā)數(shù)據(jù),這里是實現(xiàn)如何發(fā)送數(shù)據(jù)給串口的定義:

1#define TX_8(P1)?SEND_DATA((P1)&0xFF) //發(fā)送單個字節(jié) 2#define TX_8N(P,N)?SendNU8((uint8?*)P,N) //發(fā)送N個字節(jié) 3#define TX_16(P1)?TX_8((P1)>>8);TX_8(P1) //發(fā)送16位整數(shù) 4#define TX_16N(P,N)?SendNU16((uint16?*)P,N) //發(fā)送N個16位整數(shù) 5#define TX_32(P1)?TX_16((P1)>>16);TX_16((P1)&0xFFFF) //發(fā)送32位整數(shù) 

這里是參考手冊發(fā)送的指令:

 1#if(CRC16_ENABLE)  2  3static uint16?_crc16?= 0xffff;  4static void AddCRC16(uint8?*buffer,uint16?n,uint16?*pcrc)  5{  6 uint16?i,j,carry_flag,a;  7  8 for (i=0;?i 9 { 10 *pcrc=*pcrc^buffer[i]; 11 for (j=0;?j<8;?j++) 12 { 13 a=*pcrc; 14 carry_flag=a&0x0001; 15 *pcrc=*pcrc>>1; 16 if (carry_flag==1) 17 *pcrc=*pcrc^0xa001; 18 } 19 } 20} 21 22uint16 CheckCRC16(uint8?*buffer,uint16?n) 23{ 24 uint16?crc0?= 0x0; 25 uint16?crc1?= 0xffff; 26 27 if(n>=2) 28 { 29 crc0?=?((buffer[n-2]<<8)|buffer[n-1]); 30 AddCRC16(buffer,n-2,&crc1); 31 } 32 33 return (crc0==crc1); 34} 35 36void SEND_DATA(uint8?c) 37{ 38 AddCRC16(&c,1,&_crc16); 39 SendChar(c); 40} 41 42void BEGIN_CMD() 43{ 44 TX_8(0XEE); 45 _crc16?= 0XFFFF;//開始計算CRC16 46} 47 48void END_CMD() 49{ 50 uint16?crc16?=?_crc16; 51 TX_16(crc16);//發(fā)送CRC16 52 TX_32(0XFFFCFFFF); 53} 54 55#else//NO?CRC16 56 57#define SEND_DATA(P)?SendChar(P) 58#define BEGIN_CMD()?TX_8(0XEE) 59#define END_CMD()?TX_32(0XFFFCFFFF) 60 61#endif 62 63void DelayMS(unsigned int n) 64{ 65 int i,j; 66 for(i?=?n;i>0;i--) 67 for(j=1000;j>0;j--)?; 68} 69 70void SendStrings(uchar?*str) 71{ 72 while(*str) 73 { 74 TX_8(*str); 75 str++; 76 } 77} 78 79void SendNU8(uint8?*pData,uint16?nDataLen) 80{ 81 uint16?i?= 0; 82 for (;i83 { 84 TX_8(pData[i]); 85 } 86} 87 88void SendNU16(uint16?*pData,uint16?nDataLen) 89{ 90 uint16?i?= 0; 91 for (;i92 { 93 TX_16(pData[i]); 94 } 95}


長期商務(wù)合作服務(wù):



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

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

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉