中国建设银行天津分行网站,apache wordpress 404,建设审批网站查询,后缀的域名暂无法进行网站备案uCOSii中信号量的作用#xff1a;
在创建信号量时#xff0c;Sem_EventOSSemCreate(1)用于分时复用共享资源#xff1b;
Sem_EventOSSemCreate(0)用于中断和任务间同步或任务之间的同步。
具体在使用时#xff0c;需要灵活运用。在访问共享资源时#xff0c;我喜欢用互…uCOSii中信号量的作用
在创建信号量时Sem_EventOSSemCreate(1)用于分时复用共享资源
Sem_EventOSSemCreate(0)用于中断和任务间同步或任务之间的同步。
具体在使用时需要灵活运用。在访问共享资源时我喜欢用互斥信号量爱好不同而已。 一、uCOSii信号量用于对共享资源的保护
1、举例如下
任务1每隔1小时将DATA1数据保存到EEPROM。
任务2每隔2小时将DATA2数据保存到EEPROM。
可见任务1和任务2都要使用公共资源“写EEPROM”。为了防止使用冲突我们通过发送信号量和接收信号量来分时操作“写EEPROM”保证写入正确。
当然也可以放在一个任务里去做为了了解怎么使用共享资源这里使用信号量来实现。 2、实现方法
1)、声明事件指针
OS_EVENT *Sem_Event;//定义一个事件指针 2)、任务1
//函数功能:任务1每隔1小时将DATA1数据保存到EEPROM。
void SaveDATA1_Task(void *pdata)
{
u16 SaveDATA1_Cnt;
u8 Sem_Err; while(1)
{
OSTimeDlyHMSM(0,0,0,1000);//延时1秒
SaveDATA1_Cnt;
if(SaveDATA1_Cnt 3600)//1小时时间到,保存DATA1
{
OSSemPend(Sem_Event,0,Sem_Err);//等待一个信号量,实现资源保护
EEPROM_U8_Data_Write(DATA1, DATA1_address);
OSSemPost(Sem_Event);//发出一个信号量
SaveDATA1_Cnt 0;
}
}
} 3)、任务2
//函数功能:任务2每隔2小时将DATA2数据保存到EEPROM。
void SaveDATA2_Task(void *pdata)
{
u16 SaveDATA2_Cnt;
u8 Sem_Err; while(1)
{
OSTimeDlyHMSM(0,0,0,1000);//延时1秒
SaveDATA2_Cnt;
if(SaveDATA2_Cnt 7200)//2小时时间到,保存DATA2
{
OSSemPend(Sem_Event,0,Sem_Err);//等待一个信号量,实现资源保护
EEPROM_U8_Data_Write(DATA2, DATA2_address);
OSSemPost(Sem_Event);//发出一个信号量
SaveDATA2_Cnt 0;
}
}
} 4)、启动任务
void Start_Task(void *pdata)
{
OS_CPU_SR cpu_sr0; OS_ENTER_CRITICAL();
//进入临界区(无法被中断打断),需要定义cpu_sr变量
Sem_EventOSSemCreate(1);
//创建信号量Sem_Event设置计数器初始值设置为1即发送了一个信号量。 OSTaskCreate(
SaveDATA1_Task,/* 函数指针*/ (void *)0,/* 建立任务时传递的参数*/ (OS_STK*)SaveDATA1_Task_STACK[SaveDATA1_Task_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/ SaveDATA1_Task_PRIORITY/* 任务优先级*/ ); OSTaskCreate(
SaveDATA2_Task,/* 函数指针*/
(void *)0,/* 建立任务时传递的参数*/
(OS_STK*)SaveDATA2_Task_STACK[SaveDATA2_Task_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/ SaveDATA2_Task_PRIORITY/* 任务优先级*/
); OSTaskDel(OS_PRIO_SELF); //删除自己 OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
} 二、uCOSii使用信号量实现中断和任务之间的同步
1、举例如下
串口接收一组配置参数然后将该参数需要保存到EEPROM中。显然我们不能在中断中写EPPROM这样会导致串口中断执行时间太长。因此需要分成两个部分实现一个是串口接收一个是负责保存参数同时还要干其他事情。
有人会在某个任务中扫描串口若收完配置信息立即保存不用搞这个信号量也实现实现方法千万种。这里使用信号量实现中断和任务之间的同步,完成中断和任务之间无缝隙对接。 2、实现方法
1)、声明事件指针
OS_EVENT *Sem_Event;//定义一个事件指针 2)中断
uint8_t UART4HeadFlag;
uint8_t UART4_in; //UART4接收缓冲区的输入下标;
#define UART4_RCV_buffer_Size 100
//定义UART4接收缓冲区的长度100;
uint8_t UART4_RCV_buffer[UART4_RCV_buffer_Size];
//用来存放硬件串口接收到的数据;
//(ID04661219C1677461)
//函数功能:USART4中断服务函数
void UART4_IRQHandler(void)
{ unsigned char temp; (void)temp;//不让temp产生警告 if(USART_GetITStatus(UART4, USART_IT_RXNE) ! RESET) { tempUSART_ReceiveData(UART4); //从UART4串口读取一个字节; if(temp’(’ UART4HeadFlag0)
{
UART4_in 0;
UART4HeadFlag1;
}
if(UART4HeadFlag1)
{
UART4_RCV_buffer[UART4_in]temp;
UART4_in;
} if(temp’)’ UART4HeadFlag1)
{
UART4_in 0;
UART4HeadFlag0;//接收完成
OSSemPost(Sem_Event);//发出一个信号量
} } if(USART_GetFlagStatus(UART4,USART_FLAG_PE) ! RESET) { USART_ReceiveData(UART4);//读串口 USART_ClearFlag(UART4, USART_FLAG_PE); } if(USART_GetFlagStatus(UART4,USART_FLAG_ORE) ! RESET) { USART_ReceiveData(UART4);//读串口 USART_ClearFlag(UART4,USART_FLAG_ORE); //清除溢出中断 } if(USART_GetFlagStatus(UART4,USART_FLAG_FE) ! RESET) { USART_ReceiveData(UART4);//读串口 USART_ClearFlag(UART4,USART_FLAG_FE); }
} 3)、任务1
void Task1(void *pdata)
{
u8 Sem_Err; while(1)
{
OSSemPend(Sem_Event,0,Sem_Err);//等待一个信号量,实现无缝对接
{
Save_String_To_EEPROM(UART4_RCV_buffer,UART4_in,ID_address);
}
}
} void LED1_Task(void *pdata)
{
while(1)
{
LED1!LED1;//信号有效 OSTimeDlyHMSM(0,0,0,500);//500毫秒闪烁1次
}
} 4)、启动任务
void Start_Task(void *pdata)
{
OS_CPU_SR cpu_sr0; OS_ENTER_CRITICAL();
//进入临界区(无法被中断打断),需要定义cpu_sr变量
Sem_EventOSSemCreate(0);
//创建信号量Sem_Event设置计数器初始值设置为0即不发送一个信号量 OSTaskCreate(
Task1,/* 函数指针*/ (void *)0,/* 建立任务时传递的参数*/ (OS_STK*)Task1_STACK[Task1_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/ Task1_PRIORITY/* 任务优先级*/ ); OSTaskCreate(
LED1_Task,/* 函数指针*/ (void *)0,/* 建立任务时传递的参数*/ (OS_STK*)LED1_TASK_STACK[LED1_TASK_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/ LED1_TASK_PRIORITY/* 任务优先级*/ ); OSTaskDel(OS_PRIO_SELF); //删除自己 OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
} 三、uCOSii使用信号量实现任务和任务之间的同步
1、举例如下
任务1为负责按键触发
任务2负责点灯。
任务1中的按键KEY按下任务2负责点灯ED1开灯关灯。
使用信号量实现任务与任务之间的同步,完成任务与任务之间无缝隙对接。 2、实现方法
1)、声明事件指针
OS_EVENT *Sem_Event;//定义一个事件指针 2)、任务1
//函数功能:任务1负责按键触发。
void Key_Task(void *pdata)
{
u8 Sem_Err; while(1)
{
if(KEY)OSSemPost(Sem_Event);//发出一个信号量
LED0!LED0;
OSTimeDlyHMSM(0,0,0,500);//500毫秒闪烁1次
}
} 3)、任务2
void LED_Task(void *pdata)
{
u8 Sem_Err; while(1)
{
OSSemPend(Sem_Event,0,Sem_Err);//等待一个信号量,实现无缝对接
LED1!LED1;//信号有效
}
} 4)、启动任务
void Start_Task(void *pdata)
{
OS_CPU_SR cpu_sr0;
OS_ENTER_CRITICAL();
//进入临界区(无法被中断打断),需要定义cpu_sr变量
Sem_EventOSSemCreate(0);
//创建信号量Sem_Event设置计数器初始值设置为0即不发送一个信号量 OSTaskCreate(
LED_Task,/* 函数指针*/ (void *)0,/* 建立任务时传递的参数*/ (OS_STK*)LED_Task_STACK[LED_Task_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/ LED_Task_PRIORITY/* 任务优先级*/ ); OSTaskCreate(
Key_Task,/* 函数指针*/ (void *)0,/* 建立任务时传递的参数*/ (OS_STK*)KEY_TASK_STACK[KEY_TASK_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/ KEY_TASK_PRIORITY/* 任务优先级*/ ); OSTaskDel(OS_PRIO_SELF); //删除自己 OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}