FreeRTOS *** 作系统例程(8):消息队列

FreeRTOS *** 作系统例程(8):消息队列,第1张

安富莱电子 www.armfly.com

安富莱_STM32-V5开发板_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

/*

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

*  函 数 名: AppObjCreate

*  功能说明: 创建早雹任务通信机制

*  形 参: 无

*  返 回 值: 无

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

*/

static void AppObjCreate (void)

{

/* 创建 10 个 uint8_t 型消息队列 */

xQueue1 = xQueueCreate(10, sizeof(uint8_t))

if( xQueue1 == 0 )

{

/* 没有创建成功,用户可以在这里加入创建失败的处理机制 */

}

/* 创建 10 个存储指针变量的消息队列,由于 CM3/CM4 内核是 32 位机,一个指针变量占用 4 个字节 */

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

if( xQueue2 == 0 )

{

/* 没有创建成功,用户可以在这里加入创建失败的处理机制 */

}

}

//初始化定义

uint8_t ucCount = 0

/* while循环里实现向 xQueue2 发送数据 */

ucCount++

/* 向消息队列发数据,如果消息队列满了,等待 10 个时钟节拍 */

if( xQueueSend(xQueue1,

                          (void *) &ucCount,

                          (TickType_t)10) != pdPASS )

{

/* 发送失败,即使等待了 10 个时钟节拍 */

printf("向 xQueue1 发送数据失败,帆凳即使等待了 10 个时钟节拍\r\n")

}

else

{

/* 发送成功 */

printf("向 xQueue1 发送数据成功\r\n")

}

//初始化定义

MSG_T *ptMsg

/* 初始化结构体指针 */

ptMsg = &g_tMsg

/* 初始化数组 */

ptMsg->ucMessageID = 0

ptMsg->ulData[0] = 0

ptMsg->usData[0] = 0

/* while循环里实现向 xQueue2 发送数据 */

ptMsg->ucMessageID++

ptMsg->ulData[0]++

ptMsg->usData[0]++

/* 使用消息队列实现指针变量的传递 */

if(xQueueSend(xQueue2, /* 消息队列句柄 */

                         (void *) &ptMsg, /* 发送结构体指针变量 ptMsg 的地址 */

                         (TickType_t)10) != pdPASS )

{

/* 发送失败,即使等待了 10 个时钟节拍 */

printf("向 xQueue2 发送数据失败,即使等待了 10 个时钟节拍\r\n")

}

else

{

/* 发送成功 */

printf("向 xQueue2 发送数据成功\r\n")

}

static QueueHandle_t xQueue1 = NULL

/*

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

*  函 数 名: vTaskMsgPro

*  功能说明: 使用函数 xQueueReceive 接收任务 vTaskTaskUserIF 发送的消息队列数据(xQueue1)

*  形 参: pvParameters 是在创建该任务时传递的形参

*  返 回 值: 无

* 优 先 级: 3

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

*/

static void vTaskMsgPro(void *pvParameters)

{

BaseType_t xResult

const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300)/* 设置最大等待时间为 300ms */

uint8_t ucQueueMsgValue

while(1)

{

xResult = xQueueReceive(xQueue1, /* 消息队列句柄 */

                                           (void *)&ucQueueMsgValue, /* 存储接收到的数据到变量 ucQueueMsgValue 中 */

                                           (TickType_t)xMaxBlockTime)/* 设置阻塞时间 */

if(xResult == pdPASS)

{

/* 成功接收,并通过串口将数据打印出来 */

printf("接收到消息队列数据 ucQueueMsgValue = %d\r\n", ucQueueMsgValue)

}

else

{

/* 超时 */

bsp_LedToggle(1)

bsp_LedToggle(4)

}

}

}

/*

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

*  函 数 名: vTaskLED

*  功能说明: 使用函数 xQueueReceive 接收任务 vTaskTaskUserIF 发送的消息队列数据(xQueue2)

*  形 参: pvParameters 是在创建该任务时传递的形参

*  返 回 值: 无

* 优 先 级: 2

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

*/

static void vTaskLED(void *pvParameters)

{

MSG_T *ptMsg

BaseType_t xResult

const TickType_t xMaxBlockTime = pdMS_TO_TICKS(200)/* 设置最大等待时间为 200ms */

while(1)

{

xResult = xQueueReceive(xQueue2, /* 消息队列句柄 */

                                          (void *)&ptMsg, /* 这里获取的是结构体的地址 */

                                          (TickType_t)xMaxBlockTime)/* 设置阻塞时间 */

if(xResult == pdPASS)

{

/* 成功接收,并通过串口将数据打印出来 */

printf("接收到消息队列数据 ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID)

printf("接收到消息队列数据 ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0])

printf("接收到消息队列数据 ptMsg->usData[0] = %d\r\n", ptMsg->usData[0])

}

else

{

/* 超时 */

bsp_LedToggle(2)

bsp_LedToggle(3)

}

}

}

/*按键或什么外部触发启动定时器*/

printf("启动单次定时器中断,50ms 后在定时器中断给任务 vTaskMsgPro 发送消息\r\n")

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

printf("启动单次定时器中断,50ms 后在定时器中断给任务 vTaskLED 发送消息\r\n")

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

/*

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

*  函 数 名: TIM_CallBack1 和 TIM_CallBack2

*  功能说明: 定时器中断的回调函数,此函数被 bsp_StartHardTimer 所调用。

*  形 参: 无

*  返 回 值: 无

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

*/

static uint32_t g_uiCount = 0/* 设置为全局静态变量,方便数据更新 */

static void TIM_CallBack1(void)

{

BaseType_t xResult

BaseType_t xHigherPriorityTaskWoken = pdFALSE

/* 中断消息处理,此处省略 */

……

g_uiCount++

/* 向消息队列发数据 */

xQueueSendFromISR(xQueue1,

                                    (void *)&g_uiCount,

                                    &xHigherPriorityTaskWoken)

/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */

portYIELD_FROM_ISR(xHigherPriorityTaskWoken)

}

static void TIM_CallBack2 (void)

{

MSG_T *ptMsg

BaseType_t xHigherPriorityTaskWoken = pdFALSE

/* 中断消息处理,此处省略 */

……

/* 初始化结构体指针 */

ptMsg = &g_tMsg

/* 初始化数组 */

ptMsg->ucMessageID++

ptMsg->ulData[0]++

ptMsg->usData[0]++

/* 向消息队列发数据 */

xQueueSendFromISR(xQueue2,

                                    (void *)&ptMsg,

                                    &xHigherPriorityTaskWoken)

/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */

portYIELD_FROM_ISR(xHigherPriorityTaskWoken)

}

java中的消息队列

消息队列是线程间通讯的手段:

import java.util.*

public class MsgQueue{

private Vector queue = null

public MsgQueue(){

queue = new Vector()

}

public synchronized void send(Object o)

{

queue.addElement(o)

}

public synchronized Object recv()

{

if(queue.size()==0)

return null

Object o = queue.firstElement()

queue.removeElementAt(0)//or queue[0] = null can also work

return o

}

}

因为java中是locked by object的所以添加synchronized 就可以用于线程同步锁定对象

可以作为多线程处理多任务的存放task的队列。他的client包括封装好的task类以及thread类

Java的多线程-线程间的通信2009-08-25 21:58

1. 线程的几种状态

线程有四种状态,任何一个线程肯定处于这四种状态中的一种:

1) 产生(New):线程对象已经产生,但尚未被启动,所以无法执行。如通过new产生了一个线程对象后没对它调用start()函数之前。

2) 可执行(Runnable):每个支持多线程的系统都仔姿有一个排程器,排程器会从线程池念掘绝中选择一个线程并启动它。当一个线程处于可执行状态时,表示它可能正处于线程池中等待排排程器启动它;也可能它已正在执行。如执行了一个线程对象的start()方法后,线程就处于可散液执行状态,但显而易见的是此时线程不一定正在执行中。

3) 死亡(Dead):当一个线程正常结束,它便处于死亡状态。如一个线程的run()函数执行完毕后线程就进入死亡状态。

4) 停滞(Blocked):当一个线程处于停滞状态时,系统排程器就会忽略它,不对它进行排程。当处于停滞状态的线程重新回到可执行状态时,它有可能重新执行。如通过对一个线程调用wait()函数后,线程就进入停滞状态,只有当两次对该线程调用notify或notifyAll后它才能两次回到可执行状态。

2. class Thread下的常用函数函数

2.1 suspend()、resume()

1) 通过suspend()函数,可使线程进入停滞状态。通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回可执行状态。

2) 当调用suspend()函数后,线程不会释放它的“锁标志”。

例11:

class TestThreadMethod extends Thread{

public static int shareVar = 0

public TestThreadMethod(String name){

super(name)

}

public synchronized void run(){

if(shareVar==0){

for(int i=0i<5i++){

shareVar++

if(shareVar==5){

this.suspend() //(1)

}}}

else{

System.out.print(Thread.currentThread().getName())

System.out.println(" shareVar = " + shareVar)

this.resume() //(2)

}}

}

public class TestThread{

public static void main(String[] args){

TestThreadMethod t1 = new TestThreadMethod("t1")

TestThreadMethod t2 = new TestThreadMethod("t2")

t1.start() //(5)

//t1.start() //(3)

t2.start() //(4)

}}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12283224.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存