Parcourir la source

实现附加功能:一次性读取大量线圈,并修改读取0x1000寄存器部分代码

main
the_deepest il y a 6 jours
Parent
révision
0fe7a322dc
3 fichiers modifiés avec 133 ajouts et 14 suppressions
  1. +3
    -3
      iar/settings/F407_uCOSii_Modbus.wsdt
  2. +1
    -1
      iar/settings/uCOS_Modbus.dnx
  3. +129
    -10
      modbus/modbus.c

+ 3
- 3
iar/settings/F407_uCOSii_Modbus.wsdt
Fichier diff supprimé car celui-ci est trop grand
Voir le fichier


+ 1
- 1
iar/settings/uCOS_Modbus.dnx Voir le fichier

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


+ 129
- 10
modbus/modbus.c Voir le fichier

@@ -8,10 +8,11 @@
uint8_t ModbusErr; uint8_t ModbusErr;
/*0x270F + 1 = K10000 */ /*0x270F + 1 = K10000 */
uint8_t ModbusCoil[1250]; /*10000/8=1250*/ uint8_t ModbusCoil[1250]; /*10000/8=1250*/
uint16_t ModbusReg[10001];
uint16_t ModbusReg[10000];


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


@@ -31,6 +32,7 @@ uint8_t ModbusReadRegs(uint16_t addres, uint16_t num);
uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data); uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data);
uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data); uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data);
uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data); uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data);
uint8_t ModbusExtReadOdd(uint16_t num);




/*USART接收空闲中断*/ /*USART接收空闲中断*/
@@ -78,6 +80,12 @@ void USART1_IRQHandler(void)
/*modbus响应帧发送*/ /*modbus响应帧发送*/
void ModbusSend(uint8_t *txBuf, uint16_t len) 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发送通道*/
DMA_Cmd(DMA2_Stream7, DISABLE); DMA_Cmd(DMA2_Stream7, DISABLE);


@@ -90,6 +98,9 @@ void ModbusSend(uint8_t *txBuf, uint16_t len)
/*配置发送地址和长度*/ /*配置发送地址和长度*/
DMA_MemoryTargetConfig(DMA2_Stream7, (uint32_t)txBuf, DMA_Memory_0); DMA_MemoryTargetConfig(DMA2_Stream7, (uint32_t)txBuf, DMA_Memory_0);
DMA_SetCurrDataCounter(DMA2_Stream7, len); DMA_SetCurrDataCounter(DMA2_Stream7, len);

/*等待串口发送完成*/
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
/*启动 DMA 发送*/ /*启动 DMA 发送*/
DMA_Cmd(DMA2_Stream7, ENABLE); DMA_Cmd(DMA2_Stream7, ENABLE);
@@ -104,8 +115,6 @@ void AppTaskModbusParse (void *p_arg)
uint16_t rxLen; uint16_t rxLen;
uint8_t rxBuf[256]; uint8_t rxBuf[256];


ModbusReg[10000] = 123;

while(1) while(1)
{ {
/*无限期等待接收到数据帧信号量*/ /*无限期等待接收到数据帧信号量*/
@@ -174,8 +183,16 @@ void AppTaskModbusParse (void *p_arg)
ModbusErr = ModbusErrReply(frame.func, ERR_FUNC); ModbusErr = ModbusErrReply(frame.func, ERR_FUNC);
break; break;
} }
/*启动发送*/
ModbusSend(ModbusTxBuf, ModbusTxLen);
/*实现附加功能时不在这里启动发送*/
if(frame.func == 0x03 && frame.opeAddres == 0XFFFF)
{
;
}
else
{
/*启动发送*/
ModbusSend(ModbusTxBuf, ModbusTxLen);
}
} }
} }


@@ -192,6 +209,10 @@ uint8_t ModbusReadCoils(uint16_t addres, uint16_t num)
uint8_t readVal; /*读取到的形式值*/ uint8_t readVal; /*读取到的形式值*/
uint8_t writeVal; /*写入的形式值*/ uint8_t writeVal; /*写入的形式值*/


if(ModbusRxLen < 8)
{
return ModbusErrReply(0x01, ERR_DATA);
}
/*操作地址超限*/ /*操作地址超限*/
if(addres > 0x270F || (addres + (num - 1)) > 0x270F) if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
{ {
@@ -250,6 +271,10 @@ uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data)
uint8_t readVal; uint8_t readVal;
uint8_t writeVal; uint8_t writeVal;


if(ModbusRxLen < 10)
{
return ModbusErrReply(0x0F, ERR_DATA);
}
/*操作地址超限*/ /*操作地址超限*/
if(addres > 0x270F || (addres + (num - 1)) > 0x270F) if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
{ {
@@ -306,10 +331,21 @@ uint8_t ModbusReadRegs(uint16_t addres, uint16_t num)
uint8_t readValL; uint8_t readValL;
uint8_t dataLen; uint8_t dataLen;


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


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


ModbusTxBuf[3] = readValH; ModbusTxBuf[3] = readValH;
ModbusTxBuf[4] = readValL; ModbusTxBuf[4] = readValL;
} }
/*附加功能:读取大量奇数寄存器*/
else if(addres == 0xFFFF && num == 1)
{
return ModbusExtReadOdd(ModbusExtOdd[0]);
}
else else
{ {
for(uint16_t i = 0; i < num; i++) for(uint16_t i = 0; i < num; i++)
@@ -357,11 +399,15 @@ uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data)
uint8_t writeValH; uint8_t writeValH;
uint8_t writeValL; uint8_t writeValL;
uint16_t writeVal; uint16_t writeVal;

if(ModbusRxLen < 11)
{
return ModbusErrReply(0x10, ERR_DATA);
}
/*操作地址超限*/ /*操作地址超限*/
if(addres > 0x270F || (addres + (num - 1)) > 0x270F) if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
{ {
if(addres == 0xFFFE && num == 1)
if((addres == 0xFFFE || addres == 0xFFFF) && num == 1)
{ {
; ;
} }
@@ -376,6 +422,7 @@ uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data)
return ModbusErrReply(0x10, ERR_DATA); return ModbusErrReply(0x10, ERR_DATA);
} }


/*附加功能:读取0x10000寄存器*/
if(addres == 0xFFFE && num == 1) if(addres == 0xFFFE && num == 1)
{ {
writeValH = data[0]; writeValH = data[0];
@@ -385,6 +432,17 @@ uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data)
writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF); writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
ModbusExtPage[0] = writeVal; 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 else
{ {
for(uint16_t i = 0; i < num; i++) for(uint16_t i = 0; i < num; i++)
@@ -497,6 +555,67 @@ uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data)
return 0; return 0;
} }


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;
}
OSTimeDlyHMSM(0, 0, 0, 10);
ModbusSend(ModbusTxBuf, ModbusTxLen);
}
return 0;
}




uint8_t ModbusErrReply(uint8_t func, uint8_t err) uint8_t ModbusErrReply(uint8_t func, uint8_t err)


Chargement…
Annuler
Enregistrer