|
|
|
@@ -1,4 +1,7 @@ |
|
|
|
#include "modbus_rec_send.h" |
|
|
|
#include "hardware.h" |
|
|
|
|
|
|
|
MODBUS_RX_STATE ModbusRxState = MODBUS_RX_RECEIVING; |
|
|
|
|
|
|
|
|
|
|
|
/*USART接收空闲中断*/ |
|
|
|
@@ -17,13 +20,36 @@ void USART1_IRQHandler(void) |
|
|
|
|
|
|
|
/*判断是否接收到帧,触发TIM计时*/ |
|
|
|
rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2); |
|
|
|
if(rxLenRemain != MODBUS_RX_BUF_SIZE) |
|
|
|
ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain; |
|
|
|
|
|
|
|
if(ModbusRxLen != 0) |
|
|
|
{ |
|
|
|
/*启动TIM计时*/ |
|
|
|
TIM_Cmd(TIM5, DISABLE); |
|
|
|
TIM_SetCounter(TIM5, 0); /*清除计数值*/ |
|
|
|
//TIM_ClearITPendingBit(TIM5, TIM_IT_Update); /*清除中断标志位*/ |
|
|
|
TIM_Cmd(TIM5, ENABLE); |
|
|
|
switch (ModbusRxState) |
|
|
|
{ |
|
|
|
/*正常接收数据*/ |
|
|
|
case MODBUS_RX_RECEIVING: |
|
|
|
ModbusRxState = MODBUS_RX_CHECK_T15; |
|
|
|
TimRestart(MODBUS_IDLE_TO_T15_US); |
|
|
|
break; |
|
|
|
|
|
|
|
/*在判断t1.5~t3.5是否出现字符时,t3.5定时中断还未触发,又接收到了数据*/ |
|
|
|
case MODBUS_RX_CHECK_T35: |
|
|
|
ModbusRxState = MODBUS_RX_DISCARD_CHECK_T35; /*判断为错误帧*/ |
|
|
|
TimRestart(MODBUS_IDLE_TO_T35_US); /*等待3.5字符该帧结束之后丢失该帧*/ |
|
|
|
break; |
|
|
|
|
|
|
|
/*在t1.5~t3.5中出现字符,随后又接收到数据*/ |
|
|
|
case MODBUS_RX_DISCARD: |
|
|
|
ModbusRxState = MODBUS_RX_DISCARD_CHECK_T35; /*判断为错误帧*/ |
|
|
|
TimRestart(MODBUS_IDLE_TO_T35_US); /*等待3.5字符该帧结束之后丢失该帧*/ |
|
|
|
break; |
|
|
|
|
|
|
|
/*在等待3.5字符该帧结束期间又接收到数据*/ |
|
|
|
case MODBUS_RX_DISCARD_CHECK_T35: |
|
|
|
ModbusRxState = MODBUS_RX_DISCARD_CHECK_T35; |
|
|
|
TimRestart(MODBUS_IDLE_TO_T35_US); /*再等待3.5字符该帧结束之后丢失该帧*/ |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
OSIntExit(); /*退出中断*/ |
|
|
|
@@ -35,33 +61,123 @@ void TIM5_IRQHandler(void) |
|
|
|
uint16_t rxLenRemain; |
|
|
|
|
|
|
|
OSIntEnter(); |
|
|
|
|
|
|
|
rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2); |
|
|
|
|
|
|
|
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) |
|
|
|
{ |
|
|
|
/*清除TIM5更新中断标志*/ |
|
|
|
TIM_ClearITPendingBit(TIM5, TIM_IT_Update); |
|
|
|
switch (ModbusRxState) |
|
|
|
{ |
|
|
|
/*检查在t1-t1.5期间是否接收到数据*/ |
|
|
|
case MODBUS_RX_CHECK_T15: |
|
|
|
/*在t1-t1.5期间接收到了数据,正常继续接收*/ |
|
|
|
if (MODBUS_RX_BUF_SIZE - rxLenRemain != ModbusRxLen) |
|
|
|
{ |
|
|
|
ModbusRxState = MODBUS_RX_RECEIVING; |
|
|
|
TimOff(); |
|
|
|
} |
|
|
|
/*在t1-t1.5期间没收到,开始检查t1.5-t3.5期间是否接收到数据*/ |
|
|
|
else |
|
|
|
{ |
|
|
|
ModbusRxState = MODBUS_RX_CHECK_T35; |
|
|
|
TimRestart(MODBUS_T15_TO_T35_US); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
/*关闭DMA*/ |
|
|
|
DMA_Cmd(DMA2_Stream2, DISABLE); |
|
|
|
/*清除传输已经完成TCIF2、传输已经完成一半HTIF2标志位*/ |
|
|
|
DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2 | DMA_FLAG_HTIF2); |
|
|
|
/*检查在t1.5-t3.5期间是否接收到数据*/ |
|
|
|
case MODBUS_RX_CHECK_T35: |
|
|
|
/*在t1.5-t3.5期间接收到了数据,判断为错误帧,等待串口空闲中断开启3.5字符等待定时器计时*/ |
|
|
|
if (MODBUS_RX_BUF_SIZE - rxLenRemain != ModbusRxLen) |
|
|
|
{ |
|
|
|
ModbusRxState = MODBUS_RX_DISCARD; |
|
|
|
TimOff(); |
|
|
|
} |
|
|
|
/*在t1.5-t3.5之间都没接收到数据,该帧结束,开始帧解析*/ |
|
|
|
else |
|
|
|
{ |
|
|
|
ModbusRxState = MODBUS_RX_RECEIVING; |
|
|
|
ModbusParseWakeUp(); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
/*接收到错误帧,等待3.5字符之后丢弃该帧*/ |
|
|
|
case MODBUS_RX_DISCARD_CHECK_T35: |
|
|
|
/*在等待3.5字符期间又接收到了数据,等待串口空闲中断重新开启3.5字符等待定时器计时*/ |
|
|
|
if (MODBUS_RX_BUF_SIZE - rxLenRemain != ModbusRxLen) |
|
|
|
{ |
|
|
|
ModbusRxState = MODBUS_RX_DISCARD_CHECK_T35; |
|
|
|
TimOff(); |
|
|
|
} |
|
|
|
/*在等待3.5字符期间没接收到数据,该错误帧结束,丢弃该帧,准备开始下一帧的接收*/ |
|
|
|
else |
|
|
|
{ |
|
|
|
ModbusRxState = MODBUS_RX_RECEIVING; |
|
|
|
ModbusDmaRestart(); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
OSIntExit(); |
|
|
|
} |
|
|
|
|
|
|
|
/*计算数据长度*/ |
|
|
|
rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2); |
|
|
|
ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain; |
|
|
|
void TimRestart(uint32_t timArr) |
|
|
|
{ |
|
|
|
/*启动TIM计时*/ |
|
|
|
TIM_Cmd(TIM5, DISABLE); |
|
|
|
TIM_SetCounter(TIM5, 0); /*清除计数值*/ |
|
|
|
TIM_SetAutoreload(TIM5, timArr); |
|
|
|
TIM_ClearITPendingBit(TIM5, TIM_IT_Update); /*清除中断标志位*/ |
|
|
|
TIM_Cmd(TIM5, ENABLE); |
|
|
|
} |
|
|
|
|
|
|
|
/*释放接收到数据帧信号量,唤醒帧解析任务*/ |
|
|
|
if(ModbusRxLen >= 4) /*4字节(1字节地址、1字节功能、2字节CRC)*/ |
|
|
|
{ |
|
|
|
OSSemPost(ModbusReceived); |
|
|
|
} |
|
|
|
void TimOff(void) |
|
|
|
{ |
|
|
|
TIM_Cmd(TIM5, DISABLE); |
|
|
|
TIM_SetCounter(TIM5, 0); /*清除计数值*/ |
|
|
|
TIM_ClearITPendingBit(TIM5, TIM_IT_Update); /*清除中断标志位*/ |
|
|
|
} |
|
|
|
|
|
|
|
void ModbusParseWakeUp(void) |
|
|
|
{ |
|
|
|
uint16_t rxLenRemain; |
|
|
|
|
|
|
|
TimOff(); |
|
|
|
|
|
|
|
/*关闭DMA*/ |
|
|
|
DMA_Cmd(DMA2_Stream2, DISABLE); |
|
|
|
/*清除传输已经完成TCIF2、传输已经完成一半HTIF2标志位*/ |
|
|
|
DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2 | DMA_FLAG_HTIF2); |
|
|
|
|
|
|
|
/*重新指定接收地址*/ |
|
|
|
DMA_MemoryTargetConfig(DMA2_Stream2, (uint32_t)ModbusRxBuf, DMA_Memory_0); |
|
|
|
/*重启DMA*/ |
|
|
|
DMA_SetCurrDataCounter(DMA2_Stream2, MODBUS_RX_BUF_SIZE); |
|
|
|
DMA_Cmd(DMA2_Stream2, ENABLE); |
|
|
|
/*计算数据长度*/ |
|
|
|
rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2); |
|
|
|
ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain; |
|
|
|
|
|
|
|
/*释放接收到数据帧信号量,唤醒帧解析任务*/ |
|
|
|
if(ModbusRxLen >= 4) /*4字节(1字节地址、1字节功能、2字节CRC)*/ |
|
|
|
{ |
|
|
|
OSSemPost(ModbusReceived); |
|
|
|
} |
|
|
|
OSIntExit(); |
|
|
|
|
|
|
|
/*重新指定接收地址*/ |
|
|
|
DMA_MemoryTargetConfig(DMA2_Stream2, (uint32_t)ModbusRxBuf, DMA_Memory_0); |
|
|
|
/*重启DMA*/ |
|
|
|
DMA_SetCurrDataCounter(DMA2_Stream2, MODBUS_RX_BUF_SIZE); |
|
|
|
DMA_Cmd(DMA2_Stream2, ENABLE); |
|
|
|
} |
|
|
|
|
|
|
|
void ModbusDmaRestart(void) |
|
|
|
{ |
|
|
|
TimOff(); |
|
|
|
|
|
|
|
/*关闭DMA*/ |
|
|
|
DMA_Cmd(DMA2_Stream2, DISABLE); |
|
|
|
/*清除传输已经完成TCIF2、传输已经完成一半HTIF2标志位*/ |
|
|
|
DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2 | DMA_FLAG_HTIF2); |
|
|
|
/*重新指定接收地址*/ |
|
|
|
DMA_MemoryTargetConfig(DMA2_Stream2, (uint32_t)ModbusRxBuf, DMA_Memory_0); |
|
|
|
/*重启DMA*/ |
|
|
|
DMA_SetCurrDataCounter(DMA2_Stream2, MODBUS_RX_BUF_SIZE); |
|
|
|
DMA_Cmd(DMA2_Stream2, ENABLE); |
|
|
|
} |
|
|
|
|
|
|
|
/*modbus响应帧发送*/ |
|
|
|
|