Ver código fonte

modbus的4个功能码实现

main
the_deepest 1 semana atrás
pai
commit
ab61557cea
5 arquivos alterados com 1244 adições e 932 exclusões
  1. +2
    -0
      app/main.c
  2. +1
    -1
      iar/settings/uCOS_Modbus.dnx
  3. +917
    -913
      iar/uCOS_Modbus.dep
  4. +310
    -3
      modbus/modbus.c
  5. +14
    -15
      modbus/modbus.h

+ 2
- 0
app/main.c Ver arquivo

@@ -16,6 +16,8 @@ void AppTaskModbusParse (void *p_arg);





int main()
{
Sys_Config(); /* stm32系统初始化配置 */


+ 1
- 1
iar/settings/uCOS_Modbus.dnx Ver arquivo

@@ -24,7 +24,7 @@
<stlinkResetStrategy>0</stlinkResetStrategy>
</StLinkDriver>
<DebugChecksum>
<Checksum>2329420531</Checksum>
<Checksum>3881723374</Checksum>
</DebugChecksum>
<Exceptions>
<StopOnUncaught>_ 0</StopOnUncaught>


+ 917
- 913
iar/uCOS_Modbus.dep
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 310
- 3
modbus/modbus.c Ver arquivo

@@ -4,9 +4,25 @@
#include "os.h"
#include "app_cfg.h"
#include "sys_cfg.h"
#include "string.h"
#include "modbus.h"

extern OS_EVENT* ModbusReceived; /*接收到modbus请求报文*/
extern OS_EVENT* ModbusAssembled; /*modbus响应帧组装完成*/




/*0x270F+1=K10000*/
uint8_t ModbusCoil[1250]; /*10000/8=1250*/
uint16_t ModbusReg[10000];


void AddCrc16(uint8_t *data, uint16_t length);
int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length);
uint8_t ModbusReadCoil(uint16_t addres, uint16_t num);
uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data);
uint8_t ModbusReadReg(uint16_t addres, uint16_t num);
uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data);

/*USART接收空闲中断*/
void USART1_IRQHandler(void)
@@ -73,12 +89,303 @@ void ModbusSend(uint8_t *txBuf, uint16_t len)
/*modbus协议帧解析任务*/
void AppTaskModbusParse (void *p_arg)
{
INT8U err;
MODBUS_FRAME frame;
uint16_t rxLen;
uint8_t rxBuf[256];

while(1)
{
OSTimeDly(OS_TICKS_PER_SEC);
OSSemPend(ModbusReceived, 0, &err);
rxLen = ModbusRxLen;

memcpy(rxBuf, ModbusRxBuf, rxLen);

frame.crc = ((uint16_t)(rxBuf[rxLen - 1])) | ((uint16_t)rxBuf[rxLen - 2] << 8);
if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0)
{
/****************************crc错误处理******************************/
}


frame.slaveAddres = rxBuf[0];
if(frame.slaveAddres != SLAVE_ADDRES)
{
/*****************************从机地址错误处理************************/
}


frame.func = rxBuf[1];
frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]);
frame.opeNum = ((uint16_t)rxBuf[4] << 8) | ((uint16_t)rxBuf[5]);

switch(frame.func)
{
case 0x01:/*读线圈*/
ModbusReadCoil(frame.opeAddres, frame.opeNum);

break;

case 0x03:/*读寄存器*/
ModbusReadReg(frame.opeAddres, frame.opeNum);

break;

case 0x0F:/*写多个线圈*/
frame.wNum = rxBuf[6];
memcpy(frame.wData, &rxBuf[7], frame.wNum);

ModbusWriteCoil(frame.opeAddres, frame.opeNum, frame.wData);

break;

case 0x10:/*写多个寄存器*/
frame.wNum = rxBuf[6];
memcpy(frame.wData, &rxBuf[7], frame.wNum);

ModbusWriteReg(frame.opeAddres, frame.opeNum, frame.wData);

break;

default:/*功能码错误*/



break;

}
ModbusSend(ModbusTxBuf, ModbusTxLen);
}
}

uint8_t ModbusReadCoil(uint16_t addres, uint16_t num)
{
uint16_t byteIndI;
uint8_t bitIndI;
uint16_t byteIndO;
uint8_t bitIndO;

uint8_t dataLen;

uint8_t index;
uint8_t readVal;
uint8_t writeVal;


if(addres > 0x270F || (addres + num) > 0x270F)
{
/********************地址超限处理*****************/
}


dataLen = (num + 7) / 8;

memset(&ModbusTxBuf[3], 0, 253);/*清零发送数组*/


for(uint16_t i = 0; i < num; i++)
{
byteIndO = i / 8;
bitIndO = i % 8;

byteIndI = (addres + i) / 8;
bitIndI = (addres + i) % 8;

readVal = ModbusCoil[byteIndI] & ((uint8_t)1 << bitIndI);
if(readVal != 0)
{
index = 3 + byteIndO;
writeVal = (uint8_t)1u << bitIndO;

ModbusTxBuf[index] |= writeVal;
}
}

ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = 0x01;
ModbusTxBuf[2] = dataLen;/*响应帧返回数据字节数*/
AddCrc16(ModbusTxBuf, 3 + dataLen);
ModbusTxLen = 5 + dataLen;
}

uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data)
{
uint16_t byteIndI;
uint8_t bitIndI;
uint16_t byteIndO;
uint8_t bitIndO;

uint8_t readVal;
uint8_t writeVal;


if(addres > 0x270F || (addres + num) > 0x270F)
{
/********************地址超限处理*****************/
}


for(uint16_t i = 0; i < num; i++)
{
byteIndI = (addres + i) / 8;
bitIndI = (addres + i) % 8;
byteIndO = i / 8;
bitIndO = i % 8;

readVal = data[byteIndO] | ((uint8_t)1 << bitIndO);
writeVal = (uint8_t)1 << bitIndI;


if(readVal != 0)
{
ModbusCoil[byteIndI] |= writeVal;
}
else
{
ModbusCoil[byteIndI] &= (~writeVal);
}

ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = 0x0F;
/*操作地址*/
ModbusTxBuf[2] = (uint8_t)(addres >> 8);
ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
/*成功写入的数量*/
ModbusTxBuf[4] = (uint8_t)(num >> 8);
ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
AddCrc16(ModbusTxBuf, 6);
ModbusTxLen = 8;
}
}

uint8_t ModbusReadReg(uint16_t addres, uint16_t num)
{
uint8_t index;
uint8_t readValH;
uint8_t readValL;
uint8_t dataLen;

if(addres > 0x270F || (addres + num) > 0x270F)
{
/********************地址错误处理*****************/
}


dataLen = num * 2;
for(uint16_t i = 0; i < num; i++)
{
index = 3 + (i * 2);
readValH = (uint8_t)(ModbusReg[addres + i] >> 8);
readValL = (uint8_t)(ModbusReg[addres + i] & 0x00FF);

ModbusTxBuf[index] = readValH;
ModbusTxBuf[index + 1] = readValL;
}
ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = 0x03;
ModbusTxBuf[2] = dataLen;
AddCrc16(ModbusTxBuf, 3 + dataLen);
ModbusTxLen = 5 + dataLen;
}

uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data)
{
uint8_t index;

uint8_t writeValH;
uint8_t writeValL;
uint16_t writeVal;
if(addres > 0x270F || (addres + num) > 0x270F)
{
/********************地址错误处理*****************/
}


for(uint16_t i = 0; i < num; i++)
{
index = i * 2;

writeValH = data[index];
writeValL = data[index + 1];
writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
ModbusReg[addres + i] = writeVal;
}

ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = 0x10;
/*操作地址*/
ModbusTxBuf[2] = (uint8_t)(addres >> 8);
ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
/*成功写入数量*/
ModbusTxBuf[4] = (uint8_t)(num >> 8);
ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
AddCrc16(ModbusTxBuf, 6);
ModbusTxLen = 8;
}

uint16_t Crc16(const uint8_t *data, uint16_t length);

void AddCrc16(uint8_t *data, uint16_t length)
{
uint16_t crc16 = Crc16(data, length);

/*低前高后*/
data[length] = (uint8_t)(crc16 & 0x00FF);
data[length + 1] = (uint8_t)(crc16 >> 8);
}

/*crc16校验*/
uint16_t Crc16(const uint8_t *data, uint16_t length)
{
uint16_t crc;
uint16_t byteInd;
uint8_t bitInd;
crc = 0xFFFFu;
for (byteInd = 0u; byteInd < length; byteInd++)
{
crc ^= (uint16_t)data[byteInd];
for (bitInd = 0u; bitInd < 8u; bitInd++)
{
if ((crc & 0x0001u) != 0u)
{
crc >>= 1;
crc ^= 0xA001u;
}
else
{
crc >>= 1;
}
}
}
return crc;
}

/*crc16检查*/
int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length)
{
uint16_t crc16 = Crc16(data, (length - 2));

if(recCrc16 == crc16)
{
return 0;
}
else
{
return -1;
}
}

+ 14
- 15
modbus/modbus.h Ver arquivo

@@ -3,22 +3,21 @@

#include "ucos_ii.h"

/*
* Modbus task synchronization objects.
*
* ModbusReceived:
* USART IDLE ISR -> parse task
* ModbusAssembled:
* parse task -> send task
* ModbusTxCompleted:
* USART TC ISR -> send task
* ModbusTxBufferFree:
* ownership of the single transmit buffer
*/
#define SLAVE_ADDRES 0x01

typedef struct Modbus_Frame
{
uint8_t slaveAddres; /*从机地址*/
uint8_t func; /*功能码*/
uint16_t opeAddres; /*操作地址*/
uint16_t opeNum; /*操作数量*/
uint8_t wNum; /*写入字节数*/
uint8_t wData[256]; /*写入数据*/
uint16_t crc; /*CRC校验码*/
}MODBUS_FRAME;

extern OS_EVENT *ModbusReceived;
extern OS_EVENT *ModbusAssembled;
extern OS_EVENT *ModbusTxCompleted;
extern OS_EVENT *ModbusTxBufferFree;


void AppTaskModbusParse(void *p_arg);
void AppTaskModbusSend(void *p_arg);


Carregando…
Cancelar
Salvar