久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
我的ModBus主機-協議篇
[打印本頁]
作者:
qinlu123
時間:
2021-11-15 13:22
標題:
我的ModBus主機-協議篇
該章節是整個系列中最簡單的由"Modbus_Master.c"和"Modbus_Master.h"兩個文件組成。
首先來看"Modbus_Master.h"
#ifndef __MODBUSMASTER_H
#define __MODBUSMASTER_H
#include "Header.h"
#include "UartDebug.h"
#include "Delay.h"
struct ModbusMasterDevice
{
struct UartDebugMember *UDM;
uint8_t State;
uint16_t DelayTime;
uint16_t Input_Reg[8];
uint16_t Hold_Reg[8];
uint8_t RIR_Update;
uint8_t WHR_Success;
};
extern struct ModbusMasterDevice MMDPort1;
void ModBusMasterInit(void);
uint8_t WriteHoldReg(struct ModbusMasterDevice *MBM,uint8_t DeviceAddr,uint16_t Addr,uint16_t Len,uint16_t *Data);
uint8_t ReadHoldInputReg(struct ModbusMasterDevice *MBM,uint8_t DeviceAddr,uint8_t Com,uint16_t Addr,uint16_t Len);
#endif
復制代碼
該文件包含了最基本的"Header.h"和UART篇介紹的 "UartDebug.h"以及我個人最常用的"Delay.h"。
為了更方便的講解后續代碼我們首先介紹一下"Delay.c"中的三個函數。
void Set_Delay_Time(uint16_t Time,uint16_t *DelayTime_Count)
{
*DelayTime_Count=Time;
}
void DelayTimeCount_ms(uint16_t *DelayTime_Count)
{
if(*DelayTime_Count==0)
{
*DelayTime_Count=0;
}
else
{
*DelayTime_Count-=1;
}
}
uint8_t CheckDelay(uint16_t *DelayTime_Count)
{
if(*DelayTime_Count==0)
{
return 0;
}
else
{
return 1;
}
}
復制代碼
第一個函數“
void Set_Delay_Time(uint16_t Time,uint16_t *DelayTime_Count)
”就是把Time賦值給*DelayTime_Count,具體使用示例會在下文體現;
第二個函數“
void DelayTimeCount_ms(uint16_t *DelayTime_Count)
”就是把輸入的變量作累減直到0,該函數需要每隔1ms或者其他時間來周期執行;
第三個函數“
uint8_t CheckDelay(uint16_t *DelayTime_Count)
”就是查詢輸入的變量是否為0并返回相應的值,具體使用示例會在下文體現。
好了我們接著看"Modbus_Master.h"。
“struct UartDebugMember *UDM;” ModBus主機使用的端口信息;
“uint8_t State;” ModBus主機當前的工作狀態;
“uint16_t DelayTime;” 從機未響應計時;
“uint16_t Input_Reg[8];” 輸入寄存器;
“uint16_t Hold_Reg[8];” 保持寄存器;
“uint8_t RIR_Update;” 讀取輸入/保持寄存器成功標志;
“uint8_t WHR_Success;” 寫保持寄存器成功標志。
從代碼中可以看出我們的ModBus主機僅實現了讀取輸入/保持寄存器和寫保持寄存器兩個功能,因為這兩個功能最常用,其他的功能我也懶得寫了。現在看看具體代碼。
#include "Modbus_Master.h"
struct ModbusMasterDevice MMDPort1;
void ModBusMasterInit(void)
{
MMDPort1.UDM = &U_D_Uart7;
}
/*******************************************************************************
*Function Name : CRC16_CHECK
*Input :
*Return :
*Description :
*******************************************************************************/
static unsigned short int CRC16_CHECK(unsigned char *Buf, unsigned char CRC_CNT)
{
unsigned short int CRC16_Temp;
unsigned char i,j;
CRC16_Temp = 0xffff;
for (i=0;i<CRC_CNT; i++)
{
CRC16_Temp ^= Buf[i];
for (j=0;j<8;j++)
{
if (CRC16_Temp & 0x01)
CRC16_Temp = (CRC16_Temp >>1 ) ^ 0xa001;
else
CRC16_Temp = CRC16_Temp >> 1;
}
}
return CRC16_Temp;
}
uint8_t WriteHoldReg(struct ModbusMasterDevice *MBM,uint8_t DeviceAddr,uint16_t Addr,uint16_t Len,uint16_t *Data)
{
uint16_t CRC16=0;
uint16_t CRC16_Receive=0;
uint8_t i=0;
switch(MBM->State)
{
case 0:
{
MBM->UDM->TransmitBuf[0] = DeviceAddr;
MBM->UDM->TransmitBuf[1] = 0x10;
MBM->UDM->TransmitBuf[2] = Addr>>8;
MBM->UDM->TransmitBuf[3] = Addr;
MBM->UDM->TransmitBuf[4] = Len>>8;
MBM->UDM->TransmitBuf[5] = Len;
MBM->UDM->TransmitBuf[6] = Len*2;
for(i=0;i<Len;i++)
{
MBM->UDM->TransmitBuf[i*2+7] = *(Data+i)>>8;
MBM->UDM->TransmitBuf[i*2+8] = *(Data+i);
}
CRC16 = CRC16_CHECK(MBM->UDM->TransmitBuf,7+Len*2);
MBM->UDM->TransmitBuf[8+Len*2] = CRC16>>8;
MBM->UDM->TransmitBuf[7+Len*2] = CRC16;
TransmitData(MBM->UDM,MBM->UDM->TransmitBuf,9+Len*2);
Set_Delay_Time(100,&MBM->DelayTime);
MBM->State ++;
}break;
case 1:
{
if(MBM->UDM->ReceiveFinish)
{
CRC16_Receive=(MBM->UDM->ReceiveBuf[MBM->UDM->ReceivePoint-1]<<8)|MBM->UDM->ReceiveBuf[MBM->UDM->ReceivePoint-2];
CRC16 = CRC16_CHECK(MBM->UDM->ReceiveBuf,MBM->UDM->ReceivePoint-2);
if(CRC16_Receive == CRC16)
{
/*這么寫是有bug的,算了先這么著吧*/
MBM->WHR_Success = 1;
}
MBM->State = 0;
ClearRxData(MBM->UDM);
return 1;
}
else if(CheckDelay(&MBM->DelayTime) == 0)
{
MBM->State = 0;
ClearRxData(MBM->UDM);
return 1;
}
}break;
}
return 0;
}
uint8_t ReadHoldInputReg(struct ModbusMasterDevice *MBM,uint8_t DeviceAddr,uint8_t Com,uint16_t Addr,uint16_t Len)
{
uint16_t CRC16=0;
uint16_t CRC16_Receive=0;
uint8_t i=0;
switch(MBM->State)
{
case 0:
{
MBM->UDM->TransmitBuf[0] = DeviceAddr;
MBM->UDM->TransmitBuf[1] = Com;
MBM->UDM->TransmitBuf[2] = Addr>>8;
MBM->UDM->TransmitBuf[3] = Addr;
MBM->UDM->TransmitBuf[4] = Len>>8;
MBM->UDM->TransmitBuf[5] = Len;
CRC16 = CRC16_CHECK(MBM->UDM->TransmitBuf,6);
MBM->UDM->TransmitBuf[7] = CRC16>>8;
MBM->UDM->TransmitBuf[6] = CRC16;
TransmitData(MBM->UDM,MBM->UDM->TransmitBuf,8);
Set_Delay_Time(100,&MBM->DelayTime);
MBM->State ++;
}break;
case 1:
{
if(MBM->UDM->ReceiveFinish)
{
CRC16_Receive=(MBM->UDM->ReceiveBuf[MBM->UDM->ReceivePoint-1]<<8)|MBM->UDM->ReceiveBuf[MBM->UDM->ReceivePoint-2];
CRC16 = CRC16_CHECK(MBM->UDM->ReceiveBuf,MBM->UDM->ReceivePoint-2);
if(CRC16_Receive == CRC16)
{
for(i=0;i<MBM->UDM->ReceiveBuf[2]/2;i++)
{
if(Com == 0x04)
{
MBM->Input_Reg[Addr+i] = (MBM->UDM->ReceiveBuf[3+i*2])<<8 | MBM->UDM->ReceiveBuf[4+i*2];
}
else
{
MBM->Hold_Reg[Addr+i] = (MBM->UDM->ReceiveBuf[3+i*2])<<8 | MBM->UDM->ReceiveBuf[4+i*2];
}
}
MBM->RIR_Update = 1;
}
MBM->State = 0;
ClearRxData(MBM->UDM);
return 1;
}
else if(CheckDelay(&MBM->DelayTime) == 0)
{
MBM->State = 0;
ClearRxData(MBM->UDM);
return 1;
}
}break;
}
return 0;
}
復制代碼
可以看到首先定義了一個ModbusMasterDevice實體MMDPort1,然后初始化該實體將其要使用的端口與U_D_Uart7對接起來。
其余的代碼就很簡單了,需要注意的有兩個地方,一是我們把給從機發數據和接收從機數據分成了兩部分來完成。為什么要這么做呢?這是為了當從機響應不及時或者從機不在線時MCU可以去做其他的事情而不必在這里死等。二是當收到從機應答(無論CRC校驗是否成功)或者從機響應超時(這里就涉及到前文中提及的“delay”三個函數)都需要執行
ClearRxData
()并返回1,這點非常重要。
在該函數中沒有做重發機制,并不是沒有重發機制而是在更往上的層中來實現的后面會介紹到。
作者:
rfvrfv
時間:
2022-10-18 09:40
Input_Reg[Addr+i]這里代表啥寄存器?
作者:
wxcsmzh
時間:
2022-12-2 19:10
extern struct ModbusMasterDevice MMDPort1; void ModBusMasterInit(void); uint8_t WriteHoldReg(struct ModbusMasterDevice *MBM,uint8_t DeviceAddr,uint16_t Addr,uint16_t Len,uint16_t *Data); uint8_t ReadHoldInputReg(struct ModbusMasterDevice *MBM,uint8_t DeviceAddr,uint8_t Com,uint16_t Addr,uint16_t Len); #endif
作者:
woyaodwn
時間:
2023-3-2 12:14
這個基于什么芯片的啊?
作者:
liixaofei5
時間:
2023-4-16 09:45
,標記學習一下,感謝分享
作者:
qinlu123
時間:
2024-8-16 11:47
woyaodwn 發表于 2023-3-2 12:14
這個基于什么芯片的啊?
stm32,可以輕松移植到任何單片機平臺
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
国产又粗又猛
|
亚洲影视在线
|
欧美一级淫片免费视频黄
|
国产精品99久久久久久久久久久久
|
高清视频一区二区
|
黄色一级大片在线免费看国产一
|
色婷婷免费视频
|
色综合99
|
欧美日韩一二三区
|
成人一区二区视频
|
一区二区免费看
|
亚洲一区免费
|
欧美精品一区二区在线观看
|
日本一级一片免费视频
|
国产h视频在线观看
|
99视频+国产日韩欧美
|
精品久久网站
|
六月激情婷婷
|
免费成人毛片
|
最新免费黄色网址
|
久久久久久国产精品
|
欧美国产一区二区
|
国产伦精品一区二区三区视频黑人
|
国产精品一级二级
|
人人草人人草
|
中文字幕在线观看亚洲
|
操出白浆视频
|
亚洲一区二区免费视频
|
97中文字幕
|
亚洲人高潮女人毛茸茸
|
日韩精品网
|
女子spa高潮呻吟抽搐
|
精品免费国产一区二区三区四区
|
一级特黄视频
|
国产精品免费一区二区三区
|
欧美专区在线观看
|
狠狠干美女
|
能看的毛片
|
欧美一区二区三
|
一级二级毛片
|
免费成人蒂法网站
|