久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 12530|回復: 15
打印 上一主題 下一主題
收起左側

在STM32F103 C8T6上采用MODBUS協議實現開關量輸入輸出采集

  [復制鏈接]
跳轉到指定樓層
樓主
采用MODBUS協議實現開關量輸入輸出采集的程序,希望對大家有用,下載使用的時候記得回復哦

本例程是采用 MODBUS 協議實現的,為了實現 MODBUS 協議,我們移植了一個叫FREE MODBUS協議棧。關于 FREE MODBUS協議棧,在這里就不做介紹了,
   在閱讀例程之前,請大家先學習下標準 MODBUS協議,不然你無法了解功能代碼的使用。
接下來我給大家介紹如何在串口調試軟件中用MODBUS協議命令點亮從機
板子上的LED燈以及讀取板子上按鍵的狀態。
在這個例程的工程文件夾下找一個名為:ECOMV280的文件夾,打開后有一個“ECOM串口助手  V2.80.exe”的軟件和好多說明資料,請先閱讀下軟件的使用方法。等你熟悉了調試軟件的使用后,就可以連接板子進行調試了,調試板子前你首先要準備一個 RS485轉 RS232的轉換器,不然沒有辦法跟電腦連接。  
操作說明:
1、  通訊參數設置:           

注意:發送命令的時候一定要按照上圖設置,數據按 HEX格式發送,最后還要用CRC校驗。   
設置完了以后直接在數據輸入框中填寫發送的命令就行,CRC 校驗碼用戶
不用管,在發送數據時,軟件會自動在后面加上的。
3、  接收窗口設置:

注意:終端一定要設置成 HEX顯示,否則看不到返回的 代碼。
4、  數字量輸入采集指令:(采集板子上2個按鍵的狀態)
發送:01 02 00 00 00 02 38 0B   十六進制

備注:如果沒有板子按鍵按下,收到 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   十六進制

         接收: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校驗,軟件自動添加
好了,這個例程的應用操作說明就先介紹到這里,祝福大家能操作成功。


stm32單片機源程序如下:
  1. #include "stm32f10x.h"
  2. #include "sys.h"
  3. //#include "usart.h"
  4. #include "led.h"   /*------添加了IO控制端口的頭文件------*/
  5. #include "mb.h"
  6. #include "mbutils.h"

  7. //輸入寄存器起始地址
  8. #define REG_INPUT_START       0x0000
  9. //輸入寄存器數量
  10. #define REG_INPUT_NREGS       8
  11. //保持寄存器起始地址
  12. #define REG_HOLDING_START     0x0000
  13. //保持寄存器數量
  14. #define REG_HOLDING_NREGS     8

  15. //線圈起始地址
  16. #define REG_COILS_START       0x0000
  17. //線圈數量
  18. #define REG_COILS_SIZE        16

  19. //開關寄存器起始地址
  20. #define REG_DISCRETE_START    0x0000
  21. //開關寄存器數量
  22. #define REG_DISCRETE_SIZE     16


  23. /* Private variables ---------------------------------------------------------*/
  24. //輸入寄存器內容
  25. uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x0ed6,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
  26. //寄存器起始地址
  27. uint16_t usRegInputStart = REG_INPUT_START;

  28. //保持寄存器內容
  29. uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x0ed6,0x3f8e,0x147b,0x400e,0x1eb8,0x4055,0x147b,0x408e};
  30. //保持寄存器起始地址
  31. uint16_t usRegHoldingStart = REG_HOLDING_START;

  32. //線圈狀態                                                                                                                        
  33. uint8_t ucRegCoilsBuf[REG_COILS_SIZE / 8] = {0x03,0x00};  //0x03表示2個LED全亮,這是剛復位后的狀態。
  34. //開關輸入狀態
  35. uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE / 8] = {0x00,0x00};

  36. void LED_Poll(void);
  37. void Button_Poll(void);


  38. int main(void)
  39. {        
  40.    LED_Config(); //--------LED端口初始化-------------
  41.    Button_Config();        //-----按鍵端口初始化------------
  42.   eMBInit(MB_RTU, 0x02, 0x01, 9600, MB_PAR_NONE); //初始化 RTU模式 從機地址為1 USART1 9600 無校驗  
  43.   eMBEnable(); //啟動FreeModbus
  44.   while(1)
  45.         {
  46.                 eMBPoll();
  47.                 LED_Poll();
  48.                 Button_Poll();
  49.         }
  50. }


  51. void LED_Poll(void)
  52. {
  53.   uint8_t LED_Status;
  54.   LED_Status = ucRegCoilsBuf[0];
  55.   if(LED_Status & 0x01) {LED1_ON;} else {LED1_OFF;}
  56.   if(LED_Status & 0x02) {LED2_ON;} else {LED2_OFF;}
  57.   //if(LED_Status & 0x04) {LED3_ON;} else {LED3_OFF;}
  58. }

  59. void Button_Poll(void)
  60. {
  61.   
  62.   uint8_t Button_Status = 0x00;  
  63.   BUTTON1_READ()?(Button_Status &=~ 0x01):(Button_Status |= 0x01);
  64.   BUTTON2_READ()?(Button_Status &=~ 0x02):(Button_Status |= 0x02);
  65.   //BUTTON3_READ()?(Button_Status &=~ 0x04):(Button_Status |= 0x04);   
  66.   ucRegDiscreteBuf[0] = Button_Status;
  67. }
  68. /**
  69.   * @brief  輸入寄存器處理函數,輸入寄存器可讀,但不可寫。
  70.   * @param  pucRegBuffer  返回數據指針
  71.   *         usAddress     寄存器起始地址
  72.   *         usNRegs       寄存器長度
  73.   * @retval eStatus       寄存器狀態
  74.   */
  75. eMBErrorCode
  76. eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
  77. {
  78.   eMBErrorCode    eStatus = MB_ENOERR;
  79.   int16_t         iRegIndex;
  80.   
  81.   //查詢是否在寄存器范圍內
  82.   //為了避免警告,修改為有符號整數
  83.   if( ( (int16_t)usAddress >= REG_INPUT_START ) \
  84.         && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
  85.   {
  86.     //獲得操作偏移量,本次操作起始地址-輸入寄存器的初始地址
  87.     iRegIndex = ( int16_t )( usAddress - usRegInputStart );
  88.     //逐個賦值
  89.     while( usNRegs > 0 )
  90.     {
  91.       //賦值高字節
  92.       *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] >> 8 );
  93.       //賦值低字節
  94.       *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] & 0xFF );
  95.       //偏移量增加
  96.       iRegIndex++;
  97.       //被操作寄存器數量遞減
  98.       usNRegs--;
  99.     }
  100.   }
  101.   else
  102.   {
  103.     //返回錯誤狀態,無寄存器  
  104.     eStatus = MB_ENOREG;
  105.   }

  106.   return eStatus;
  107. }

  108. /**
  109.   * @brief  保持寄存器處理函數,保持寄存器可讀,可讀可寫
  110.   * @param  pucRegBuffer  讀操作時--返回數據指針,寫操作時--輸入數據指針
  111.   *         usAddress     寄存器起始地址
  112.   *         usNRegs       寄存器長度
  113.   *         eMode         操作方式,讀或者寫
  114.   * @retval eStatus       寄存器狀態
  115.   */
  116. eMBErrorCode
  117. eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
  118.                  eMBRegisterMode eMode )
  119. {
  120.   //錯誤狀態
  121.   eMBErrorCode    eStatus = MB_ENOERR;
  122.   //偏移量
  123.   int16_t         iRegIndex;
  124.   
  125.   //判斷寄存器是不是在范圍內
  126.   if( ( (int16_t)usAddress >= REG_HOLDING_START ) \
  127.      && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
  128.   {
  129.     //計算偏移量
  130.     iRegIndex = ( int16_t )( usAddress - usRegHoldingStart );
  131.    
  132.     switch ( eMode )
  133.     {
  134.       //讀處理函數  
  135.       case MB_REG_READ:
  136.         while( usNRegs > 0 )
  137.         {
  138.           *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] >> 8 );
  139.           *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] & 0xFF );
  140.           iRegIndex++;
  141.           usNRegs--;
  142.         }
  143.         break;

  144.       //寫處理函數
  145.       case MB_REG_WRITE:
  146.         while( usNRegs > 0 )
  147.         {
  148.           usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
  149.           usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
  150.           iRegIndex++;
  151.           usNRegs--;
  152.         }
  153.         break;
  154.      }
  155.   }
  156.   else
  157.   {
  158.     //返回錯誤狀態
  159.     eStatus = MB_ENOREG;
  160.   }
  161.   
  162.   return eStatus;
  163. }


  164. /**
  165.   * @brief  線圈寄存器處理函數,線圈寄存器可讀,可讀可寫
  166.   * @param  pucRegBuffer  讀操作---返回數據指針,寫操作--返回數據指針
  167.   *         usAddress     寄存器起始地址
  168.   *         usNRegs       寄存器長度
  169.   *         eMode         操作方式,讀或者寫
  170.   * @retval eStatus       寄存器狀態
  171.   */
  172. eMBErrorCode
  173. eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
  174.                eMBRegisterMode eMode )
  175. {
  176.   //錯誤狀態
  177.   eMBErrorCode    eStatus = MB_ENOERR;
  178.   //寄存器個數
  179.   int16_t         iNCoils = ( int16_t )usNCoils;
  180.   //寄存器偏移量
  181.   int16_t         usBitOffset;

  182.   //檢查寄存器是否在指定范圍內
  183.   if( ( (int16_t)usAddress >= REG_COILS_START ) &&
  184.         ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
  185.   {
  186.     //計算寄存器偏移量
  187.     usBitOffset = ( int16_t )( usAddress - REG_COILS_START );
  188.     switch ( eMode )
  189.     {
  190.       //讀操作
  191.       case MB_REG_READ:
  192.         while( iNCoils > 0 )
  193.         {
  194.           *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
  195.                                           ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
  196.           iNCoils -= 8;
  197.           usBitOffset += 8;
  198.         }
  199.         break;

  200.       //寫操作
  201.       case MB_REG_WRITE:
  202.         while( iNCoils > 0 )
  203.         {
  204.           xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
  205.                         ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
  206.                         *pucRegBuffer++ );
  207.           iNCoils -= 8;
  208.         }
  209.         break;
  210.     }

  211.   }
  212.   else
  213.   {
  214.     eStatus = MB_ENOREG;
  215.   }
  216.   return eStatus;
  217. }

  218. eMBErrorCode
  219. eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
  220. {
  221. ……………………

  222. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:

ECOMV280調試軟件.zip

1.46 MB, 下載次數: 170, 下載積分: 黑幣 -5

1

采用MODBUS協議實現開關量輸入輸出采集例程說明.pdf

237.43 KB, 下載次數: 212, 下載積分: 黑幣 -5

2

多塊板子利用485總線 采用MODBUS協議實現開關量采集與控制采集.zip

403.35 KB, 下載次數: 307, 下載積分: 黑幣 -5

3

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏13 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:368549 發表于 2018-7-10 11:20 | 只看該作者
來看看,學習學習
回復

使用道具 舉報

板凳
ID:122622 發表于 2018-12-20 21:47 | 只看該作者
正在學習485轉開關量,參考一下,在此感謝樓主的辛勤勞動。
回復

使用道具 舉報

地板
ID:122622 發表于 2018-12-20 21:50 | 只看該作者
參考一下,謝謝樓主。
回復

使用道具 舉報

5#
ID:354798 發表于 2019-4-11 14:45 | 只看該作者
好的,希望對我們有用
回復

使用道具 舉報

6#
ID:160930 發表于 2019-5-24 16:29 | 只看該作者
謝謝分享。最近正好用得到
回復

使用道具 舉報

7#
ID:570893 發表于 2019-6-24 15:36 | 只看該作者
正在學習modbus,學習一下
回復

使用道具 舉報

8#
ID:284642 發表于 2020-2-5 21:55 | 只看該作者
感謝分享,希望對我有用
回復

使用道具 舉報

9#
ID:624009 發表于 2020-2-6 16:56 | 只看該作者
謝謝分享
回復

使用道具 舉報

10#
ID:108573 發表于 2020-2-9 10:26 | 只看該作者
工業最常用的通訊協議,學習一下
回復

使用道具 舉報

11#
ID:140644 發表于 2020-2-9 19:10 | 只看該作者
工業觸摸屏怎么用
回復

使用道具 舉報

12#
ID:142383 發表于 2020-2-19 19:56 | 只看該作者
感謝樓主分享,正在學習STM32視頻,下載學習。
回復

使用道具 舉報

13#
ID:605030 發表于 2021-3-19 15:23 | 只看該作者
這是個好東西,學習了
回復

使用道具 舉報

14#
ID:313601 發表于 2021-5-13 17:18 | 只看該作者
工業最常用的通訊協議,學習一下。
回復

使用道具 舉報

15#
ID:65633 發表于 2021-5-17 14:45 | 只看該作者
是一篇很好的學習資料
回復

使用道具 舉報

16#
ID:205436 發表于 2024-10-19 08:25 | 只看該作者
感謝分享!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 美女中文字幕视频 | 日韩视频三区 | 精品国产乱码久久久久久中文 | 欧美日韩在线视频一区 | 国产亚洲精品综合一区 | 亚洲天堂一区 | 国产在线高清 | 天天舔天天 | 国产在线h | 欧美一区二区在线观看 | 国产一区二区三区高清 | 热re99久久精品国产99热 | 一区二区三区在线 | 欧 | 久久综合久久综合久久综合 | 日一区二区三区 | 免费看一区二区三区 | 亚洲h在线观看 | 久久久xxx| 欧美激情国产精品 | 久久久久久综合 | 久久精品亚洲欧美日韩精品中文字幕 | 中文字幕亚洲欧美日韩在线不卡 | 日韩三级电影一区二区 | av免费电影在线 | 91久久久精品国产一区二区蜜臀 | 午夜欧美| 午夜爱爱毛片xxxx视频免费看 | 亚洲精品美女在线观看 | 黄色网址免费在线观看 | 国产精品无码永久免费888 | 91精品国产综合久久久久久漫画 | 久久人爽爽人爽爽 | 欧美日韩国产欧美 | 欧美一区二区三区视频在线 | 我要看免费一级毛片 | 毛片在线免费 | gav成人免费播放视频 | av天天干 | 亚洲高清视频在线观看 | 久草视频观看 | 中文字幕一区二区三区四区五区 |