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

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


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


▲長(zhǎng)按圖片保存可分享至朋友圈


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

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

指令格式如下:

一般情況下,采用的是CRC格式校驗(yàn)的指令。

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

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

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

操作隊(duì)列的接口有:

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

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

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

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

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

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

 1//從隊(duì)列中取一個(gè)數(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 //取一個(gè)數(shù)據(jù) 18 queue_pop(&_data); 19 20 if(cmd_pos==0&&_data!=CMD_HEAD)//指令第一個(gè)字節(jié)必須是幀頭,否則跳過(guò) 21 continue; 22 23 if(cmd_pos//防止緩沖區(qū)溢出 24 buffer[cmd_pos++]?=?_data; 25 26 cmd_state?=?((cmd_state<<8)|_data);//拼接最后4個(gè)字節(jié),組成一個(gè)32位整數(shù) 27 28 //最后4個(gè)字節(jié)與幀尾匹配,得到完整幀 29 if(cmd_state==CMD_TAIL) 30 { 31 cmd_size?=?cmd_pos; //指令字節(jié)長(zhǎng)度 32 cmd_state?= 0; //重新檢測(cè)幀尾巴 33 cmd_pos?= 0; //復(fù)位指令指針 34 35#if(CRC16_ENABLE) 36 //去掉指令頭尾EE,尾FFFCFFFF共計(jì)5個(gè)字節(jié),只計(jì)算數(shù)據(jù)部分CRC 37 if(!CheckCRC16(buffer+1,cmd_size-5))//CRC校驗(yàn) 38 return 0; 39 40 cmd_size?-= 2;//去掉CRC16(2字節(jié)) 41#endif 42 43 return cmd_size; 44 } 45 } 46 47 return 0;//沒(méi)有形成完整的一幀 48}

那么具體在哪里入隊(duì)呢?在大彩提供的例程中,入隊(duì)操作是在串口中斷服務(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ā)生兩個(gè)操作:

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

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

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

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

 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ù),對(duì)指令進(jìn)行處理,其中將數(shù)據(jù)強(qiáng)轉(zhuǎn)為PCTRL_MSG這個(gè)數(shù)據(jù)結(jié)構(gòu),主要為:

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

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

 1/*!  2 *??\brief??消息處理流程,此處一般不需要更改  3 *??\param?msg?待處理消息  4 *??\param?size?消息長(zhǎng)度  5 */  6void?ProcessMessage(?PCTRL_MSG?msg,?uint16?size?)  7{  8 uint8?cmd_type?=?msg->cmd_type;//指令類(lèi)型  9 uint8?ctrl_msg?=?msg->ctrl_msg; //消息的類(lèi)型 10 uint8?control_type?=?msg->control_type;//控件類(lèi)型 11 uint16?screen_id?=?PTR2U16(&msg->screen_id_high);//畫(huà)面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://觸摸屏松開(kāi) 19 NotifyTouchXY(cmd_buffer[1],PTR2U16(cmd_buffer+2),PTR2U16(cmd_buffer+4)); 20 break; 21 case NOTIFY_WRITE_FLASH_OK://寫(xiě)FLASH成功 22 NotifyWriteFlash(1); 23 break; 24 case NOTIFY_WRITE_FLASH_FAILD://寫(xiě)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時(shí)間 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)//畫(huà)面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: //滑動(dòng)條控件 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://倒計(jì)時(shí)控件 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í)到了一個(gè)編程的小技巧,將數(shù)據(jù)強(qiáng)轉(zhuǎn)為一個(gè)結(jié)構(gòu)體,再利用結(jié)構(gòu)體的偏移特性來(lái)獲得數(shù)據(jù)。
這個(gè)函數(shù)的作用就顯而易見(jiàn)了,通過(guò)一條指令得知當(dāng)前使用的是什么控件等等。。。

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

1#define TX_8(P1)?SEND_DATA((P1)&0xFF) //發(fā)送單個(gè)字節(jié) 2#define TX_8N(P,N)?SendNU8((uint8?*)P,N) //發(fā)送N個(gè)字節(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個(gè)16位整數(shù) 5#define TX_32(P1)?TX_16((P1)>>16);TX_16((P1)&0xFFFF) //發(fā)送32位整數(shù) 

這里是參考手冊(cè)發(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;//開(kāi)始計(jì)算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}


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



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

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

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

關(guān)鍵字: 驅(qū)動(dòng)電源

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

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

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

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

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

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

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

關(guān)鍵字: 電動(dòng)汽車(chē) 新能源 驅(qū)動(dòng)電源

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

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

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

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周?chē)娮釉O(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

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

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

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

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉