金牌会员
- 积分
- 1108
- 金钱
- 1108
- 注册时间
- 2018-11-6
- 在线时间
- 240 小时
|
1金钱
本帖最后由 霸王猫 于 2022-11-28 17:09 编辑
问题:
我要实现MODBUS通信(串口为USART3),我不满意我目前采用的资源共享方法,想请求大家帮我想个更简便的方法:
1、上位机(MODBUS主站)发出请求报文,USART3中断服务程序发送消息队列激活【MODBUS任务】,MODBUS任务将30001,30002,30003上传给上位机。
2、【任务A】通过消息队列将变量XA (对应于30001)传输给【MODBUS任务】。
3、【任务B】通过消息队列将变量XB (对应于30002)传输给【MODBUS任务】。
4、【任务C】通过消息队列将变量XC (对应于30003)传输给【MODBUS任务】。
5、消息队列格式如下:
msg[0] = 1,代表 【USART3中断服务程序】发送的消息队列
msg[0] = 2,代表 【任务A】发送的消息队列
msg[0] = 3,代表 【任务B】发送的消息队列
msg[0] = 4,代表 【任务C】发送的消息队列
msg[1] = XA或XB或XC
6、为了防止正在进行MODBUS报文解析时,再次触发USART3中断,需要将USART3缓冲区进行资源共享(用互斥信号量保护)
7、下面是将XA (对应于30001),XB (对应于30002),XC (对应于30003) 添加互斥信号量保护原子完整性
- int16_t USART3_GetInputRegisterVal(uint16_t tempAddr)
- {
- int16_t tempData = 0x00;
-
- switch (tempAddr + 1 )
- {
- case 1:
- //任务A互斥信号量
- xSemaphoreTake(<font color="#ff00ff">xMutex1</font>, portMAX_DELAY);
- tempData = XA ; //30001
- xSemaphoreGive(<font color="#ff00ff">xMutex1</font>);
- break;
- case 2:
- //任务B互斥信号量
- xSemaphoreTake(xMutex2, portMAX_DELAY);
- tempData = XB ; //30002
- xSemaphoreGive(xMutex2);
- break;
- case 3:
- //任务C互斥信号量
- xSemaphoreTake(xMutex3, portMAX_DELAY);
- tempData = XC ; //30003
- xSemaphoreGive(xMutex3);
- break;
- }
- }
复制代码
8、下面是USART3中断服务程序,将USART3通信缓冲区进行互斥信号量保护,防止正在进行MODBUS报文解析时,再次触发USART3中断覆盖正在进行的报文分析工作,确保数据完整性。
- void USART3_IRQHandler(void)
- {
- uint16_t ch;
- uint8_t Buffer[10];
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-
- if (USART_GetITStatus(USART3,USART_IT_IDLE) != RESET)
- {
-
- //使用互斥信号量,保护通信缓冲区(MB_USART3.mscomm_buffer)数据的完整性
- xSemaphoreTakeFromISR(xMutex4, portMAX_DELAY);
- memcpy(MB_USART3.mscomm_buffer , USART3_DMA_RX_Buffer , 255);
- xSemaphoreGiveFromISR(xMutex4, portMAX_DELAY);
- // 发送消息队列
- Buffer[0] = 1;
- xQueueSendToBackFromISR(xQueueWIFI , Buffer , &xHigherPriorityTaskWoken);
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
- }
- }
复制代码
89、下面是MODBUS任务,将USART3通信缓冲区进行互斥信号量保护,防止正在进行MODBUS报文解析时,再次触发USART3中断覆盖正在进行的报文分析工作,确保数据完整性。最后解析完报文后,将30001,30002,30003上传给上位机(MODBUS主站)
- static void vTask_Modbus(void *pvParameters)
- {
- BaseType_t xStatus;
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- uint8_t Buffer[10];
-
- USART3_Configuration();
- USART3_DMA_Tx_Configuration();
- USART3_DMA_Rx_Configuration();
- while(1)
- {
- xStatus = xQueueReceive( xQueueWIFI, &Buffer, xTicksToWait );
- if ( xStatus == pdPASS )
- {
- switch (Buffer[0])
- {
- case 1:
- //使用互斥信号量,保护通信缓冲区(MB_USART3.mscomm_buffer)数据的完整性
- xSemaphoreTake(xMutex4, portMAX_DELAY);
- 从缓冲区MB_USART3.mscomm_buffer中解析MODBUS报文,将30001,30002,30003上传给上位机。
- xSemaphoreGive(xMutex4);
- break;
- case 2:
- //任务A互斥信号量
- xSemaphoreTake(xMutex1, portMAX_DELAY);
- //从消息队列中读取任务A的变量XA
- XA = buffer[1]; //30001
- xSemaphoreGive(xMutex1);
- break;
- case 2:
- //任务B互斥信号量
- xSemaphoreTake(xMutex2, portMAX_DELAY);
- //从消息队列中读取任务B的变量XB
- XB = buffer[1]; //30002
- xSemaphoreGive(xMutex2);
- break;
- case 3:
- //任务C互斥信号量
- xSemaphoreTake(xMutex3, portMAX_DELAY);
- //从消息队列中读取任务C的变量XC
- XC = buffer[1]; //30003
- xSemaphoreGive(xMutex3);
- break;
- }//switch (Buffer[0])
- }//if( xStatus == pdPASS )
- }//while(1)
- }
复制代码
|
|