首页 > 其他分享 >Modbus主机模板

Modbus主机模板

时间:2023-10-17 15:02:34浏览次数:33  
标签:MODBUS USART 主机 void InitStructure Modbus MASTER GPIO 模板

#ifndef  MODBUS_MASTER_H
#define  MODBUS_MASTER_H
#include "main.h"

#ifdef   MODBUS_MASTER_C
#include "stm32f10x_usart.h"
#include "crc.h"

#define PrioritySize 3
#define MissionSize  10

#define Bps 115200

#define RecSize     100
#define SignalDelay 50
#define BroadcastID 0x00

#define CounterMax  20000
#define WaitDelay   200
#define ErrorMax    3

#define MissionNone     0x00
#define MissionReady    0x01
#define MissionStart    0x02

#define NoneCmd  0x00
#define ReadCmd  0x01
#define WriteCmd 0x02

typedef struct{
    int*   Pointer;
    int    Last;
    uchar  ReadOrWrite;
    uchar  ID;
    ushort Addr;
    uchar  Size;
    uchar  Error;
    ushort Counter;
} MODBUS_MasterCommandType;

void MODBUS_MASTER_Deal0x03(void);
void MODBUS_MASTER_Deal0x06(void);
void MODBUS_MASTER_Deal0x10(void);

void MODBUS_MASTER_DealRead (void);
void MODBUS_MASTER_DealWrite(void);

void MODBUS_MASTER_InsertMission(MODBUS_MasterCommandType mission, uchar priority);
void MODBUS_MASTER_RemoveMission(MODBUS_MasterCommandType mission);

void MODBUS_MASTER_GetNewMission(void);

/*----------Queue----------*/
#define MODBUS_MASTER_QUEUE_ValueType MODBUS_MasterCommandType
#define MODBUS_MASTER_QUEUE_MaxSize 10

typedef struct
{
    MODBUS_MASTER_QUEUE_ValueType Value[MODBUS_MASTER_QUEUE_MaxSize];
    ushort Head;
    ushort Tail;
    ushort Size;
} MODBUS_MASTER_QUEUE_TypeDef;

void   MODBUS_MASTER_QUEUE_Push(MODBUS_MASTER_QUEUE_TypeDef* Que, MODBUS_MASTER_QUEUE_ValueType Data);
void   MODBUS_MASTER_QUEUE_Pop (MODBUS_MASTER_QUEUE_TypeDef* Que);
ushort MODBUS_MASTER_QUEUE_NextIndex(ushort curIndex);

/*----------End----------*/

#endif

extern uchar MODBUS_MASTER_ActionFlag;

void MODBUS_MASTER_Read (int* pointer);
void MODBUS_MASTER_Write(int* pointer);

void MODBUS_MASTER_Init  (void);
void MODBUS_MASTER_Action(void);

#endif
#define  MODBUS_MASTER_C
#include "modbus_master.h"

MODBUS_MASTER_QUEUE_TypeDef DirectMission;
MODBUS_MASTER_QUEUE_TypeDef DutyMission[PrioritySize];
MODBUS_MasterCommandType*   CurrentMission;

uchar MODBUS_MASTER_ActionFlag;
uchar MODBUS_MASTER_ErrorFlag;

uchar  RecByte[RecSize];
uchar  Position;
uchar  StartFlag;
ushort Counter;

ushort DutyDelay[PrioritySize];
uchar  MissionStatusFlag;

void MODBUS_MASTER_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure ;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure ;
    
    //----------DATA Init----------
    StartFlag = 0;
    Position  = 0;
    Counter   = 0;
    
    DutyDelay[0] = 100;
    DutyDelay[1] = 200;
    DutyDelay[2] = 500;
    
    MissionStatusFlag = MissionNone;
    
    //Mission
    MODBUS_MasterCommandType cmd;
    
//    cmd.Pointer     =&SERVO_DataA.speed;
//    cmd.Last        = SERVO_DataA.speed;
//    cmd.ReadOrWrite = WriteCmd;
//    cmd.ID          = 0x01;
//    cmd.Addr        = 0x0303;
//    cmd.Size        = 1;
//    MODBUS_MASTER_InsertMission(cmd, 0);
//    
//    cmd.Pointer     =&SERVO_DataA.position;
//    cmd.ReadOrWrite = ReadCmd;
//    cmd.ID          = 0x01;
//    cmd.Addr        = 0x1507;
//    cmd.Size        = 2;
//    MODBUS_MASTER_InsertMission(cmd, 1);
    
    //----------GPIO Init----------
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    //RS485
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    //Limit
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    
    //----------USART Init----------
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    
    USART_InitStructure.USART_BaudRate            = Bps;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART3, &USART_InitStructure);
    
    //----------NVIC Init----------
    NVIC_InitStructure.NVIC_IRQChannel                   = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x03;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);
    
    //----------ENABLE----------
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART3, ENABLE);
}

uchar MODBUS_MASTER_CrcCheck(void)
{
    uchar end = Position - 2;
    
    MyCRC_TypeDef crc;
    CRC_Clear(&crc);
    for(uchar i = 0; i < end; i ++)
    {
        CRC_Check(&crc, RecByte[i]);
    }

    if(RecByte[end] == crc.RegL && RecByte[end + 1] == crc.RegH)
    {
        return 0;
    }
    return 1;
}

void MODBUS_MASTER_SendData(uchar Data)
{
    while(USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET);
    USART_SendData(USART3, Data);
}

void MODBUS_MASTER_Deal0x03(void)
{
    int rtn = 0;
    for(uchar i = 0; i < (*CurrentMission).Size; i ++)
    {
        uchar p = 3 + (i << 1);
        
        rtn<<= 16;
        rtn |= RecByte[p] << 8 | RecByte[p + 1];
    }
    
    (*CurrentMission).Last  = *(*CurrentMission).Pointer = rtn;
    (*CurrentMission).Error = 0;
    MissionStatusFlag = MissionNone;
}

void MODBUS_MASTER_Deal0x06(void)
{
    (*CurrentMission).Last  = *(*CurrentMission).Pointer;
    (*CurrentMission).Error = 0;
    MissionStatusFlag = MissionNone;
}

void MODBUS_MASTER_Deal0x10(void)
{
    (*CurrentMission).Last  = *(*CurrentMission).Pointer;
    (*CurrentMission).Error = 0;
    MissionStatusFlag = MissionNone;
}

void MODBUS_MASTER_Deal0x83(void)
{
    (*CurrentMission).Error = ErrorMax;
    MissionStatusFlag = MissionNone;
}

void MODBUS_MASTER_DealRead(void)
{
    uchar array[10];
    
    array[0] = (*CurrentMission).ID;
    array[1] = 0x03;
    array[2] = (*CurrentMission).Addr >> 8;
    array[3] = (*CurrentMission).Addr;
    array[4] = 0x00;
    array[5] = (*CurrentMission).Size;
    
    MyCRC_TypeDef crc;
    CRC_Clear(&crc);
    
    for(uchar i = 0; i < 6; i ++)
    {
        MODBUS_MASTER_SendData(array[i]);
        CRC_Check(&crc, array[i]);
    }
    
    MODBUS_MASTER_SendData(crc.RegL);
    MODBUS_MASTER_SendData(crc.RegH);
    
    MissionStatusFlag = MissionStart;
    (*CurrentMission).Counter = 0;
}

void MODBUS_MASTER_DealWrite(void)
{
    if((*CurrentMission).Last != *(*CurrentMission).Pointer)
    {
        uchar array[100];
        
        array[0] = (*CurrentMission).ID;
        array[1] = 0x10;
        array[2] = (*CurrentMission).Addr >> 8;
        array[3] = (*CurrentMission).Addr;
        array[4] = 0x00;
        array[5] = (*CurrentMission).Size;
        array[6] = (*CurrentMission).Size << 1;
        
        int data = *(*CurrentMission).Pointer;
        for(uchar i = 0; i < (*CurrentMission).Size; i ++)
        {
            uchar p = 7 + (i << 1);
            array[p]   = data >> 8;
            array[p+1] = data;
            data >>= 16;
        }
        
        MyCRC_TypeDef crc;
        CRC_Clear(&crc);
        
        uchar len = 7 + ((*CurrentMission).Size << 1);
        for(uchar i = 0; i < len; i ++)
        {
            MODBUS_MASTER_SendData(array[i]);
            CRC_Check(&crc, array[i]);
        }
        
        MODBUS_MASTER_SendData(crc.RegL);
        MODBUS_MASTER_SendData(crc.RegH);
        
        MissionStatusFlag = MissionStart;
    }
    else
    {
        MissionStatusFlag = MissionNone;
    }
    
    (*CurrentMission).Counter = 0;
}

void MODBUS_MASTER_Read(int* pointer)
{
    MODBUS_MasterCommandType cmd;
    cmd.Pointer     = pointer;
    cmd.ReadOrWrite = ReadCmd;
    
    MODBUS_MASTER_QUEUE_Push(&DirectMission, cmd);
}

void MODBUS_MASTER_Write(int* pointer)
{
    MODBUS_MasterCommandType cmd;
    cmd.Pointer     =  pointer;
    cmd.Last        =!*pointer;
    cmd.ReadOrWrite = WriteCmd;
    
    MODBUS_MASTER_QUEUE_Push(&DirectMission, cmd);
}

void MODBUS_MASTER_InsertMission(MODBUS_MasterCommandType mission, uchar priority)
{
    MODBUS_MASTER_QUEUE_Push(&DutyMission[priority], mission);
}

void MODBUS_MASTER_RemoveMission(MODBUS_MasterCommandType mission)
{
    for(uchar i = 0; i < PrioritySize; i ++)
    {
        uchar j = DutyMission[i].Size;
        while(j --)
        {
            uchar p = DutyMission[i].Head;
            if(DutyMission[i].Value[p].ID == mission.ID && DutyMission[i].Value[p].Addr == mission.Addr)
            {
                MODBUS_MASTER_QUEUE_Pop(&DutyMission[i]);
                return;
            }
            else
            {
                MODBUS_MASTER_QUEUE_Push(&DutyMission[i], DutyMission[i].Value[p]);
                MODBUS_MASTER_QUEUE_Pop (&DutyMission[i]);
            }
        }
    }
}

void MODBUS_MASTER_GetNewMission(void)
{
    if(DirectMission.Size)
    {
        CurrentMission    = &DirectMission.Value[DirectMission.Head];
        MissionStatusFlag = MissionReady;
        MODBUS_MASTER_QUEUE_Pop(&DirectMission);
        return;
    }
    for(uchar i = 0; i < PrioritySize; i ++)
    {
        uchar j = DutyMission[i].Size;
        while(j--)
        {
            uchar p = DutyMission[i].Head;
            MODBUS_MASTER_QUEUE_Push(&DutyMission[i], DutyMission[i].Value[p]);
            MODBUS_MASTER_QUEUE_Pop (&DutyMission[i]);
            if(DutyMission[i].Value[p].Counter > DutyDelay[i])
            {
                CurrentMission    = &DutyMission[i].Value[p];
                MissionStatusFlag = MissionReady;
                return;
            }
        }
    }
}

void MODBUS_MASTER_Action(void)
{
    if(!MODBUS_MASTER_ActionFlag)
    {
        return;
    }
    MODBUS_MASTER_ActionFlag = 0;
    
    Counter ++;
    Counter = Min_ushort(Counter, CounterMax);
    if(Counter > SignalDelay && Position)
    {
        if(!MODBUS_MASTER_CrcCheck())
        {
            switch(RecByte[1])
            {
                case 0x03:
                {
                    MODBUS_MASTER_Deal0x03();
                }break;
                case 0x06:
                {
                    MODBUS_MASTER_Deal0x06();
                }break;
                case 0x10:
                {
                    MODBUS_MASTER_Deal0x10();
                }break;
            }
            
            StartFlag = 0;
            Position  = 0;
        }
    }
    
    for(uchar i = 0; i < PrioritySize; i ++)
    {
        uchar j = DutyMission[i].Size;
        uchar k = DutyMission[i].Head;
        while(j--)
        {
            DutyMission[i].Value[k].Counter ++;
            DutyMission[i].Value[k].Counter = Min_ushort(DutyMission[i].Value[k].Counter, CounterMax);
            k = MODBUS_MASTER_QUEUE_NextIndex(k);
        }
    }
    
    if(MissionStatusFlag == MissionStart)
    {
        if((*CurrentMission).Counter > WaitDelay)
        {
            (*CurrentMission).Error ++;
            if((*CurrentMission).Error >= ErrorMax)
            {
                MODBUS_MASTER_GetNewMission();
            }
            MissionStatusFlag = MissionReady;
        }
    }
    else
    {
        MODBUS_MASTER_GetNewMission();
    }
    
    if(MissionStatusFlag != MissionReady)
    {
        return;
    }
    
    switch((*CurrentMission).ReadOrWrite)
    {
        case NoneCmd:
        {
            
        }break;
        case ReadCmd:
        {
            MODBUS_MASTER_DealRead();
        }break;
        case WriteCmd:
        {
            MODBUS_MASTER_DealWrite();
        }break;
    }
}

void USART3_IRQHandler(void)
{
    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    {
        uchar rec = USART_ReceiveData(USART3);
        USART_ClearFlag(USART3, USART_IT_RXNE);
        
        if(Counter > SignalDelay)
        {
            StartFlag = 0;
            Position  = 0;
        }
        Counter = 0;
        
        RecByte[Position ++] = rec;
        
        if(Position >= RecSize)
        {
            StartFlag = 0;
            Position  = 0;
        }
    }
}

/*----------Queue----------*/
void MODBUS_MASTER_QUEUE_Push(MODBUS_MASTER_QUEUE_TypeDef* Que, MODBUS_MASTER_QUEUE_ValueType Data)
{
    Que->Value[Que->Tail] = Data;
    Que->Tail = (Que->Tail + 1) % MODBUS_MASTER_QUEUE_MaxSize;
    Que->Size ++;
}

void MODBUS_MASTER_QUEUE_Pop(MODBUS_MASTER_QUEUE_TypeDef* Que)
{
    Que->Head = (Que->Head + 1) % MODBUS_MASTER_QUEUE_MaxSize;
    Que->Size --;
}

ushort MODBUS_MASTER_QUEUE_NextIndex(ushort curIndex)
{
    return (curIndex + 1) % MODBUS_MASTER_QUEUE_MaxSize;
}

/*----------End----------*/

 

标签:MODBUS,USART,主机,void,InitStructure,Modbus,MASTER,GPIO,模板
From: https://www.cnblogs.com/PolarBearINBrown/p/17769700.html

相关文章

  • Oracle中如何根据查询sql片段定位查询客户端主机地址
    --1.根据sql片段获取sql_id--select*fromv$sqlwherelast_active_time>sysdateandsql_textlike'%ZL0204_03r%';selectsql_id,modulefromv$sqlwherelast_active_time>sysdateandsql_textlike'%ZL0204_03%';--2.根据sql_id查询sid......
  • React-Admin后台管理模板|react18+arco+zustand后台解决方案
    基于react18.x+vite4+arco-design自研中后台管理系统解决方案ReactAdmin。react-vite-admin基于vite4搭建react18.x后台管理项目。使用了react18hooks+arco.design+zustand+bizcharts等技术实现权限管理模板框架。支持暗黑/亮色主题、i18n国际化、动态权限鉴定、3种布局模板、t......
  • 有趣的大玩具之N4100,小主机也来玩群辉
    这款小主机很有趣。先来看看图。当时忘记备份图片,找咸鱼把图片下载回来。正面背面当时拿这个机器安装的群晖测试了一下局域网+2.5G网卡跑群晖的网速,速度还是非常不错的。晒完图啦。我先来说说优缺点。优点:1、支持type-c一线通,插一根连接显示器就可以开机显示,省去一根电......
  • [python] 使用nmap搜索主机及端口号:寻找宿舍路由
    prologue明明设置好了端口映射,但出来却发现无法远程连接宿舍的电脑,怀疑是路由器WAN网口地址变动idea很神奇的是原ip能ping通,不过也可能是被分配给其他宿舍,尝试了telnet,无果。上网搜索发现了netcat,又看到了nmap,似乎更合适solution安装好nmap,计划是先扫描主机,再扫描在线主机的2......
  • 麒麟KYLINOS2303上通过模板设置电源
    hello,大家好啊,今天给大家带来一篇在麒麟kylinOS2303上通过模板设置电源的文章,主要通过开机启动脚本实现,开机脚本内容主要为gsettings的设置,关于gestating的相关信息,请大家自行查阅相关资料获取。1、查看系统信息pdsyw@pdsyw-pc:~/桌面$cat/etc/.kyinfo[dist]name=Kylinmiles......
  • java导出占位符word模板
    实际项目中,便于维护模板,采用直接word里面制作占位符来导出更为直观,而不是将word做成tpl模板。使用XWPFDocument(这种解析xlsx或者docx)和HWPFDocument(这种解析xls或者doc)。代码如下:写磁盘代码:点击查看代码//创建Word模板文件:在开始代码编写之前,我们需要准备一个Wor......
  • [Vue]模板语法和MVVM
    模板语法分为:①插值语法、②指令语法插值语法{{xxx}}指令语法v-bind:attr='xxx' 注意v-bind:只是一种指令,指令可以有很多种。v-bind:可以简写为:<body><divid="root"><h1>插值语法</h1><h3>{{name}}</h3><hr/&g......
  • Qt/C++编写物联网组件/支持modbus/rtu/tcp/udp/websocket/mqtt/多线程采集
    一、功能特点支持多种协议,包括Modbus_Rtu_Com/Modbus_Rtu_Tcp/Modbus_Rtu_Udp/Modbus_Rtu_Web/Modbus_Tcp/Modbus_Udp/Modbus_Web等,其中web指websocket。支持多种采集通讯方式,包括串口和网络等,可自由拓展其他方式。自定义采集间隔(精确到毫秒)和超时次数,超时后自动将离线的文件......
  • 线段树模板
    线段树理解起来不难,主要是书写起来比较麻烦这里学的是董晓老师的线段树模板#include<bits/stdc++.h>usingnamespacestd;#definelcp<<1#definercp<<1|1#defineN500005intn,w[N];structnode{intl,r,sum,add;//add用于懒标记}tr[N*4];//建树,深搜递归的过......
  • 手撕Vue-编译模板数据
    经上一篇编译指令数据后,我们已经可以将指令数据编译成具体需要展示的数据了,上一篇只是编译了指令数据,还没有编译模板数据,这一篇我们就来编译模板数据。也就是{{}}这种模板的形式我们该如何编译,其实和指令数据编译的思路是一样的,废话不多说,直接上代码。改造一下buildText方法......