32微控制器與迪文屏通訊的開發學習

2021-10-08 17:44:36 字數 3687 閱讀 4020

本章主要說一下,乙個初學者學習迪文屏的經歷。適用於略懂、接觸過modbus的人。

有一說一,這個迪文屏上位機的軟體開發確實簡單,比我之前使用的ewin方便了不少。不過迪文屏使用的是rs232介面,它比tft-lcd驅動起來可能要麻煩一些,對於初學者來說,spi可能用的還不錯,但是modbus協議可以說是乙個分水嶺。能不能用好迪文屏的關鍵就在於對modbus協議的理解。

迪文屏的介面協議是串列埠,所以說只需要使用微控制器的串列埠外設即可。

rs232的簡介就不多說了,既然要驅動迪文屏,首先就要選擇合適的資料協議,說到資料協議,我對於資料協議的通俗理解就是為了讓兩種不同的東西能夠進行溝通的介質。比如乙個中國人在和乙個美國人打**,中國人說中國話美國人說美國話,哎這下子美國人矇了,聽不懂說什麼,畢竟漢語是世界上最難學的語言,這個時候就需要用到協議的概念了,兩個人同時約定說什麼語言,這就完美解決了聽不懂的問題。 當然資料協議最初的產生就是為了解決這類問題,就像 微控制器和迪文屏進行通訊,它倆不能各發各的資料吧,要以固定形式傳送資料,這時候對方接收以後已固定形式去解析,這樣就可以進行通訊了。

接著就不扯皮直接說重點

簡單的串列埠配置就不多寫了,配置成串列埠接收中斷即可,傳送中斷不要求。

先簡單介紹一下資料幀格式

以03為例,其他功能碼可參考modbus協議文件

接收時暫存器數量為n,那為什麼暫存器值為2*n呢?請看下邊

03這個功能碼的暫存器位元組是採用這種方式的,哪怕你的暫存器值是1,也要寫成0x00、0x01的形式。本次用到的兩個功能碼相同,還有10

modbus完整支援很多功能碼,但是實際在應用的時候常用的也就那麼幾個。具體如下:

0x01: 讀線圈暫存器 寫單個暫存器

0x02: 讀離散輸入暫存器

0x03: 讀保持暫存器 讀整頁的暫存器

0x04: 讀輸入暫存器

0x05: 寫單個線圈暫存器

0x06: 寫單個保持暫存器 寫單個暫存器

0x0f: 寫多個線圈暫存器

0x10: 寫多個保持暫存器 寫整頁的暫存器

如上所示一共8種功能碼。所謂的線圈是由於modbus一開始是由plc誕生的,對應在迪文屏上就是暫存器而已,而暫存器這個概念其實就是迪文屏頁面的不同的控制項而已。

我在迪文屏中使用到的功能碼:

1、功能碼03:用來讀取整個迪文屏頁面的暫存器,當下位機中的資料發生改變,那麼上位機介面上也要進行改變(最典型的就是倒計時,下位機定時器,上位機顯示倒計時時間值)

此處的暫存器指的就是迪文屏頁面的全部變數、控制項。當位址為當前頁面的起始位址時,而暫存器數量就是當前頁面的變數控制項的數量。例如當前頁面有乙個按鍵開關,乙個燈,那麼這頁就只有兩個暫存器。

直接來一段**:一下**中的位址全部為0x01

先定義幾個指標和結構體:

u8 rcv_buffer[210]; //用來存放接收到的完整的一幀資料	(第乙個位元組用來存放接收到的有效位元組數,也就是陣列中的有效位元組數)

u8 send_buffer[210];//用來存放待傳送的完整的一幀資料(第乙個位元組用來存放待傳送的有效位元組數,也就是陣列中的有效位元組數)

u8 *pointtorcvbuf; //用來指向接收的資料快取

u8 *pointtosendbuf; //用來指向帶傳送的資料快取`

pointtorcvbuf=rcv_buffer;

pointtosendbuf=send_buffer;

03功能碼程式:

/* 函式功能:讀取保持暫存器	//讀取頁面的全部暫存器

函式輸入:兩個指標,pointer_1指向用來存放輸入資訊幀的陣列,

pointer_2用來指向存放輸出資訊幀的陣列(兩個陣列的第乙個元素都用來存放資訊幀的有效位元組個數)

後面的元素按照modbus協議組織。

函式輸出:無。

*/void readholdingreg(u8 *pointer_1,u8 *pointer_2)//pointer_1用作輸入,pointer_2用作輸出

//寫入校驗碼

sendkey=crc16(pointer_2+1,*pointer_2-2);

//將計算出來的校驗碼裝入輸出資料快取中

*(pointer_2+(*pointer_2-1))=(u8)(sendkey>>8);

*(pointer_2+(*pointer_2))=(u8)(sendkey&0x00ff);

//啟動資料傳送

modsend();

}else

}else

} else

}

2、10功能碼

再配著寫乙個10的

10功能碼是寫當前頁面的全部暫存器。下位機資料改變那上位機也要隨著改變,因此需要這個功能碼。

直接上**:

/* 函式功能:預製多個暫存器

函式輸入:兩個指標,pointer_1指向用來存放輸入資訊幀的陣列,

pointer_2用來指向存放輸出資訊幀的陣列(兩個陣列的第乙個元素都用來存放資訊幀的有效位元組個數)

後面的元素按照modbus協議組織。

函式輸出:無。

*/void presetmulreg(u8 *pointer_1,u8 *pointer_2)//pointer_1用作輸入,pointer_2用作輸出

else

}else

}else

}

附加:錯誤幀處理和crc校驗

函式輸入:第乙個引數mode用來指示哪一類錯誤,

pointer用來指向存放輸出資訊幀的陣列(兩個陣列的第乙個元素都用來存放資訊幀的有效位元組個數)

後面的元素按照modbus協議組織。

函式輸出:無。

*/void errorhandle(u8 mode,u8 *pointer)

*pointer=0x05;//輸出暫存器有效資料個數

*(pointer+2)|=0x80;//功能碼最高位置一

//寫入校驗碼

sendkey=crc16(pointer+1,*pointer-2);

//將計算出來的校驗碼裝入輸出資料快取中

*(pointer+(*pointer-1))=(u8)(sendkey>>8);

*(pointer+(*pointer))=(u8)(sendkey&0x00ff);

//啟動資料傳送

modsend();

printlog("error:%d\r\n",mode);

}/* 函式功能:crc校驗用函式

函式輸入:puchmsgg是要進行crc校驗的訊息,usdatalen是訊息中位元組數

函式輸出:計算出來的crc校驗碼。

*/u16 crc16(u8 *puchmsgg,u8 usdatalen)//puchmsgg是要進行crc校驗的訊息,usdatalen是訊息中位元組數

return ((uchcrchi << 8) | uchcrclo) ;}

如果有開發問題,可直接與我溝通聯絡,作者每天都會看部落格,歡迎指正。

迪文串列埠屏與STM32的通訊

最近由於學習需要,需要使用迪文串列埠屏與stm32做乙個通訊測試實驗。因為是剛接觸這兩種裝置,在一開始的時候遇到了很多困難。好在網上資源十分豐富,csdn的大佬們寫的部落格內容也十分給力,通過一段時間的學習摸索,最終完成了這個實驗。在此將這個過程和程式分享給大家,希望能對將來有需要的人提供多乙個參考...

labVIEW與微控制器實現串列埠通訊的設計過程

在現代測控系統中,我們經常會採用上位機和下位機的開發控制模式。下位機主要是用來採集資料,可以通過嵌入式控制器 微控制器 控制器 plc 等來實現。上位機主要是圖形介面,用來實時顯示採集資料,並進行資料分析及處理,同時可以控制下位機。上位機的實現可以通過各種高階語言,比如vb delphi等以及ni公...

微控制器串列埠通訊UART與USART的區別

uart與usart都是微控制器上的串列埠通信,他們之間的區別如下 首先從名字上看 uart universal asynchronous receiver and transmitter通用非同步收 髮器 usart universal synchronous asynchronous recei...