|
采用MODBUS協議實現開關量輸入輸出采集的程序,希望對大家有用,下載使用的時候記得回復哦
本例程是采用 MODBUS 協議實現的,為了實現 MODBUS 協議,我們移植了一個叫FREE MODBUS協議棧。關于 FREE MODBUS協議棧,在這里就不做介紹了,
在閱讀例程之前,請大家先學習下標準 MODBUS協議,不然你無法了解功能代碼的使用。
接下來我給大家介紹如何在串口調試軟件中用MODBUS協議命令點亮從機
板子上的LED燈以及讀取板子上按鍵的狀態。
在這個例程的工程文件夾下找一個名為:ECOMV280的文件夾,打開后有一個“ECOM串口助手 V2.80.exe”的軟件和好多說明資料,請先閱讀下軟件的使用方法。等你熟悉了調試軟件的使用后,就可以連接板子進行調試了,調試板子前你首先要準備一個 RS485轉 RS232的轉換器,不然沒有辦法跟電腦連接。
操作說明:
1、 通訊參數設置:
0.jpg (11.87 KB, 下載次數: 66)
下載附件
2017-12-19 16:35 上傳
0.jpg (20.98 KB, 下載次數: 86)
下載附件
2017-12-19 16:36 上傳
注意:發送命令的時候一定要按照上圖設置,數據按 HEX格式發送,最后還要用CRC校驗。
設置完了以后直接在數據輸入框中填寫發送的命令就行,CRC 校驗碼用戶
不用管,在發送數據時,軟件會自動在后面加上的。
3、 接收窗口設置:
0.jpg (8.14 KB, 下載次數: 71)
下載附件
2017-12-19 16:36 上傳
注意:終端一定要設置成 HEX顯示,否則看不到返回的 代碼。
4、 數字量輸入采集指令:(采集板子上2個按鍵的狀態)
發送:01 02 00 00 00 02 38 0B 十六進制
0.jpg (40.48 KB, 下載次數: 82)
下載附件
2017-12-19 16:37 上傳
0.png (22.89 KB, 下載次數: 68)
下載附件
2017-12-19 16:37 上傳
備注:如果沒有板子按鍵按下,收到 01 02 01 00 A1 88
板子上按鍵KEY1按下,收到01 02 01 01 60 48
板子上按鍵KEY2按下,收到01 02 01 02 20 49
注意:發送時在數據框中只填入紅色部分數據,藍色部分為 CRC校驗,軟件自動添加。
讀取的數據是一個字節,轉化為二進制為 8 個位 0000 0000 我們的 3 個
按鍵的狀態對應為:KEY1對應D0位,KEY2對應D1位。
如果按鍵按下對應的位為 1,如果按鍵沒有按下對應的位為0。
5、 數字量輸出控制指令:(控制板子上2個LED燈)
發送:01 0F 00 00 00 02 01 00 8F 57 十六進制
0.jpg (37.46 KB, 下載次數: 75)
下載附件
2017-12-19 16:38 上傳
接收:01 0F 00 00 00 02 15 CA 十六進制
寫入的一個字節數據轉換成二進制為 8個位 0000 0000,LED1對應DO,
LED2對應D1。 “1”表示點亮LED, “0”表示熄滅LED,
例如發送:01 0F 00 00 00 02 01 01 4E 97 表示點亮LED1.
發送:01 0F 00 00 00 02 01 02 0E 96 表示點亮LED2
發送:01 0F 00 00 00 02 01 00 8F 57 表示熄滅所有LED
注意:發送時在數據框中只填入紅色部分數據,藍色部分為CRC校驗,軟件自動添加
好了,這個例程的應用操作說明就先介紹到這里,祝福大家能操作成功。
0.jpg (54.76 KB, 下載次數: 75)
下載附件
2017-12-19 16:39 上傳
0.jpg (58.43 KB, 下載次數: 64)
下載附件
2017-12-19 16:34 上傳
stm32單片機源程序如下:
- #include "stm32f10x.h"
- #include "sys.h"
- //#include "usart.h"
- #include "led.h" /*------添加了IO控制端口的頭文件------*/
- #include "mb.h"
- #include "mbutils.h"
- //輸入寄存器起始地址
- #define REG_INPUT_START 0x0000
- //輸入寄存器數量
- #define REG_INPUT_NREGS 8
- //保持寄存器起始地址
- #define REG_HOLDING_START 0x0000
- //保持寄存器數量
- #define REG_HOLDING_NREGS 8
- //線圈起始地址
- #define REG_COILS_START 0x0000
- //線圈數量
- #define REG_COILS_SIZE 16
- //開關寄存器起始地址
- #define REG_DISCRETE_START 0x0000
- //開關寄存器數量
- #define REG_DISCRETE_SIZE 16
- /* Private variables ---------------------------------------------------------*/
- //輸入寄存器內容
- uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x0ed6,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
- //寄存器起始地址
- uint16_t usRegInputStart = REG_INPUT_START;
- //保持寄存器內容
- uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x0ed6,0x3f8e,0x147b,0x400e,0x1eb8,0x4055,0x147b,0x408e};
- //保持寄存器起始地址
- uint16_t usRegHoldingStart = REG_HOLDING_START;
- //線圈狀態
- uint8_t ucRegCoilsBuf[REG_COILS_SIZE / 8] = {0x03,0x00}; //0x03表示2個LED全亮,這是剛復位后的狀態。
- //開關輸入狀態
- uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE / 8] = {0x00,0x00};
- void LED_Poll(void);
- void Button_Poll(void);
- int main(void)
- {
- LED_Config(); //--------LED端口初始化-------------
- Button_Config(); //-----按鍵端口初始化------------
- eMBInit(MB_RTU, 0x02, 0x01, 9600, MB_PAR_NONE); //初始化 RTU模式 從機地址為1 USART1 9600 無校驗
- eMBEnable(); //啟動FreeModbus
- while(1)
- {
- eMBPoll();
- LED_Poll();
- Button_Poll();
- }
- }
- void LED_Poll(void)
- {
- uint8_t LED_Status;
- LED_Status = ucRegCoilsBuf[0];
- if(LED_Status & 0x01) {LED1_ON;} else {LED1_OFF;}
- if(LED_Status & 0x02) {LED2_ON;} else {LED2_OFF;}
- //if(LED_Status & 0x04) {LED3_ON;} else {LED3_OFF;}
- }
- void Button_Poll(void)
- {
-
- uint8_t Button_Status = 0x00;
- BUTTON1_READ()?(Button_Status &=~ 0x01):(Button_Status |= 0x01);
- BUTTON2_READ()?(Button_Status &=~ 0x02):(Button_Status |= 0x02);
- //BUTTON3_READ()?(Button_Status &=~ 0x04):(Button_Status |= 0x04);
- ucRegDiscreteBuf[0] = Button_Status;
- }
- /**
- * @brief 輸入寄存器處理函數,輸入寄存器可讀,但不可寫。
- * @param pucRegBuffer 返回數據指針
- * usAddress 寄存器起始地址
- * usNRegs 寄存器長度
- * @retval eStatus 寄存器狀態
- */
- eMBErrorCode
- eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int16_t iRegIndex;
-
- //查詢是否在寄存器范圍內
- //為了避免警告,修改為有符號整數
- if( ( (int16_t)usAddress >= REG_INPUT_START ) \
- && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
- {
- //獲得操作偏移量,本次操作起始地址-輸入寄存器的初始地址
- iRegIndex = ( int16_t )( usAddress - usRegInputStart );
- //逐個賦值
- while( usNRegs > 0 )
- {
- //賦值高字節
- *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] >> 8 );
- //賦值低字節
- *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] & 0xFF );
- //偏移量增加
- iRegIndex++;
- //被操作寄存器數量遞減
- usNRegs--;
- }
- }
- else
- {
- //返回錯誤狀態,無寄存器
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /**
- * @brief 保持寄存器處理函數,保持寄存器可讀,可讀可寫
- * @param pucRegBuffer 讀操作時--返回數據指針,寫操作時--輸入數據指針
- * usAddress 寄存器起始地址
- * usNRegs 寄存器長度
- * eMode 操作方式,讀或者寫
- * @retval eStatus 寄存器狀態
- */
- eMBErrorCode
- eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
- eMBRegisterMode eMode )
- {
- //錯誤狀態
- eMBErrorCode eStatus = MB_ENOERR;
- //偏移量
- int16_t iRegIndex;
-
- //判斷寄存器是不是在范圍內
- if( ( (int16_t)usAddress >= REG_HOLDING_START ) \
- && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
- {
- //計算偏移量
- iRegIndex = ( int16_t )( usAddress - usRegHoldingStart );
-
- switch ( eMode )
- {
- //讀處理函數
- case MB_REG_READ:
- while( usNRegs > 0 )
- {
- *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] & 0xFF );
- iRegIndex++;
- usNRegs--;
- }
- break;
- //寫處理函數
- case MB_REG_WRITE:
- while( usNRegs > 0 )
- {
- usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- break;
- }
- }
- else
- {
- //返回錯誤狀態
- eStatus = MB_ENOREG;
- }
-
- return eStatus;
- }
- /**
- * @brief 線圈寄存器處理函數,線圈寄存器可讀,可讀可寫
- * @param pucRegBuffer 讀操作---返回數據指針,寫操作--返回數據指針
- * usAddress 寄存器起始地址
- * usNRegs 寄存器長度
- * eMode 操作方式,讀或者寫
- * @retval eStatus 寄存器狀態
- */
- eMBErrorCode
- eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
- eMBRegisterMode eMode )
- {
- //錯誤狀態
- eMBErrorCode eStatus = MB_ENOERR;
- //寄存器個數
- int16_t iNCoils = ( int16_t )usNCoils;
- //寄存器偏移量
- int16_t usBitOffset;
- //檢查寄存器是否在指定范圍內
- if( ( (int16_t)usAddress >= REG_COILS_START ) &&
- ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
- {
- //計算寄存器偏移量
- usBitOffset = ( int16_t )( usAddress - REG_COILS_START );
- switch ( eMode )
- {
- //讀操作
- case MB_REG_READ:
- while( iNCoils > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
- iNCoils -= 8;
- usBitOffset += 8;
- }
- break;
- //寫操作
- case MB_REG_WRITE:
- while( iNCoils > 0 )
- {
- xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
- *pucRegBuffer++ );
- iNCoils -= 8;
- }
- break;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- eMBErrorCode
- eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
|
評分
-
查看全部評分
|