|
- #include "modbus_rec_send.h"
- #include "hardware.h"
-
- MODBUS_RX_STATE ModbusRxState = MODBUS_RX_RECEIVING;
-
-
- /*USART接收空闲中断*/
- void USART1_IRQHandler(void)
- {
- uint32_t temp;
- uint16_t rxLenRemain;
-
- OSIntEnter(); /*进入中断*/
- if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)
- {
- /*清除IDLE中断标志位*/
- temp = USART1->SR;
- temp = USART1->DR;
- (void)temp;
-
- /*判断是否接收到帧,触发TIM计时*/
- rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2);
- ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain;
-
- if(ModbusRxLen != 0)
- {
- switch (ModbusRxState)
- {
- /*正常接收数据*/
- case MODBUS_RX_RECEIVING:
- ModbusRxState = MODBUS_RX_CHECK_T15;
- TimRestart(MODBUS_IDLE_TO_T15_US);
- break;
-
- /*在t1.5定时还未到达时又接收到了数据*/
- case MODBUS_RX_CHECK_T15:
- 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(); /*退出中断*/
- }
-
- /*TIM定时器中断*/
- void TIM5_IRQHandler(void)
- {
- uint16_t rxLenRemain;
-
- OSIntEnter();
-
- rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2);
-
- if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
- {
- 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;
-
- /*检查在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();
- }
-
- 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);
- }
-
- 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);
-
- /*计算数据长度*/
- rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2);
- ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain;
-
- /*释放接收到数据帧信号量,唤醒帧解析任务*/
- if(ModbusRxLen >= 4) /*4字节(1字节地址、1字节功能、2字节CRC)*/
- {
- 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);
- }
-
- 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响应帧发送*/
- 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);
- }
-
- /*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;
- }
- }
-
- 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);
- }
|