FreeRTOS操作系統(tǒng)例程(8):消息隊(duì)列

安富萊電子 www.armfly.com

安富萊_STM32-V5開(kāi)發(fā)板_FreeRTOS教程(V1.0)


static QueueHandle_t xQueue1 = NULL;

static QueueHandle_t xQueue2 = NULL;

typedef struct Msg

{

uint8_t ucMessageID;

uint16_t usData[2];

uint32_t ulData[2];

}MSG_T;

MSG_T g_tMsg;

/*

*********************************************************************************************************

*? 函 數(shù) 名: AppObjCreate

*? 功能說(shuō)明: 創(chuàng)建任務(wù)通信機(jī)制

*? 形 參: 無(wú)

*? 返 回 值: 無(wú)

*********************************************************************************************************

*/

static void AppObjCreate (void)

{

/* 創(chuàng)建 10 個(gè) uint8_t 型消息隊(duì)列 */

xQueue1 = xQueueCreate(10, sizeof(uint8_t));

if( xQueue1 == 0 )

{

/* 沒(méi)有創(chuàng)建成功,用戶可以在這里加入創(chuàng)建失敗的處理機(jī)制 */

}

/* 創(chuàng)建 10 個(gè)存儲(chǔ)指針變量的消息隊(duì)列,由于 CM3/CM4 內(nèi)核是 32 位機(jī),一個(gè)指針變量占用 4 個(gè)字節(jié) */

xQueue2 = xQueueCreate(10, sizeof(struct Msg *));

if( xQueue2 == 0 )

{

/* 沒(méi)有創(chuàng)建成功,用戶可以在這里加入創(chuàng)建失敗的處理機(jī)制 */

}

}

/*向 xQueue1 發(fā)送數(shù)據(jù) */

//初始化定義

uint8_t ucCount = 0;


/*?while循環(huán)里實(shí)現(xiàn)向 xQueue2 發(fā)送數(shù)據(jù) */

ucCount++;

/* 向消息隊(duì)列發(fā)數(shù)據(jù),如果消息隊(duì)列滿了,等待 10 個(gè)時(shí)鐘節(jié)拍 */

if( xQueueSend(xQueue1,

? ? ? ? ? ? ? ? ? ? ? ? ? (void *) &ucCount,

? ? ? ? ? ? ? ? ? ? ? ? ? (TickType_t)10) != pdPASS )

{

/* 發(fā)送失敗,即使等待了 10 個(gè)時(shí)鐘節(jié)拍 */

printf("向 xQueue1 發(fā)送數(shù)據(jù)失敗,即使等待了 10 個(gè)時(shí)鐘節(jié)拍\r\n");

}

else

{

/* 發(fā)送成功 */

printf("向 xQueue1 發(fā)送數(shù)據(jù)成功\r\n");

}

/* 向 xQueue2 發(fā)送數(shù)據(jù) */

//初始化定義

MSG_T *ptMsg;

/* 初始化結(jié)構(gòu)體指針 */

ptMsg = &g_tMsg;

/* 初始化數(shù)組 */

ptMsg->ucMessageID = 0;

ptMsg->ulData[0] = 0;

ptMsg->usData[0] = 0;


/*?while循環(huán)里實(shí)現(xiàn)向 xQueue2 發(fā)送數(shù)據(jù) */

ptMsg->ucMessageID++;

ptMsg->ulData[0]++;;

ptMsg->usData[0]++;

/* 使用消息隊(duì)列實(shí)現(xiàn)指針變量的傳遞 */

if(xQueueSend(xQueue2, /* 消息隊(duì)列句柄 */

? ? ? ? ? ? ? ? ? ? ? ? ?(void *) &ptMsg, /* 發(fā)送結(jié)構(gòu)體指針變量 ptMsg 的地址 */

? ? ? ? ? ? ? ? ? ? ? ? ?(TickType_t)10) != pdPASS )

{

/* 發(fā)送失敗,即使等待了 10 個(gè)時(shí)鐘節(jié)拍 */

printf("向 xQueue2 發(fā)送數(shù)據(jù)失敗,即使等待了 10 個(gè)時(shí)鐘節(jié)拍\r\n");

}

else

{

/* 發(fā)送成功 */

printf("向 xQueue2 發(fā)送數(shù)據(jù)成功\r\n");

}


xQueueReceive接收消息隊(duì)列中的數(shù)據(jù)

static QueueHandle_t xQueue1 = NULL;

/*

*********************************************************************************************************

*? 函 數(shù) 名: vTaskMsgPro

*? 功能說(shuō)明: 使用函數(shù) xQueueReceive 接收任務(wù) vTaskTaskUserIF 發(fā)送的消息隊(duì)列數(shù)據(jù)(xQueue1)

*? 形 參: pvParameters 是在創(chuàng)建該任務(wù)時(shí)傳遞的形參

*? 返 回 值: 無(wú)

* 優(yōu) 先 級(jí): 3

*********************************************************************************************************

*/

static void vTaskMsgPro(void *pvParameters)

{

BaseType_t xResult;

const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 設(shè)置最大等待時(shí)間為 300ms */

uint8_t ucQueueMsgValue;

while(1)

{

xResult = xQueueReceive(xQueue1, /* 消息隊(duì)列句柄 */

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(void *)&ucQueueMsgValue, /* 存儲(chǔ)接收到的數(shù)據(jù)到變量 ucQueueMsgValue 中 */

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(TickType_t)xMaxBlockTime);/* 設(shè)置阻塞時(shí)間 */

if(xResult == pdPASS)

{

/* 成功接收,并通過(guò)串口將數(shù)據(jù)打印出來(lái) */

printf("接收到消息隊(duì)列數(shù)據(jù) ucQueueMsgValue = %d\r\n", ucQueueMsgValue);

}

else

{

/* 超時(shí) */

bsp_LedToggle(1);

bsp_LedToggle(4);

}

}

}

/*

*********************************************************************************************************

*? 函 數(shù) 名: vTaskLED

*? 功能說(shuō)明: 使用函數(shù) xQueueReceive 接收任務(wù) vTaskTaskUserIF 發(fā)送的消息隊(duì)列數(shù)據(jù)(xQueue2)

*? 形 參: pvParameters 是在創(chuàng)建該任務(wù)時(shí)傳遞的形參

*? 返 回 值: 無(wú)

* 優(yōu) 先 級(jí): 2

*********************************************************************************************************

*/

static void vTaskLED(void *pvParameters)

{

MSG_T *ptMsg;

BaseType_t xResult;

const TickType_t xMaxBlockTime = pdMS_TO_TICKS(200); /* 設(shè)置最大等待時(shí)間為 200ms */

while(1)

{

xResult = xQueueReceive(xQueue2, /* 消息隊(duì)列句柄 */

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (void *)&ptMsg, /* 這里獲取的是結(jié)構(gòu)體的地址 */

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (TickType_t)xMaxBlockTime);/* 設(shè)置阻塞時(shí)間 */

if(xResult == pdPASS)

{

/* 成功接收,并通過(guò)串口將數(shù)據(jù)打印出來(lái) */

printf("接收到消息隊(duì)列數(shù)據(jù) ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);

printf("接收到消息隊(duì)列數(shù)據(jù) ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);

printf("接收到消息隊(duì)列數(shù)據(jù) ptMsg->usData[0] = %d\r\n", ptMsg->usData[0]);

}

else

{

/* 超時(shí) */

bsp_LedToggle(2);

bsp_LedToggle(3);

}

}

}

中斷方式?

?bsp_InitHardTimer(); /* 初始化 TIM2 定時(shí)器 */

/*按鍵或什么外部觸發(fā)啟動(dòng)定時(shí)器*/

printf("啟動(dòng)單次定時(shí)器中斷,50ms 后在定時(shí)器中斷給任務(wù) vTaskMsgPro 發(fā)送消息\r\n");

bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack1);


printf("啟動(dòng)單次定時(shí)器中斷,50ms 后在定時(shí)器中斷給任務(wù) vTaskLED 發(fā)送消息\r\n");

bsp_StartHardTimer(2 ,50000, (void *)TIM_CallBack2);


函數(shù) xQueueSendFromISR 在中斷服務(wù)程序中的使用方法

/*

*********************************************************************************************************

*? 函 數(shù) 名: TIM_CallBack1 和 TIM_CallBack2

*? 功能說(shuō)明: 定時(shí)器中斷的回調(diào)函數(shù),此函數(shù)被 bsp_StartHardTimer 所調(diào)用。

*? 形 參: 無(wú)

*? 返 回 值: 無(wú)

*********************************************************************************************************

*/

static uint32_t g_uiCount = 0; /* 設(shè)置為全局靜態(tài)變量,方便數(shù)據(jù)更新 */

static void TIM_CallBack1(void)

{

BaseType_t xResult;

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

/* 中斷消息處理,此處省略 */

……

g_uiCount++;

/* 向消息隊(duì)列發(fā)數(shù)據(jù) */

xQueueSendFromISR(xQueue1,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (void *)&g_uiCount,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &xHigherPriorityTaskWoken);

/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中斷后切到當(dāng)前最高優(yōu)先級(jí)任務(wù)執(zhí)行 */

portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}


static void TIM_CallBack2 (void)

{

MSG_T *ptMsg;

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

/* 中斷消息處理,此處省略 */

……

/* 初始化結(jié)構(gòu)體指針 */

ptMsg = &g_tMsg;

/* 初始化數(shù)組 */

ptMsg->ucMessageID++;

ptMsg->ulData[0]++;

ptMsg->usData[0]++;

/* 向消息隊(duì)列發(fā)數(shù)據(jù) */

xQueueSendFromISR(xQueue2,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (void *)&ptMsg,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &xHigherPriorityTaskWoken);

/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中斷后切到當(dāng)前最高優(yōu)先級(jí)任務(wù)執(zhí)行 */

portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容