FreeRTOS队列

在实际应用中,我们会遇到一个任务或者中断服务需要和另一个任务进行消息传递,FreeRTOS提供了队列的机制来完成任务与任务、任务与中断之间的消息传递。

0x01 队列简介

队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。队列中能保存的最大数据项目数量叫做队列的长度。

1. 数据存储

队列提供了FIFO、LIFO的存储缓冲机制,数据发送到队列中会导致数据拷贝,数据拷贝是值传递,在队列中存储的是数据的原始值,而不是原始值的引用(即值传递数据的引用),FreeRTOS中使用队列传递消息的话虽然使用的是数据拷贝,但是也可以使用引用来传递消息,直接往队列中发送指向这个消息的地址指针就可以了。

2. 多任务访问

队列不属于某个特别指定的任务,任何任务都可以向队列中发送消息,提取消息

0x02 队列结构体

队列的类型是Queue_t,定义在queue.c文件中

typedef struct QueueDefinition
{int8_t *pcHead;					/*< Points to the beginning of the queue storage area. */int8_t *pcTail;					/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */int8_t *pcWriteTo;				/*< Points to the free next place in the storage area. */union							/* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */{int8_t *pcReadFrom;			/*< Points to the last place that a queued item was read from when the structure is used as a queue. */UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */} u;List_t xTasksWaitingToSend;		/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */List_t xTasksWaitingToReceive;	/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */UBaseType_t uxLength;			/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */UBaseType_t uxItemSize;			/*< The size of each items that the queue will hold. */volatile int8_t cRxLock;		/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */volatile int8_t cTxLock;		/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */#endif#if ( configUSE_QUEUE_SETS == 1 )struct QueueDefinition *pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif} xQUEUE;/* The old xQUEUE name is maintained above then typedefed to the new Queue_t
name below to enable the use of older kernel aware debuggers. */
typedef xQUEUE Queue_t;
  • pcHead:指向队列存储区首地址
  • pcTail:指向队列存储区最后一个字节地址
  • pcWriteTo:指向下一个可以存储的地址
  • pcReadFrom:当用作队列的时候,指向最后一个出队的队列项首地址
  • uxRecursiveCallCount:当用作递归互斥量的时候用来记录递归互斥量被调用的次数
  • xTasksWaitingToSend:等待发送任务列表,那些因为队列满导致入队失败而进入阻塞态的任务就会挂到此列表上
  • xTasksWaitingToReceive:等待接受任务列表,那些因为队列空导致出队失败而进入阻塞态的任务就会挂到此列表上
  • uxMessagesWaiting:队列中当前消息数
  • uxLength:队列中最大允许的消息数量
  • uxItemSize:每个消息最大长度
  • cRxLock:当列表上锁后,统计出队的消息数量
  • cTxLock:当列表上锁后,统计入队的消息数量

0x03 队列创建

队列创建有两种方法:

  1. 方法1:使用xQueueCreate函数动态创建
  2. 方法2:使用xQueueCreateStatic动态创建
1. xQueueCreate

从源码可以看出,使用xQueueCreate,configSUPPORT_DYNAMIC_ALLOCATION 要等于1,支持动态分配内存

 QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,UBaseType_t uxItemSize)
  • uxQueueLength:要创建的队列的队列长度,即最多可以接受多少个消息
  • uxItemSize :队列中每个消息的长度

创建成功返回队列句柄,失败返回NULL

2.xQueueCreateStatic
 QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorageBuffer,StaticQueue_t *pxQueueBuffer);
  • uxQueueLength:要创建的队列的队列长度,即最多可以接受多少个消息
  • uxItemSize :队列中每个消息的长度
  • pucQueueStorage:指向消息的存储区,是一个uint8_t类型的数组,数组的大小要大于等于(uxQueueLength*uxItemSize )
  • pxQueueBuffer :保存队列结构体

创建成功返回队列句柄,失败返回NULL

0x04 向队列发送消息

1. 函数原型

创建好队列就可以向队列发送消息了,FreeRTOS提供了8个向对列发送消息的API函数。
在这里插入图片描述

1.1 xQueueSend、xQueueSendToBack、xQueueSendToToFront
 BaseType_t xQueueSend(QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);BaseType_t xQueueSendToBack(QueueHandle_t	xQueue,const void		*pvItemToQueue,TickType_t		xTicksToWait);BaseType_t xQueueSendToToFront(QueueHandle_t	xQueue,const void		*pvItemToQueue,TickType_t		xTicksToWait);
  • QueueHandle_t xQueue:任务句柄,指明要向那个队列发送数据
  • const void *pvItemToQueue:指向要发送的数据,发送的时候会将这个消息拷贝到队列中
  • TickType_t xTicksToWait:阻塞时间,此参数指示队列满的时候任务进入阻塞态等待队列空闲的最大时间,如果是0,队列满会立即返回,当为portMAX_DELAY就会一直等待。

成功返回pdPASS,失败返回errQUEUE_FULL

1.2 xQueueOverwrite
 BaseType_t xQueueOverwrite(QueueHandle_t xQueue,const void * pvItemToQueue);
  • QueueHandle_t xQueue:队列句柄,指明要向那个队列发送数据
  • const void * pvItemToQueue:要发送的数据
1.3 xQueueSendFromISR、xQueueSendToBackFromISR、xQueueSendToFrontFromISR
 BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue,const void * pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);
  • QueueHandle_t xQueue:队列句柄,指明要向那个队列发送数据
  • const void *pvItemToQueue:要发送的数据
  • BaseType_t *pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换,这个变量由三个函数来设置,用户不用进行设置,用户只需提供一个变量来保存这个值就行了。当此值为pdTRUE的时候在退出中断服务函数之前一定要进行一次任务切换。

成功返回pdTURE,失败返回errQUEUE_FULL

0x05 从队列读取消息

从队列中获取消息,FreeRTOS相关API函数如下
在这里插入图片描述

1. xQueueReceive、xQueuePeek
BaseType_t xQueueReceive(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait)BaseType_t xQueuePeek(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait);
  • QueueHandle_t xQueue:指明读取那个队列的数据
  • void *pvBuffer:读取队列的过程中将读取的数据拷贝到这个缓冲区
  • TickType_t xTicksToWait:阻塞时间,如果为0,队列为空立即返回,当为portMAX_DELAY的话就一直等待,直到队列有数据。
2. xQueueReceiveFromISR
 BaseType_t xQueueReceiveFromISR(QueueHandle_t	xQueue,void	*pvBuffer,BaseType_t *pxTaskWoken);BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,void *pvBuffer,);
  • QueueHandle_t xQueue:指明读取那个队列的数据
  • void *pvBuffer:读取队列的过程中将读取的数据拷贝到这个缓冲区
  • BaseType_t *pxTaskWoken:标记退出此函数以后是否进行任务切换

返回值:
返回pdTRUE,从队列中读取数据成功,返回pdFALSE,从队列中读取数据失败。

验证

实验设计三个任务,start_task、task1_task、Keyprocess_task这三个任务。
start_task:用来创建其他两个任务
task1_task:读取按键的键值,然后将键值发送到KEY_Queue队列中,并且检查队列的剩余容量等信息
Keyprocess_task:按键处理任务,读取队列Key_Queue中的信息,根据不同的消息值做相应的处理。
实验需要是哪个按键KEY_UP、KEY2、KEY0,不同的按键对应不同的按键值,任务task1_task会将这些值发送到队列Key_Queue中。
实验中创建两个队列Key_Queue和Message_Queue,队列Key_Queue用于传递按键值,队列Message_Queue用于传递串口发送过来的消息。
实验还需要两个中断,一个是串口1接收中断,一个是定时器9中断,他们的作用如下:串口1接收中断,接收串口发送过来的数据,并将接收到的数据发送到队列Message_Queue中,定时器9中断,定时周期为500ms,在定时器中断中读取队列Message_Queue中的消息,并将其显示在LCD上。

start_task代码:

//开始任务任务函数
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建消息队列Key_Queue=xQueueCreate(KEYMSG_Q_NUM,sizeof(u8));        //创建消息Key_QueueMessage_Queue=xQueueCreate(MESSAGE_Q_NUM,USART_REC_LEN); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度//创建TASK1任务xTaskCreate((TaskFunction_t )task1_task,             (const char*    )"task1_task",           (uint16_t       )TASK1_STK_SIZE,        (void*          )NULL,                  (UBaseType_t    )TASK1_TASK_PRIO,        (TaskHandle_t*  )&Task1Task_Handler);   //创建TASK2任务xTaskCreate((TaskFunction_t )Keyprocess_task,     (const char*    )"keyprocess_task",   (uint16_t       )KEYPROCESS_STK_SIZE,(void*          )NULL,(UBaseType_t    )KEYPROCESS_TASK_PRIO,(TaskHandle_t*  )&Keyprocess_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}

在start_task中创建了两个队列,分别是Key_Queue和Message_Queue,Key_Queue用于和按键通信,Message_Queue用于和串口通信。

task1_task代码

//task1任务函数
void task1_task(void *pvParameters)
{u8 key,i=0;BaseType_t err;while(1){key=KEY_Scan(0);            //扫描按键if((Key_Queue!=NULL)&&(key))   //消息队列Key_Queue创建成功,并且按键被按下{err=xQueueSend(Key_Queue,&key,10);if(err==errQUEUE_FULL)   //发送按键值{printf("队列Key_Queue已满,数据发送失败!\r\n");}}i++;if(i%10==0) check_msg_queue();//检Message_Queue队列的容量if(i==50){i=0;LED0=!LED0;}vTaskDelay(10);                           //延时10ms,也就是10个时钟节拍	}
}

task1_task获取按键值,并将按键值发送到Key_Queue中

Keyprocess_task代码:

//Keyprocess_task函数
void Keyprocess_task(void *pvParameters)
{u8 num,key,beepsta=1;while(1){if(Key_Queue!=NULL){if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))//请求消息Key_Queue{switch(key){case WKUP_PRES:		//KEY_UP控制LED1LED1=!LED1;break;case KEY1_PRES:		//KEY1控制蜂鸣器beepsta=!beepsta;BEEP=beepsta;break;case KEY0_PRES:		//KEY0刷新LCD背景num++;LCD_Fill(126,111,233,313,lcd_discolor[num%14]);break;}}} vTaskDelay(10);      //延时10ms,也就是10个时钟节拍	}
}

Keyprocess_task获取Key_Queue队列中按键值

整个main.c代码如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "sdram.h"
#include "key.h"
#include "timer.h"
#include "beep.h"
#include "string.h"
#include "malloc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/************************************************ALIENTEK 水星STM32F429开发板 FreeRTOS实验13-1FreeRTOS队列操作实验-HAL库版本技术支持:www.openedv.com淘宝店铺:http://eboard.taobao.com 关注微信公众平台微信号:"正点原子",免费获取STM32资料。广州市星翼电子科技有限公司  作者:正点原子 @ALIENTEK
************************************************///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		256  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define TASK1_TASK_PRIO		2
//任务堆栈大小	
#define TASK1_STK_SIZE 		256  
//任务句柄
TaskHandle_t Task1Task_Handler;
//任务函数
void task1_task(void *pvParameters);//任务优先级
#define KEYPROCESS_TASK_PRIO 3
//任务堆栈大小	
#define KEYPROCESS_STK_SIZE  256 
//任务句柄
TaskHandle_t Keyprocess_Handler;
//任务函数
void Keyprocess_task(void *pvParameters);//按键消息队列的数量
#define KEYMSG_Q_NUM    1  		//按键消息队列的数量  
#define MESSAGE_Q_NUM   4   	//发送数据的消息队列的数量 
QueueHandle_t Key_Queue;   		//按键值消息队列句柄
QueueHandle_t Message_Queue;	//信息队列句柄//LCD刷屏时使用的颜色
int lcd_discolor[14]={	WHITE, BLACK, BLUE,  BRED,      GRED,  GBLUE, RED,   MAGENTA,       	 GREEN, CYAN,  YELLOW,BROWN, 			BRRED, GRAY };//用于在LCD上显示接收到的队列的消息
//str: 要显示的字符串(接收到的消息)
void disp_str(u8* str)
{LCD_Fill(5,230,110,245,WHITE);					//先清除显示区域LCD_ShowString(5,230,100,16,16,str);
}//加载主界面
void freertos_load_main_ui(void)
{POINT_COLOR = RED;LCD_ShowString(10,10,200,16,16,"Apollo STM32F4/F7");	LCD_ShowString(10,30,200,16,16,"FreeRTOS Examp 13-1");LCD_ShowString(10,50,200,16,16,"Message Queue");LCD_ShowString(10,70,220,16,16,"KEY_UP:LED1 KEY0:Refresh LCD");LCD_ShowString(10,90,200,16,16,"KEY1:SendMsg KEY2:BEEP");POINT_COLOR = BLACK;LCD_DrawLine(0,107,239,107);		//画线LCD_DrawLine(119,107,119,319);		//画线LCD_DrawRectangle(125,110,234,314);	//画矩形POINT_COLOR = RED;LCD_ShowString(0,130,120,16,16,"DATA_Msg Size:");LCD_ShowString(0,170,120,16,16,"DATA_Msg rema:");LCD_ShowString(0,210,100,16,16,"DATA_Msg:");POINT_COLOR = BLUE;
}//查询Message_Queue队列中的总队列数量和剩余队列数量
void check_msg_queue(void)
{u8 *p;u8 msgq_remain_size;	//消息队列剩余大小u8 msgq_total_size;     //消息队列总大小taskENTER_CRITICAL();   //进入临界区msgq_remain_size=uxQueueSpacesAvailable(Message_Queue);//得到队列项剩余大小msgq_total_size=uxQueueMessagesWaiting(Message_Queue)+uxQueueSpacesAvailable(Message_Queue);//得到队列总大小,总大小=使用+剩余的。p=mymalloc(SRAMIN,20);	//申请内存sprintf((char*)p,"Total Size:%d",msgq_total_size);	//显示DATA_Msg消息队列总的大小LCD_ShowString(10,150,100,16,16,p);sprintf((char*)p,"Remain Size:%d",msgq_remain_size);	//显示DATA_Msg剩余大小LCD_ShowString(10,190,100,16,16,p);myfree(SRAMIN,p);		//释放内存taskEXIT_CRITICAL();    //退出临界区
}int main(void)
{HAL_Init();                     //初始化HAL库   Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhzdelay_init(180);                //初始化延时函数uart_init(115200);              //初始化串口LED_Init();                     //初始化LED KEY_Init();                     //初始化按键BEEP_Init();                 	//初始化蜂鸣器SDRAM_Init();                   //初始化SDRAMLCD_Init();                     //初始化LCDTIM9_Init(5000,18000-1);		//初始化定时器9,周期500msmy_mem_init(SRAMIN);            //初始化内部内存池freertos_load_main_ui();        //加载主UI//创建开始任务xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄                vTaskStartScheduler();          //开启任务调度
}//开始任务任务函数
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建消息队列Key_Queue=xQueueCreate(KEYMSG_Q_NUM,sizeof(u8));        //创建消息Key_QueueMessage_Queue=xQueueCreate(MESSAGE_Q_NUM,USART_REC_LEN); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度//创建TASK1任务xTaskCreate((TaskFunction_t )task1_task,             (const char*    )"task1_task",           (uint16_t       )TASK1_STK_SIZE,        (void*          )NULL,                  (UBaseType_t    )TASK1_TASK_PRIO,        (TaskHandle_t*  )&Task1Task_Handler);   //创建TASK2任务xTaskCreate((TaskFunction_t )Keyprocess_task,     (const char*    )"keyprocess_task",   (uint16_t       )KEYPROCESS_STK_SIZE,(void*          )NULL,(UBaseType_t    )KEYPROCESS_TASK_PRIO,(TaskHandle_t*  )&Keyprocess_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}//task1任务函数
void task1_task(void *pvParameters)
{u8 key,i=0;BaseType_t err;while(1){key=KEY_Scan(0);            //扫描按键if((Key_Queue!=NULL)&&(key))   //消息队列Key_Queue创建成功,并且按键被按下{err=xQueueSend(Key_Queue,&key,10);if(err==errQUEUE_FULL)   //发送按键值{printf("队列Key_Queue已满,数据发送失败!\r\n");}}i++;if(i%10==0) check_msg_queue();//检Message_Queue队列的容量if(i==50){i=0;LED0=!LED0;}vTaskDelay(10);                           //延时10ms,也就是10个时钟节拍	}
}//Keyprocess_task函数
void Keyprocess_task(void *pvParameters)
{u8 num,key,beepsta=1;while(1){if(Key_Queue!=NULL){if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))//请求消息Key_Queue{switch(key){case WKUP_PRES:		//KEY_UP控制LED1LED1=!LED1;break;case KEY1_PRES:		//KEY1控制蜂鸣器beepsta=!beepsta;BEEP=beepsta;break;case KEY0_PRES:		//KEY0刷新LCD背景num++;LCD_Fill(126,111,233,313,lcd_discolor[num%14]);break;}}} vTaskDelay(10);      //延时10ms,也就是10个时钟节拍	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

括号配对问题(C)

描述 现在&#xff0c;有一行括号序列&#xff0c;请你检查这行括号是否配对。 输入 第一行输入一个数N&#xff08;0<N<100&#xff09;,表示有N组测试数据。后面的N行输入多组输入数据&#xff0c;每组输入数据都是一个字符串S(S的长度小于10000&#xff0c;且S不是空串…

剧情介绍:“阿甘正传”

阿甘是个智商只有75的低能儿。在学校里为了躲避别的孩子的欺侮&#xff0c;听从一个朋友珍妮的话而开始“跑”。他跑着躲避别人的捉弄。在中学时&#xff0c;他为了躲避别人而跑进了一所学校的橄榄球场&#xff0c;就这样跑进了大学。阿甘被破格录取&#xff0c;并成了橄榄球巨…

java 方法 示例_Java集合syncedList()方法与示例

java 方法 示例集合类syncList()方法 (Collections Class synchronizedList() method) synchronizedList() method is available in java.util package. syncList()方法在java.util包中可用。 synchronizedList() method is used to return the synchronized view of the given…

FreeRTOS信号量---二值信号量

信号量可以用来进行资源管理和任务同步&#xff0c;FreeRTOS中信号量又分为二值信号量、计算型信号量、互斥信号量和递归互斥信号量。 0x01 二值信号量 二值信号量其实就是一个只有一个队列项的队列&#xff0c;这个特殊的队列要么是满的&#xff0c;要么是空的&#xff0c;任…

Linux 上 rpm包管理工具的基本使用

查询是否安装某个包&#xff1a;rpm -q 包名查询所有已安装的包&#xff1a;rpm -q a查询未安装包的文件信息&#xff1a;rpm -qilp 未安装的包安装包&#xff1a;rpm -i 包测试安装包&#xff1a;rpm -i test 包删除包&#xff1a;rpm -e 包名测试删除包&#xff1a;rpm -e te…

ios 内存使用陷阱

在iphone开发过程中&#xff0c;代码中的内存泄露我们很容易用内存检测工具leaks 检测出来&#xff0c;并一一改之&#xff0c;但有些是因为ios 的缺陷和用法上的错误&#xff0c;leaks 检测工具并不能检测出来&#xff0c;你只会看到大量的内存被使用&#xff0c;最后收到didR…

FreeRTOS软件定时器

软件定时器允许设置一段时间&#xff0c;当设置的时间达到后就执行指定的功能函数&#xff0c;被软件定时器调用的功能函数叫做定时器的回调函数。软件定时器的回调函数是在定时器服务任务中执行的&#xff0c;所以一定不能在回调函数中调用任何阻塞任务的API函数&#xff0c;比…

Java类class isAssignableFrom()方法及示例

类class isAssignableFrom()方法 (Class class isAssignableFrom() method) isAssignableFrom() method is available in java.lang package. isAssignableFrom()方法在java.lang包中可用。 isAssignableFrom() method is used to check whether the class or an interface den…

关于 列表实例

wss3.0工具中有个列表实例项目。此项目的作用是在自定义网站或自定义字段时使用默认值。也就是定义其默认的数据。 格式详见微软msdn&#xff1a;http://msdn.microsoft.com/zh-cn/library/ms478860.aspx转载于:https://www.cnblogs.com/heavencloud/archive/2009/03/20/141793…

WP7之Application Bar控件

Microsoft.Phone.Shell命名空间中定义了ApplicationBar及其相关类&#xff08;ApplicationBarIconButton和ApplicationBarMenuItem&#xff09;&#xff0c;这些类派生自Object,并完全独立于常规Silverlight编程中的DependencyObject,UIElement和FrameworkElement类层次结构。A…

TomCat使用以及端口号被占用的处理方法

一.HTTP协议 什么是HTTP协议 HTTP协议&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是因特网上应用最为广泛的一种网络传输协议&#xff0c;所有的WWW文件都必须遵守这个标准。 HTTP请求 HTTP响应 2.如何处理端口被占用 方法一&#xff…

FreeRTOS事件标志组

使用信号量来同步的话&#xff0c;任务只能与单个事务或任务进行同步&#xff0c;有时候某个任务可能会需要与多个事件或任务进行同步&#xff0c;此时信号量就无能为力了&#xff0c;FreeRTOS为此提供了一个可选的解决方法&#xff0c;那就是事件标志组。 0x01 事件标志组 事…

FusionCharts等产品简介

以前做柱状图、饼形图等图表都是根据数据绘制出来的静态图&#xff0c;偶然看到别人的一套系统&#xff0c;居然可以让柱状图的柱子动画般的逐个出现&#xff0c;效果还是很不错的。不要跟我抬杠说不就是展现数据嘛&#xff0c;静态图表有什么不好&#xff0c;要知道用户一般可…

c#foreach循环_C#| 使用foreach循环打印整数数组

c#foreach循环Given an integer array and we have to print its elements using "foreach loop" in C#. 给定一个整数数组&#xff0c;我们必须在C&#xff03;中使用“ foreach循环”打印其元素 。 Syntax for foreach loop: foreach循环的语法&#xff1a; fore…

Eclipse和Tomcat绑定并且将上传资源到Tomcat上

步骤如下&#xff1a; 创建一个Dynamic Web Project&#xff08;图一&#xff09; Target runtime 选择Apache Tomcat v7.0版本&#xff08;图二&#xff09; 切记要选择 v7.0 和2.5 &#xff08;若没有图二选项见图三&#xff09; 然后&#xff0c;点击window --> Prefer…

浅析.NET平台编程语言的未来走向

在去年的PDC2008召开期间&#xff0c;微软逐步公开了围绕.NET和编程语言的很多想法&#xff0c;据此我们可以饶有兴趣地对.NET的未来预测一番。 .NET平台以运行在通用语言运行时(Common Language Runtime&#xff0c;CLR)上的C#和VB.NET作为开端。CLR是通用语言架构(Common Lan…

FreeRTOS任务通知

从v8.2.0版本开始&#xff0c;FreeRTOS新增了任务通知这个功能&#xff0c;可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西&#xff0c;使用任务通知的话效率会更高。 任务通知在FreeRTOS是一个可选的选项&#xff0c;要使用任务通知的话就需要将宏configUSE_T…

kinect在openni下也能玩抠出人物换背景

之前想了个很拉风的名字《用kinect玩穿越》&#xff0c;但是现在功能还不是很完善&#xff0c;细节处理也不是很好&#xff0c;脸皮没有足够的厚&#xff0c;所以呢还是叫换背景吧。 这里面包含两个技术要点&#xff1a; 一、抠出活动人物 在微软的SDK里深度图像的前3位即0-2位…

物联网基础知识_联网| 基础知识能力问答 套装1

物联网基础知识1) There are the following statements that are given below, which of them are correct about the computer network? A computer network is an interconnection between multiple devices to share hardware resources and information.A computer networ…

Emit学习-基础篇-基本概念介绍

之前的Hello World例子应该已经让我们对Emit有了一个模糊的了解&#xff0c;那么Emit到底是什么样一个东西&#xff0c;他又能实现些什么功能呢&#xff1f;昨天查了点资料&#xff0c;大致总结了下&#xff0c;由于才开始学习肯定有不完善的地方&#xff0c;希望大家能够批评指…