一、基本配置
1、配置RCC、USART1、时钟84MHz
2、配置SYS,将Timebase Source修改为除滴答定时器外的其他定时器。
3、初始化LED的两个引脚、两个按键引脚
4、开启FreeRTOS,v1与v2版本不同,一般选用v1即可
5、创建二值信号量Binary Semaphore
Semaphore Name: 信号量名称
Allocation: 分配方式
Dynamic
动态内存创建Conrol Block Name: 控制块名称
如果想要创建计数信号量Counting Semaphore,必须在 Config parameters
中进行使能。
Semaphore Name: 信号量名称
Count: 计数信号量的最大值
Allocation: 分配方式:
Dynamic
动态内存创建Conrol Block Name: 控制块名称
6、创建两个任务,一个接收任务,一个发送任务
7、生成代码
二、API
1、创建一个二值量、并返回一个ID:osSemaphoreCreate
osSemaphoreDef(BinarySem01);
BinarySem01Handle = osSemaphoreCreate(osSemaphore(BinarySem01), 1);
2、删除一个信号量:osSemaphoreDelete
包括二值信号量,计数信号量,互斥量和递归互斥量。如果有任务阻塞在该信号量上,那么不要删除信号量
osSemaphoreDelete(BinarySem01Handle);
3、释放信号量的宏:osSemaphoreRelease
释放的对象必须是已经创建的,可以用于二值信号量、计数信号量、互斥量的释放,但不能释放由函数xSemaphoreCreateRecursiveMutex() 创建的互斥量。
osSemaphoreRelease(BinarySem01Handle);
4、获取信号量:osSemaphoreWait
用于获取信号量,不带中断保护。获取的信号量对象可以是二值信号量、计数信号量和互斥量,但是递归互斥量并不能使用这个API函数获取。
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
三、阻塞式二值信号量
void ReceiveTask(void const * argument)
{
osStatus xReturn = osErrorValue;
for(;;)
{
xReturn = osSemaphoreWait(BinarySemHandle, /* 二值信号量句柄 */
osWaitForever); /* 等待时间 */
if(osOK == xReturn)
{
printf("BinarySem get!\n\n");
}
}
}
void SendTask(void const * argument)
{
osStatus xReturn;
for(;;)
{
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_SET)
{
xReturn = osSemaphoreRelease(BinarySemHandle);//给出二值信号量
if(osOK == xReturn)
{
printf("release!\r\n");
}
else
{
printf("BinarySem release fail!\r\n");
}
}
osDelay(100);
}
}
四、计数信号量
当公共资源没有用完时,任务量的个数还可以添加,当公共资源用完时,第一个任务移除公共资源,新加入的进去。
eg按下key1申请车位,按下key2释放车位
osSemaphoreDef(BinarySem01);
BinarySem01Handle = osSemaphoreCreate(osSemaphore(BinarySem01), 1);
osSemaphoreDef(CountingSem02);
CountingSem02Handle = osSemaphoreCreate(osSemaphore(CountingSem02), 5);
void Send_thread_entry(void const * argument)
{
osStatus xReturn;
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == GPIO_PIN_SET)
{
xReturn = osSemaphoreRelease(CountingSem02Handle);// 给出计数信号量
if(osOK == xReturn)
{
printf( "Key2 is pressed to release 1 parking space.\n" );
}
else
{
printf( "Key2 is pressed, but there is no parking space to release!\n" );
}
}
osDelay(500);
}
}
void Receive_thread_entry(void const * argument)
{
osStatus xReturn = osErrorValue;
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
{
xReturn = osSemaphoreWait(CountingSem02Handle,0); /* 计数信号量句柄 *//* 等待时间:0 */
if(osOK == xReturn)
{
printf( "Key1 is pressed and successfully applied for parking space.\n" );
}
else
{
printf( "Key1 is pressed. Sorry, the parking lot is full now!\n" );
}
osDelay(500);
}
}
}