Modbus主机模板

发布时间 2023-10-17 15:00:54作者: 棕色的北极熊
#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----------*/