| @@ -6,15 +6,26 @@ | |||||
| #if (MODBUS_USART_BAUDRATE > 19200U) | #if (MODBUS_USART_BAUDRATE > 19200U) | ||||
| /*固定等待1750us,再减去IDLE中断等待的1个字符时间*/ | /*固定等待1750us,再减去IDLE中断等待的1个字符时间*/ | ||||
| /*1.5个字符=750us-1个字符时间*/ | |||||
| #define MODBUS_IDLE_TO_T15_US \ | |||||
| ((750UL * MODBUS_USART_BAUDRATE - 10000000UL + MODBUS_USART_BAUDRATE - 1UL) / MODBUS_USART_BAUDRATE) | |||||
| /*2个字符=1000us*/ | |||||
| #define MODBUS_T15_TO_T35_US 1000UL | |||||
| /*3.5个字符=1750us-1个字符时间*/ | |||||
| #define MODBUS_IDLE_TO_T35_US \ | #define MODBUS_IDLE_TO_T35_US \ | ||||
| ((1750UL * MODBUS_USART_BAUDRATE - 10000000UL + MODBUS_USART_BAUDRATE - 1UL) / MODBUS_USART_BAUDRATE) | |||||
| ((1750UL * MODBUS_USART_BAUDRATE - 10000000UL + MODBUS_USART_BAUDRATE - 1UL) / MODBUS_USART_BAUDRATE) | |||||
| #else | #else | ||||
| /*IDLE中断已经过了1个字符的时间,还需等待2.5个字符*/ | /*IDLE中断已经过了1个字符的时间,还需等待2.5个字符*/ | ||||
| /*1.5个字符-1个字符时间=0.5个字符时间*/ | |||||
| #define MODBUS_IDLE_TO_T15_US \ | |||||
| ((5000000UL + MODBUS_USART_BAUDRATE - 1UL) / MODBUS_USART_BAUDRATE) | |||||
| /*2个字符时间*/ | |||||
| #define MODBUS_T15_TO_T35_US \ | |||||
| ((20000000UL + MODBUS_USART_BAUDRATE - 1UL) / MODBUS_USART_BAUDRATE) | |||||
| /*3.5个字符-1个字符时间=2.5个字符时间*/ | |||||
| #define MODBUS_IDLE_TO_T35_US \ | #define MODBUS_IDLE_TO_T35_US \ | ||||
| ((25000000UL + MODBUS_USART_BAUDRATE - 1UL) / MODBUS_USART_BAUDRATE) | ((25000000UL + MODBUS_USART_BAUDRATE - 1UL) / MODBUS_USART_BAUDRATE) | ||||
| #endif | #endif | ||||
| @@ -110,7 +110,7 @@ void ModbusTimInit(void) | |||||
| TIM_DeInit(TIM5); | TIM_DeInit(TIM5); | ||||
| TIM_TimeBaseStructure.TIM_Prescaler = 84U - 1U; /*84Mhz/84=1Mhz,1us计时*/ | TIM_TimeBaseStructure.TIM_Prescaler = 84U - 1U; /*84Mhz/84=1Mhz,1us计时*/ | ||||
| TIM_TimeBaseStructure.TIM_Period = MODBUS_IDLE_TO_T35_US - 1U; /*计时周期1664us*/ | |||||
| TIM_TimeBaseStructure.TIM_Period = MODBUS_IDLE_TO_T15_US - 1U; /*计时周期1664us*/ | |||||
| TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /*向上计数*/ | TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /*向上计数*/ | ||||
| TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; | TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; | ||||
| TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; | TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; | ||||
| @@ -136,7 +136,7 @@ void ModbusNvicInit(void) | |||||
| /*定时器中断*/ | /*定时器中断*/ | ||||
| NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; | NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; | ||||
| NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; | |||||
| NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; | |||||
| NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; | ||||
| NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; | ||||
| NVIC_Init(&NVIC_InitStructure); | NVIC_Init(&NVIC_InitStructure); | ||||
| @@ -16,15 +16,15 @@ | |||||
| <ShowSource>1</ShowSource> | <ShowSource>1</ShowSource> | ||||
| </Trace1> | </Trace1> | ||||
| <StLinkDriver> | <StLinkDriver> | ||||
| <stlinkResetStyle>0</stlinkResetStyle> | |||||
| <stlinkResetStrategy>0</stlinkResetStrategy> | |||||
| <stlinkserialNo>30303031</stlinkserialNo> | |||||
| <stlinkfoundProbes /> | |||||
| <CStepIntDis>_ 0</CStepIntDis> | <CStepIntDis>_ 0</CStepIntDis> | ||||
| <LeaveTargetRunning>_ 0</LeaveTargetRunning> | <LeaveTargetRunning>_ 0</LeaveTargetRunning> | ||||
| <stlinkserialNo>24230357</stlinkserialNo> | |||||
| <stlinkfoundProbes /> | |||||
| <stlinkResetStyle>0</stlinkResetStyle> | |||||
| <stlinkResetStrategy>0</stlinkResetStrategy> | |||||
| </StLinkDriver> | </StLinkDriver> | ||||
| <DebugChecksum> | <DebugChecksum> | ||||
| <Checksum>2912698606</Checksum> | |||||
| <Checksum>3570680553</Checksum> | |||||
| </DebugChecksum> | </DebugChecksum> | ||||
| <Exceptions> | <Exceptions> | ||||
| <StopOnUncaught>_ 0</StopOnUncaught> | <StopOnUncaught>_ 0</StopOnUncaught> | ||||
| @@ -120,11 +120,26 @@ | |||||
| <ShowTimeSum>1</ShowTimeSum> | <ShowTimeSum>1</ShowTimeSum> | ||||
| <SumSortOrder>0</SumSortOrder> | <SumSortOrder>0</SumSortOrder> | ||||
| </EventLog> | </EventLog> | ||||
| <DisassembleMode> | |||||
| <mode>0</mode> | |||||
| </DisassembleMode> | |||||
| <Breakpoints2> | |||||
| <Bp0>_ 1 "EMUL_CODE" "{d:\IAR_Project\TrainCamp_fubowen_Modbus\modbus\modbus_parse.c}.67.13" 0 0 1 "" 0 "" 0</Bp0> | |||||
| <Count>1</Count> | |||||
| </Breakpoints2> | |||||
| <TermIOLog> | |||||
| <LoggingEnabled>_ 0</LoggingEnabled> | |||||
| <LogFile>_ ""</LogFile> | |||||
| </TermIOLog> | |||||
| <LogFile> | <LogFile> | ||||
| <LoggingEnabled>_ 0</LoggingEnabled> | <LoggingEnabled>_ 0</LoggingEnabled> | ||||
| <LogFile>_ ""</LogFile> | <LogFile>_ ""</LogFile> | ||||
| <Category>_ 0</Category> | <Category>_ 0</Category> | ||||
| </LogFile> | </LogFile> | ||||
| <Aliases> | |||||
| <Count>0</Count> | |||||
| <SuppressDialog>0</SuppressDialog> | |||||
| </Aliases> | |||||
| <DriverProfiling> | <DriverProfiling> | ||||
| <Enabled>0</Enabled> | <Enabled>0</Enabled> | ||||
| <Mode>3</Mode> | <Mode>3</Mode> | ||||
| @@ -138,19 +153,4 @@ | |||||
| <CallStackStripe> | <CallStackStripe> | ||||
| <ShowTiming>1</ShowTiming> | <ShowTiming>1</ShowTiming> | ||||
| </CallStackStripe> | </CallStackStripe> | ||||
| <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> | |||||
| <Aliases> | |||||
| <Count>0</Count> | |||||
| <SuppressDialog>0</SuppressDialog> | |||||
| </Aliases> | |||||
| <TermIOLog> | |||||
| <LoggingEnabled>_ 0</LoggingEnabled> | |||||
| <LogFile>_ ""</LogFile> | |||||
| </TermIOLog> | |||||
| </settings> | </settings> | ||||
| @@ -1,4 +1,7 @@ | |||||
| #include "modbus_rec_send.h" | #include "modbus_rec_send.h" | ||||
| #include "hardware.h" | |||||
| MODBUS_RX_STATE ModbusRxState = MODBUS_RX_RECEIVING; | |||||
| /*USART接收空闲中断*/ | /*USART接收空闲中断*/ | ||||
| @@ -17,13 +20,36 @@ void USART1_IRQHandler(void) | |||||
| /*判断是否接收到帧,触发TIM计时*/ | /*判断是否接收到帧,触发TIM计时*/ | ||||
| rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2); | 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(); /*退出中断*/ | OSIntExit(); /*退出中断*/ | ||||
| @@ -35,33 +61,123 @@ void TIM5_IRQHandler(void) | |||||
| uint16_t rxLenRemain; | uint16_t rxLenRemain; | ||||
| OSIntEnter(); | OSIntEnter(); | ||||
| rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2); | |||||
| if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) | 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响应帧发送*/ | /*modbus响应帧发送*/ | ||||
| @@ -4,10 +4,23 @@ | |||||
| #include "stm32f4xx.h" | #include "stm32f4xx.h" | ||||
| #include "modbus_parse.h" | #include "modbus_parse.h" | ||||
| typedef enum ModbusRxStateType | |||||
| { | |||||
| MODBUS_RX_RECEIVING = 0, /*正在正常接收*/ | |||||
| MODBUS_RX_CHECK_T15, /*等待第一次DMA检查,判断新字符是否在t1.5前开始*/ | |||||
| MODBUS_RX_CHECK_T35, /*等待第二次DMA检查,判断t1.5~t3.5是否出现字符*/ | |||||
| MODBUS_RX_DISCARD, /*当前帧已经确认错误,继续丢弃后续数据*/ | |||||
| MODBUS_RX_DISCARD_CHECK_T35 /*已收到错误帧的IDLE,等待连续t3.5静默*/ | |||||
| }MODBUS_RX_STATE; | |||||
| int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length); | int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length); | ||||
| void AddCrc16(uint8_t *data, uint16_t length); | void AddCrc16(uint8_t *data, uint16_t length); | ||||
| void ModbusSend(uint8_t *txBuf, uint16_t len); | void ModbusSend(uint8_t *txBuf, uint16_t len); | ||||
| void TimOff(void); | |||||
| void TimRestart(uint32_t timArr); | |||||
| void ModbusParseWakeUp(void); | |||||
| void ModbusDmaRestart(void); | |||||
| #endif | #endif | ||||