Bläddra i källkod

更改代码结构,修改flash写入功能,添加3.5帧间隔功能

main
the_deepest 3 dagar sedan
förälder
incheckning
5f5b18b00e
12 ändrade filer med 1113 tillägg och 1717 borttagningar
  1. +2
    -1
      app/inc/hardware.h
  2. +1
    -1
      app/main.h
  3. +32
    -1
      app/src/hardware.c
  4. +13
    -10
      iar/settings/F407_uCOSii_Modbus.wsdt
  5. +15
    -14
      iar/settings/uCOS_Modbus.dnx
  6. +991
    -941
      iar/uCOS_Modbus.dep
  7. +10
    -4
      iar/uCOS_Modbus.ewp
  8. +10
    -4
      iar/uCOS_Modbus.ewt
  9. +0
    -680
      modbus/modbus.c
  10. +0
    -57
      modbus/modbus.h
  11. +26
    -4
      modbus/modbus_flash.c
  12. +13
    -0
      modbus/modbus_rec_send.h

+ 2
- 1
app/inc/hardware.h Visa fil

@@ -1,8 +1,9 @@
#ifndef __HARDWARE_H
#define __HARDWARE_H

#include"modbus.h"
#include"modbus_parse.h"

#define MODBUS_IDLE_TO_T35_US 1664U /*1664=1750-86*/

extern uint8_t ModbusRxBuf[MODBUS_RX_BUF_SIZE];
extern uint8_t ModbusTxBuf[MODBUS_TX_BUF_SIZE];


+ 1
- 1
app/main.h Visa fil

@@ -9,7 +9,7 @@
#include "os.h"
#include "app_cfg.h"
#include "sys_cfg.h"
#include "modbus.h"
#include "modbus_parse.h"
#include "modbus_flash.h"
#include "string.h"



+ 32
- 1
app/src/hardware.c Visa fil

@@ -101,15 +101,45 @@ void ModbusDmaInit(void)
DMA_Cmd(DMA2_Stream2, ENABLE); /*使能DMA的接收通道,发送通道暂不使能*/
}


void ModbusTimInit(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

TIM_DeInit(TIM5);
TIM_TimeBaseStructure.TIM_Prescaler = 84U - 1U; /*84Mhz/84=1Mhz,1us计时*/
TIM_TimeBaseStructure.TIM_Period = MODBUS_IDLE_TO_T35_US - 1U; /*计时周期1664us*/
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /*向上计数*/
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

TIM_SelectOnePulseMode(TIM5, TIM_OPMode_Single); /*单脉冲模式,计时完成后自动停止*/
TIM_ClearITPendingBit(TIM5, TIM_IT_Update); /*清除初始化产生的标志位*/
TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE); /*使能TIM5更新中断*/
TIM_Cmd(TIM5, DISABLE);
}

void ModbusNvicInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/*串口空闲中断*/
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; /*抢占优先级5*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; /*抢占优先级5*/
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /*响应优先级0*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/*定时器中断*/
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}


@@ -121,5 +151,6 @@ void ModbusHardwareInit(void)
ModbusGpioInit();
ModbusUsartInit();
ModbusDmaInit();
ModbusTimInit();
ModbusNvicInit();
}

+ 13
- 10
iar/settings/F407_uCOSii_Modbus.wsdt
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 15
- 14
iar/settings/uCOS_Modbus.dnx Visa fil

@@ -16,15 +16,15 @@
<ShowSource>1</ShowSource>
</Trace1>
<StLinkDriver>
<stlinkserialNo>24230357</stlinkserialNo>
<stlinkserialNo>30303031</stlinkserialNo>
<stlinkfoundProbes />
<stlinkResetStyle>0</stlinkResetStyle>
<stlinkResetStrategy>0</stlinkResetStrategy>
<CStepIntDis>_ 0</CStepIntDis>
<LeaveTargetRunning>_ 0</LeaveTargetRunning>
<stlinkResetStyle>0</stlinkResetStyle>
<stlinkResetStrategy>0</stlinkResetStrategy>
</StLinkDriver>
<DebugChecksum>
<Checksum>2248251518</Checksum>
<Checksum>363296300</Checksum>
</DebugChecksum>
<Exceptions>
<StopOnUncaught>_ 0</StopOnUncaught>
@@ -120,6 +120,13 @@
<ShowTimeSum>1</ShowTimeSum>
<SumSortOrder>0</SumSortOrder>
</EventLog>
<DisassembleMode>
<mode>0</mode>
</DisassembleMode>
<Breakpoints2>
<Bp0>_ 1 "EMUL_CODE" "{$PROJ_DIR$\..\modbus\modbus_parse.c}.67.13" 0 0 1 "" 0 "" 0</Bp0>
<Count>1</Count>
</Breakpoints2>
<TermIOLog>
<LoggingEnabled>_ 0</LoggingEnabled>
<LogFile>_ ""</LogFile>
@@ -129,6 +136,10 @@
<LogFile>_ ""</LogFile>
<Category>_ 0</Category>
</LogFile>
<Aliases>
<Count>0</Count>
<SuppressDialog>0</SuppressDialog>
</Aliases>
<DriverProfiling>
<Enabled>0</Enabled>
<Mode>3</Mode>
@@ -142,14 +153,4 @@
<CallStackStripe>
<ShowTiming>1</ShowTiming>
</CallStackStripe>
<DisassembleMode>
<mode>0</mode>
</DisassembleMode>
<Breakpoints2>
<Count>0</Count>
</Breakpoints2>
<Aliases>
<Count>0</Count>
<SuppressDialog>0</SuppressDialog>
</Aliases>
</settings>

+ 991
- 941
iar/uCOS_Modbus.dep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 10
- 4
iar/uCOS_Modbus.ewp Visa fil

@@ -2344,19 +2344,25 @@
<group>
<name>inc</name>
<file>
<name>$PROJ_DIR$\..\modbus\modbus.h</name>
<name>$PROJ_DIR$\..\modbus\modbus_flash.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_flash.h</name>
<name>$PROJ_DIR$\..\modbus\modbus_parse.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_rec_send.h</name>
</file>
</group>
<group>
<name>src</name>
<file>
<name>$PROJ_DIR$\..\modbus\modbus.c</name>
<name>$PROJ_DIR$\..\modbus\modbus_flash.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_flash.c</name>
<name>$PROJ_DIR$\..\modbus\modbus_parse.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_rec_send.c</name>
</file>
</group>
</group>


+ 10
- 4
iar/uCOS_Modbus.ewt Visa fil

@@ -2602,19 +2602,25 @@
<group>
<name>inc</name>
<file>
<name>$PROJ_DIR$\..\modbus\modbus.h</name>
<name>$PROJ_DIR$\..\modbus\modbus_flash.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_flash.h</name>
<name>$PROJ_DIR$\..\modbus\modbus_parse.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_rec_send.h</name>
</file>
</group>
<group>
<name>src</name>
<file>
<name>$PROJ_DIR$\..\modbus\modbus.c</name>
<name>$PROJ_DIR$\..\modbus\modbus_flash.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_flash.c</name>
<name>$PROJ_DIR$\..\modbus\modbus_parse.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\modbus\modbus_rec_send.c</name>
</file>
</group>
</group>


+ 0
- 680
modbus/modbus.c Visa fil

@@ -1,680 +0,0 @@
#include "stm32f4xx.h"
#include "ucos_ii.h"
#include "os.h"
#include "string.h"
#include "modbus.h"

extern OS_EVENT* ModbusWriteFlash; /*接收到modbus写入coil请求报文*/
extern OS_EVENT* ModbusConnect; /*已接收到modbus正确报文*/

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

/*附加功能:页寄存器*/
uint16_t ModbusExtPage[1] = {0}; /*设置地址为0xFFFE*/
uint16_t ModbusExtReg[1]; /*地址映射为0x10000*/
/*附加功能:读取所有单数个寄存器*/
uint16_t ModbusExtOdd[1] = {0}; /*设置地址为0xFFFF*/

uint8_t ModbusRxBuf[MODBUS_RX_BUF_SIZE]; /*接收数组*/
uint16_t ModbusRxLen = 0; /*接收数据长度*/
uint8_t ModbusTxBuf[MODBUS_TX_BUF_SIZE]; /*发送数组*/
uint16_t ModbusTxLen = 0; /*发送数据长度*/


/*modbus协议帧解析任务*/
void AppTaskModbusParse (void *p_arg)
{
OS_ERR err;
MODBUS_FRAME frame;
uint16_t rxLen;
uint8_t rxBuf[256];

while(1)
{
/*无限期等待接收到数据帧信号量*/
OSSemPend(ModbusReceived, 0, &err);
/*数据接收,防止下一帧覆盖*/
rxLen = ModbusRxLen;
memcpy(rxBuf, ModbusRxBuf, rxLen);

/*帧分解*/
frame.slaveAddres = rxBuf[0];
frame.func = rxBuf[1];
frame.crc = ((uint16_t)(rxBuf[rxLen - 2])) | ((uint16_t)rxBuf[rxLen - 1] << 8);
frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]);
frame.opeNum = ((uint16_t)rxBuf[4] << 8) | ((uint16_t)rxBuf[5]);

/*crc校验判断*/
if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0)
{
/*crc校验错误,直接丢弃*/
ModbusErr = ERR_CRC;
continue;
}
/*从机地址判断*/
if(frame.slaveAddres != SLAVE_ADDRES)
{
/*从机地址错误,直接丢弃*/
ModbusErr = ERR_SLAVE_ADDRES;
continue;
}
/*释放正确接收信号量*/
OSSemPost(ModbusConnect);

/*功能码分类*/
switch(frame.func)
{
case 0x01:/*读线圈*/
ModbusErr = ModbusReadCoils(frame.opeAddres, frame.opeNum);
break;

case 0x03:/*读寄存器*/
ModbusErr = ModbusReadRegs(frame.opeAddres, frame.opeNum);
break;

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

case 0x10:/*写多个寄存器*/
frame.wNum = rxBuf[6];
memcpy(frame.wData, &rxBuf[7], frame.wNum);
ModbusErr = ModbusWriteRegs(frame.opeAddres, frame.opeNum, frame.wData);
break;
case 0x05:/*写单个线圈*/
memcpy(frame.wData, &rxBuf[4], 2);
ModbusErr = ModbusWriteCoil(frame.opeAddres, frame.wData);
break;

case 0x06:/*写单个寄存器*/
memcpy(frame.wData, &rxBuf[4], 2);
ModbusErr = ModbusWriteReg(frame.opeAddres, frame.wData);
break;

default:/*功能码错误*/
ModbusErr = ERR_FUNC;
ModbusErr = ModbusErrReply(frame.func, ERR_FUNC);
break;
}
/*实现附加功能时不在这里启动发送*/
if(frame.func == 0x03 && frame.opeAddres == 0XFFFF);
else
{
ModbusSend(ModbusTxBuf, ModbusTxLen);
}

if(ModbusErr == 0 && (frame.func == 0x0F || frame.func == 0x10
|| frame.func == 0x05 || frame.func == 0x06))
{
/*释放写FLASH信号量*/
OSSemPost(ModbusWriteFlash);
}
}
}

uint8_t ModbusReadCoils(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(ModbusRxLen < 8)
{
return ModbusErrReply(0x01, ERR_DATA);
}
/*操作地址超限*/
if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
{
return ModbusErrReply(0x01, ERR_OPE_ADDRES);
}
/*操作数量超限*/
if(num == 0 || num > 2000)
{
return ModbusErrReply(0x01, ERR_DATA);
}

/*不能num/8+1,当为8的整数时会多一个*/
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);
/*读取到的值为0则不进行操作*/
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;

return 0;
}

uint8_t ModbusWriteCoils(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(ModbusRxLen < 10)
{
return ModbusErrReply(0x0F, ERR_DATA);
}
/*操作地址超限*/
if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
{
return ModbusErrReply(0x0F, ERR_OPE_ADDRES);
}
/*操作数量超限*/
if(num == 0 || num > 1968)
{
return ModbusErrReply(0x0F, ERR_DATA);
}
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;

/*对应位写入1*/
if(readVal != 0)
{
ModbusCoil[byteIndI] |= writeVal;
}
/*对应位写入0*/
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;

return 0;
}

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

if(ModbusRxLen < 8)
{
return ModbusErrReply(0x13, ERR_DATA);
}
/*操作地址超限*/
if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
{
if(addres == 0xFFFF && num == 1)
{
;
}
else
{
return ModbusErrReply(0x03, ERR_OPE_ADDRES);
}
}
/*操作数量超限*/
if(num == 0 || num > 125)
{
return ModbusErrReply(0x03, ERR_DATA);
}

dataLen = num * 2;
/*附加功能:读取0x10000寄存器*/
if(ModbusExtPage[0] == 1 && addres == 0x0000)
{
/*将16位寄存器值拆分为两个8位*/
readValH = (uint8_t)(ModbusExtReg[0] >> 8);
readValL = (uint8_t)(ModbusExtReg[0] & 0x00FF);

ModbusTxBuf[3] = readValH;
ModbusTxBuf[4] = readValL;
}
/*附加功能:读取大量奇数寄存器*/
else if(addres == 0xFFFF && num == 1)
{
return ModbusExtReadOdd(ModbusExtOdd[0]);
}
else
{
for(uint16_t i = 0; i < num; i++)
{
index = 3 + (i * 2);
/*将16位寄存器值拆分为两个8位*/
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;

return 0;
}

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

uint8_t writeValH;
uint8_t writeValL;
uint16_t writeVal;

if(ModbusRxLen < 11)
{
return ModbusErrReply(0x10, ERR_DATA);
}
/*操作地址超限*/
if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
{
if((addres == 0xFFFE || addres == 0xFFFF) && num == 1)
{
;
}
else
{
return ModbusErrReply(0x10, ERR_OPE_ADDRES);
}
}
/*操作数量超限*/
if(num == 0 || num > 123)
{
return ModbusErrReply(0x10, ERR_DATA);
}

/*附加功能:读取0x10000寄存器*/
if(addres == 0xFFFE && num == 1)
{
writeValH = data[0];
writeValL = data[1];
/*将要写入两个8位值拼接为16位*/
writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
ModbusExtPage[0] = writeVal;
}
/*附加功能:读取大量奇数寄存器*/
else if(addres == 0xFFFF && num == 1)
{
writeValH = data[0];
writeValL = data[1];
/*将要写入两个8位值拼接为16位*/
writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
ModbusExtOdd[0] = writeVal;
}
/*正常功能*/
else
{
for(uint16_t i = 0; i < num; i++)
{
index = i * 2;

writeValH = data[index];
writeValL = data[index + 1];
/*将要写入两个8位值拼接为16位*/
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;

return 0;
}

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

uint16_t readVal;
uint8_t writeVal;

/*操作地址超限*/
if(addres > 0x270F)
{
return ModbusErrReply(0x0F, ERR_OPE_ADDRES);
}
byteIndI = addres / 8;
bitIndI = addres % 8;
/*位掩码读取要写入的值*/
readVal = ((uint16_t)data[0] << 8) | ((uint16_t)data[1] & 0x00FF);
/*将写入值移位到要写入的位*/
writeVal = (uint8_t)1 << bitIndI;

/*置on*/
if(readVal == 0xFF00)
{
ModbusCoil[byteIndI] |= writeVal;
}
/*置off*/
else if(readVal == 0x0000)
{
ModbusCoil[byteIndI] &= (~writeVal);
}
else
{
return ModbusErrReply(0x05, ERR_DATA);
}

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

return 0;
}

uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data)
{
uint8_t writeValH;
uint8_t writeValL;
uint16_t writeVal;
/*操作地址超限*/
if(addres > 0x270F)
{
return ModbusErrReply(0x10, ERR_OPE_ADDRES);
}

writeValH = data[0];
writeValL = data[1];
/*将要写入两个8位值拼接为16位*/
writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
ModbusReg[addres] = writeVal;
ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = 0x10;
/*操作地址*/
ModbusTxBuf[2] = (uint8_t)(addres >> 8);
ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
/*成功写入*/
ModbusTxBuf[4] = writeValH;
ModbusTxBuf[5] = writeValL;
AddCrc16(ModbusTxBuf, 6);
ModbusTxLen = 8;
return 0;
}

/*USART接收空闲中断*/
void USART1_IRQHandler(void)
{
OSIntEnter(); /*进入中断*/

uint32_t temp;
uint16_t rxLenRemain;
if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)
{
/*在计算数据长度之前先关闭DMA接收通道,防止计算过程中DMA继续转运数据*/
DMA_Cmd(DMA2_Stream2, DISABLE);
/*清除IDLE中断标志位*/
temp = USART1->SR;
temp = USART1->DR;
(void)temp;

/*清除传输已经完成TCIF2、传输已经完成一半HTIF2标志位*/
DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2 | DMA_FLAG_HTIF2);
/*计算数据长度*/
rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2);
ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain;

/*释放接收到数据帧信号量,唤醒帧解析任务*/
if(ModbusRxLen != 0)
{
OSSemPost(ModbusReceived);
}
/*重新指定接收地址*/
DMA_MemoryTargetConfig(DMA2_Stream2, (uint32_t)ModbusRxBuf, DMA_Memory_0);
/*重启DMA*/
DMA_SetCurrDataCounter(DMA2_Stream2, MODBUS_RX_BUF_SIZE);
DMA_Cmd(DMA2_Stream2, ENABLE);
}
OSIntExit(); /*退出中断*/
}


/*modbus响应帧发送*/
void ModbusSend(uint8_t *txBuf, uint16_t len)
{
if(DMA_GetCmdStatus(DMA2_Stream7) == ENABLE)
{
/*等待DMA发送完成*/
while(DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7) == RESET);
}

/*先关闭DMA发送通道*/
DMA_Cmd(DMA2_Stream7, DISABLE);

/*等待DMA关闭*/
while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);

/*清除传输已经完成TCIF7、传输已经完成一半HTIF7、FIFO错误FEIF7标志位*/
DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_FEIF7 | DMA_FLAG_HTIF7 | DMA_FLAG_TCIF7);
/*配置发送地址和长度*/
DMA_MemoryTargetConfig(DMA2_Stream7, (uint32_t)txBuf, DMA_Memory_0);
DMA_SetCurrDataCounter(DMA2_Stream7, len);

/*等待串口发送完成*/
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
/*启动 DMA 发送*/
DMA_Cmd(DMA2_Stream7, ENABLE);
}

uint8_t ModbusExtReadOdd(uint16_t num)
{
uint8_t i = 0;
uint8_t numJ = (num + 124) / 125;
uint8_t numI = num % 125;

uint8_t index;
uint16_t indexR;
uint8_t readValH;
uint8_t readValL;
uint8_t dataLen;

for(uint16_t j = 0; j < numJ; j++)
{
if(j == numJ - 1)
{
for(i = 0; i < numI; i++)
{
index = 3 + (i * 2);
indexR = j * 250 + 2 * i + 1;
/*将16位寄存器值拆分为两个8位*/
readValH = (uint8_t)(ModbusReg[indexR] >> 8);
readValL = (uint8_t)(ModbusReg[indexR] & 0x00FF);

ModbusTxBuf[index] = readValH;
ModbusTxBuf[index + 1] = readValL;
}
dataLen = 2 * numI;

ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = 0x03;
ModbusTxBuf[2] = dataLen;
AddCrc16(ModbusTxBuf, 3 + dataLen);
ModbusTxLen = 5 + dataLen;
}
else
{
for(i = 0; i < 125; i++)
{
index = 3 + (i * 2);
indexR = j * 250 + 2 * i + 1;
/*将16位寄存器值拆分为两个8位*/
readValH = (uint8_t)(ModbusReg[indexR] >> 8);
readValL = (uint8_t)(ModbusReg[indexR] & 0x00FF);

ModbusTxBuf[index] = readValH;
ModbusTxBuf[index + 1] = readValL;
}
dataLen = 250;

ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = 0x03;
ModbusTxBuf[2] = dataLen;
AddCrc16(ModbusTxBuf, 3 + dataLen);
ModbusTxLen = 5 + dataLen;
}
/*演示2ms*/
OSTimeDly(OS_TICKS_PER_SEC / 500);
ModbusSend(ModbusTxBuf, ModbusTxLen);
}
return 0;
}


uint8_t ModbusErrReply(uint8_t func, uint8_t err)
{
ModbusTxBuf[0] = SLAVE_ADDRES;
ModbusTxBuf[1] = func;
ModbusTxBuf[2] = err;
AddCrc16(ModbusTxBuf, 3);
ModbusTxLen = 5;

return err;
}




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

/*低前高后*/
dataT[length] = (uint8_t)(crc16 & 0x00FF);
dataT[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;
}
}

+ 0
- 57
modbus/modbus.h Visa fil

@@ -1,57 +0,0 @@
#ifndef __MODBUS_H
#define __MODBUS_H

#include "ucos_ii.h"


/*接收数组大小*/
#define MODBUS_RX_BUF_SIZE 256
/*发送数组大小*/
#define MODBUS_TX_BUF_SIZE 256

/*modbus通信波特率*/
#define MODBUS_USART_BAUDRATE 115200

/*从机地址*/
#define SLAVE_ADDRES 0x01

/*错误码*/
#define ERR_FUNC 0x01
#define ERR_OPE_ADDRES 0x02
#define ERR_DATA 0x03
#define ERR_SLAVE 0x04

#define ERR_CRC 0x1F
#define ERR_SLAVE_ADDRES 0x2F

/*modbus帧结构*/
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;

uint8_t ModbusErrReply(uint8_t func, uint8_t err);
uint16_t Crc16(const uint8_t *data, uint16_t length);
void AddCrc16(uint8_t *data, uint16_t length);
int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length);
uint8_t ModbusReadCoils(uint16_t addres, uint16_t num);
uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data);
uint8_t ModbusReadRegs(uint16_t addres, uint16_t num);
uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data);
uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data);
uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data);
uint8_t ModbusExtReadOdd(uint16_t num);
void ModbusSend(uint8_t *txBuf, uint16_t len);


#endif

+ 26
- 4
modbus/modbus_flash.c Visa fil

@@ -1,6 +1,6 @@
#include "stm32f4xx_flash.h"
#include "stm32f4xx.h"
#include "modbus.h"
#include "modbus_parse.h"
#include "modbus_flash.h"
#include "string.h"
#include "os.h"
@@ -22,10 +22,32 @@ void AppTaskModbusWriteFlash(void *p_arg)
while(1)
{
OSSemPend(ModbusWriteFlash, 0, &err);
OSTimeDly(OS_TICKS_PER_SEC);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

ModbusErr = ModbusFlashWrite();
while(1)
{
/*清除多余嵌套的信号量*/
while(OSSemAccept(ModbusWriteFlash) > 0);

OSSemPend(ModbusWriteFlash, OS_TICKS_PER_SEC * 2, &err);
/*当连续2s未收到信号量时,退出循环*/
if (err == OS_ERR_TIMEOUT)
{
break;
}
/*出现错误退出循环,防止阻塞*/
if (err != OS_ERR_NONE)
{
break;
}
}
/*当因为错误退出循环时,不进行flash写入*/
if (err != OS_ERR_TIMEOUT)
{
continue;
}

/*只有当连续2s未收到信号量时才进行写入操作,防止信号量嵌套导致重复写入延迟*/
//ModbusErr = ModbusFlashWrite();
}
}



+ 13
- 0
modbus/modbus_rec_send.h Visa fil

@@ -0,0 +1,13 @@
#ifndef __MODBUS_REC_SEND_H
#define __MODBUS_REC_SEND_H

#include "stm32f4xx.h"
#include "modbus_parse.h"



int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length);
void AddCrc16(uint8_t *data, uint16_t length);
void ModbusSend(uint8_t *txBuf, uint16_t len);

#endif

Laddar…
Avbryt
Spara