金牌会员
- 积分
- 1108
- 金钱
- 1108
- 注册时间
- 2018-11-6
- 在线时间
- 240 小时
|
发表于 2020-5-19 11:23:18
|
显示全部楼层
本帖最后由 霸王猫 于 2020-5-20 12:03 编辑
FreeRTOS一般常用的写法如下:
1、中断服务程序中发送信号量或消息队列
2、一个高优先级的普通任务接收中断服务程序发送的信号量或消息队列
3、多个任务给另外一个任务发送消息队列需要规划自定义协议
假设任务1、任务2、任务3分别给任务4发送消息队列,需要规划消息队列协议
假定:MSG[0]= 谁给任务4发送的消息队列
= 1--- 代表任务1给任务4发送消息队列
= 2--- 代表任务2给任务4发送消息队列
= 3--- 代表任务3给任务4发送消息队列
MSG[1]=消息队列类型 (不同的类型可以接收不同的数据和长度)
= 1 ---> 代表任务4接收AI数据
= 2---> 代表任务4接收AO数据
= 3---> 代表任务4接收DO数据
MSG[2]---MSG[255]=消息队列中存储的数据
下面的程序说明如下:
DI1_Task任务每隔100毫秒给MODBUS_Task任务发送DI开关量信号 (DI1,DI2)
DI2_Task任务每隔100毫秒给MODBUS_Task任务发送DI开关量信号(DI3,DI4)
SD2405ALPI_Task每隔1秒给MODBUS_Task任务发送时钟(年、月、日、时、分、秒)
MODBUS_Task任务收到USART1的上位机请求命令,把DI1,DI2,DI3,DI4,年、月、日、时、分、秒通过MODBUS协议传输给上位机。
USART1中断服务程序通过发送信号量唤醒 MODBUS_Task任务。
DI1_Task任务、DI2_Task任务、SD2405ALPI_Task给MODBUS_Task任务发送消息队列时,规划了自定义协议。
MODBUS_Task任务解析DI1_Task任务、DI2_Task任务、SD2405ALPI_Task发送的消息队列数据时,也使用了规划了自定义协议
- //DMA中断方式
- void USART1_IRQHandler(void)
- {
- uint16_t ch;
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-
- if (USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
- {
- USART_ClearITPendingBit(USART1 , USART_IT_IDLE); //必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。
- ch = USART_ReceiveData(USART1); //必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。
- DMA_Cmd(DMA1_Channel5 , DISABLE); //关闭DMA,防止处理其间有数据
- DMA_ClearFlag(DMA1_FLAG_GL5 | DMA1_FLAG_TC5 | DMA1_FLAG_HT5 | DMA1_FLAG_TE5);
- ch = USART1_DMA_RX_BUFFER_MAX_LENGTH - DMA_GetCurrDataCounter(DMA1_Channel5);
- if (ch > 0)
- {
-
- MB_USART1.receCount = ch;
- memcpy(MB_USART1.mscomm_buffer , USART1_DMA_RX_Buffer , MB_USART1.receCount);
- }
- DMA_SetCurrDataCounter(DMA1_Channel5 , USART1_DMA_RX_BUFFER_MAX_LENGTH);
- DMA_Cmd(DMA1_Channel5, ENABLE);
-
- xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);//发送同步信号
- //如果xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
-
- }
-
- else if (USART_GetITStatus(USART1,USART_IT_TC)!= RESET)
- {
- USART_ClearITPendingBit(USART1, USART_IT_TC);
- DMA_ClearFlag(DMA1_FLAG_GL4 | DMA1_FLAG_TC4 | DMA1_FLAG_HT4 | DMA1_FLAG_TE4);
- DMA_SetCurrDataCounter(DMA1_Channel4 , 0);
- }
- }
- void DI2_Task(void *pvParameters)
- {
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- BOOL DI2_1 = FALSE;
- BOOL DI2_2 = FALSE;
- uint8_t di21_array[2];
- uint8_t di22_array[2];
- uint8_t Buffer[10];
-
-
- while(1)
- {
- //第一次采集:采集行程2A和行程2B
- di21_array[0] = GPIO_DI2_1();
- di22_array[0] = GPIO_DI2_2();
- vTaskDelay(20 / portTICK_RATE_MS);
- //第二次采集:采集行程2A和行程2B
- di21_array[1] = GPIO_DI2_1();
- di22_array[1] = GPIO_DI2_2();
-
- if ((di21_array[0] == di21_array[1]) && (di22_array[0] == di22_array[1]))
- {
- DI2_1 = (di21_array[0] ? TRUE : FALSE);
- DI2_2 = (di22_array[0] ? TRUE : FALSE);
- }
- Buffer[0] = 4; //Func
- Buffer[1] = DI2_1;
- Buffer[2] = DI2_2;
-
- if( xQueueSend(xQueue, (void *) &Buffer , xTicksToWait) != pdPASS )
- {
- //发送失败,即使等待了10个时钟节拍
- }
- else
- {
- // 发送成功
- }
- vTaskDelay(100 / portTICK_RATE_MS);
- }
- }
- void DI1_Task(void *pvParameters)
- {
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- BOOL DI1_1 = FALSE;
- BOOL DI1_2 = FALSE;
- uint8_t di11_array[2];
- uint8_t di12_array[2];
- uint8_t Buffer[10];
-
-
- while(1)
- {
- //第一次采集:采集行程1A和行程1B
- di11_array[0] = GPIO_DI1_1();
- di12_array[0] = GPIO_DI1_2();
- vTaskDelay(20 / portTICK_RATE_MS);
- //第二次采集:采集行程1A和行程1B
- di11_array[1] = GPIO_DI1_1();
- di12_array[1] = GPIO_DI1_2();
-
- if ((di11_array[0] == di11_array[1]) && (di12_array[0] == di12_array[1]))
- {
- DI1_1 = (di11_array[0] ? TRUE : FALSE);
- DI1_2 = (di12_array[0] ? TRUE : FALSE);
- }
- Buffer[0] = 3; //Func
- Buffer[1] = DI1_1;
- Buffer[2] = DI1_2;
-
- if( xQueueSend(xQueue, (void *) &Buffer , xTicksToWait) != pdPASS )
- {
- //发送失败,即使等待了10个时钟节拍
- }
- else
- {
- // 发送成功
- }
- vTaskDelay(100 / portTICK_RATE_MS);
- }
- }
- void SD2405ALPI_Task(void *pvParameters)
- {
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- uint8_t Buffer[10];
- CLOCK_Type Clock;
-
- bsp_InitSD2405();
-
- while(1)
- {
- SD2405_I2CReadTime(&Clock.second , &Clock.minute , &Clock.hour , &Clock.week , &Clock.day , &Clock.month , &Clock.year);
-
- Buffer[0] = 2; //Func
- Buffer[1] = Clock.year;
- Buffer[2] = Clock.month;
- Buffer[3] = Clock.day;
- Buffer[4] = Clock.hour;
- Buffer[5] = Clock.minute;
- Buffer[6] = Clock.second;
- Buffer[7] = Clock.week;
-
- if( xQueueSend(xQueue, (void *) &Buffer , xTicksToWait) != pdPASS )
- {
- //发送失败,即使等待了10个时钟节拍
- }
- else
- {
- // 发送成功
- }
- vTaskDelay(1000 / portTICK_RATE_MS);
- }
- }
- void MODBUS_Task(void *pvParameters)
- {
- BaseType_t xResult;
- BaseType_t xStatus;
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- uint8_t Buffer[10];
- uint8_t Over = 0x00;
-
-
- USART1_Configuration();
- USART1_DMA_Tx_Configuration();
- USART1_DMA_Rx_Configuration();
- while(1)
- {
- xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
- if(xResult == pdTRUE)
- {
- while (1)
- {
- xStatus = xQueueReceive( xQueue, &Buffer, xTicksToWait );
- if( xStatus == pdPASS )
- {
- switch (Buffer[0])
- {
- case 2:
- Over |= 0x01; //bit0=1,表示收到SD2405ALPI_Task任务的消息队列数据
- MODBUS_Clock.year = Buffer[1];
- MODBUS_Clock.month = Buffer[2];
- MODBUS_Clock.day = Buffer[3];
- MODBUS_Clock.hour = Buffer[4];
- MODBUS_Clock.minute = Buffer[5];
- MODBUS_Clock.second = Buffer[6];
- MODBUS_Clock.week = Buffer[7];
- break;
- case 3:
- Over |= 0x02; //bit1=1,表示收到DI1_Task任务的消息队列数据
- MODBUS_DI1_1 = Buffer[1];
- MODBUS_DI1_2 = Buffer[2];
- break;
- case 4:
- Over |= 0x04; //bit2=1,表示收到DI2_Task任务的消息队列数据
- MODBUS_DI2_1 = Buffer[1];
- MODBUS_DI2_2 = Buffer[2];
- break;
- }//switch (Buffer[0])
-
- if (Over == 0x07) //bit0=1,bit1=1,bit2=1,表示3个任务的消息队列数据都已经收到
- {
- Over = 0x00;
- USART1_Modbus_Slave_APP();
- break;
- }
- }
- }//if( xStatus == pdPASS )
- //}//if( xQueue != NULL )
- }//if(xResult == pdTRUE)
- }//while(1)
- }
复制代码
|
|