收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
| ulTaskNotifyTake | uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) | pdTRUE时在函数退出时将通知值清零,这种方法适用于实现二值信号量; pdFALSE时在函数退出时将通知值减 1,这种方法适用于实现计数信号量。 接收 |
| xTaskNotifyWait | BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) | 用于实现全功能版的等待任务通知,根据用户指定的参数的不同,可以灵活的用于实现轻量级的消息队列队列、二值信号量、计数信号量和事件组功能,并带有超时等待 接收 |
2、CMSIS封装后任务通知函数
在CubeMX中使用任务通知,就使用了两个函数osSignalSet
发送和osSignalWait
接收。
2.1 osSignalSet
根据是否在中断中使用,osSignalSet
调用了xTaskGenericNotify
或者xTaskGenericNotifyFromISR
:
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Signal Management \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*\*
\* @brief Set the specified Signal Flags of an active thread.
\* @param thread\_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
\* @param signals specifies the signal flags of the thread that should be set.
\* @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
\* @note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
\*/
int32_t osSignalSet (osThreadId thread_id, int32_t signal)
{
#if( configUSE\_TASK\_NOTIFICATIONS == 1 )
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint32_t ulPreviousNotificationValue = 0;
if (inHandlerMode())
{
if(xTaskGenericNotifyFromISR( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue, &xHigherPriorityTaskWoken ) != pdPASS )
return 0x80000000;
portYIELD\_FROM\_ISR( xHigherPriorityTaskWoken );
}
else if(xTaskGenericNotify( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue) != pdPASS )
return 0x80000000;
return ulPreviousNotificationValue;
#else
(void) thread_id;
(void) signal;
return 0x80000000; /\* Task Notification not supported \*/
#endif
}
2.2 osSignalWait
任务通知只能在任务中使用,不允许在中断中使用,osSignalWait
调用xTaskNotifyWait
实现:
/\*\*
\* @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
\* @param signals wait until all specified signal flags set or 0 for any single signal flag.
\* @param millisec timeout value or 0 in case of no time-out.
\* @retval event flag information or error code.
\* @note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
\*/
osEvent osSignalWait (int32_t signals, uint32_t millisec)
{
osEvent ret;
#if( configUSE\_TASK\_NOTIFICATIONS == 1 )
TickType_t ticks;
ret.value.signals = 0;
ticks = 0;
if (millisec == osWaitForever) {
ticks = portMAX_DELAY;
}
else if (millisec != 0) {
ticks = millisec / portTICK_PERIOD_MS;
if (ticks == 0) {
ticks = 1;
}
}
if (inHandlerMode())
{
ret.status = osErrorISR; /\*Not allowed in ISR\*/
}
else
{
if(xTaskNotifyWait( 0,(uint32_t) signals, (uint32_t \*)&ret.value.signals, ticks) != pdTRUE)
{
if(ticks == 0) ret.status = osOK;
else ret.status = osEventTimeout;
}
else if(ret.value.signals < 0)
{
ret.status = osErrorValue;
}
else ret.status = osEventSignal;
}
#else
(void) signals;
(void) millisec;
ret.status = osErrorOS; /\* Task Notification not supported \*/
#endif
return ret;
}
二、任务通知使用
在CubeMX中,任务通知是默认使能的:
1、定义通知量
在程序中定义几个通知量,我们知道任务通知是32位的,所以可以任意定义,我们测试使用了2个通知:
/\* USER CODE BEGIN EFP \*/
#define test\_signal1 1
#define test\_signal2 0xFFFFFFFE
2、任务中发送通知
在按键任务中,发送一个任务通知给温湿度读取任务,使用osSignalSet
:
if(HAL\_GPIO\_ReadPin(K3_GPIO_Port,K3_Pin) == 0){
osDelay(10);
if(HAL\_GPIO\_ReadPin(K3_GPIO_Port,K3_Pin) == 0){
taskENTER\_CRITICAL();
printf("K3 pushed!!,send a tasksignal to thread...\r\n");
taskEXIT\_CRITICAL();
osSignalSet(THreadHandle,test_signal2);
while(HAL\_GPIO\_ReadPin(K3_GPIO_Port,K3_Pin) == 0){
osDelay(10);
}
}
}
3、接收通知
通过上文我们可以知道osSignalWait
返回的类型是osEvent
,所以需要定义过一个osEvent
类型的变量,然后结构体变量中有一个成员v
是保存的接收的通知的值,如下:
我们看一下osEvent
结构体 :
/// Event structure contains detailed information about an event.
/// \note MUST REMAIN UNCHANGED: \b os\_event shall be consistent in every CMSIS-RTOS.
/// However the struct may be extended at the end.
typedef struct {
osStatus status; ///< status code: event or error information
union {
uint32_t v; ///< message as 32-bit value
void \*p; ///< message or mail as void pointer
int32_t signals; ///< signal flags
} value; ///< event value
union {
osMailQId mail_id; ///< mail id obtained by \ref osMailCreate
osMessageQId message_id; ///< message id obtained by \ref osMessageCreate
} def; ///< event definition
} osEvent;
所以最终 温湿度读取任务函数改为:
/\* USER CODE END Header\_StartTHread \*/
void StartTHread(void const \* argument)
{
/\* USER CODE BEGIN StartTHread \*/
float T=0,H=0;
osEvent th_readevent;
/\*128会溢出字的内存空间不够SHT21 协议读取\*/
/\* Infinite loop \*/
for(;;)
{
th_readevent = osSignalWait(test_signal2,osWaitForever);
if(th_readevent.value.v == test_signal2){
SHT2X\_THMeasure();
T=(getTemperature()/100.0);
H=(getHumidity()/100.0);
taskENTER\_CRITICAL();
printf("0x%x",th_readevent.value.v);
printf("\r\n%4.2f C\r\n%4.2f%%\r\n",T,H);
taskEXIT\_CRITICAL();
}
osDelay(1);
}
/\* USER CODE END StartTHread \*/
}
结果如下,按照预期的结果执行:
4、中断中发送通知
我们在上次开启的定时器中断中,增加任务通知发送任务:
#include "cmsis\_os.h"
...
![img](https://img-blog.csdnimg.cn/img_convert/c1471a95d125c439a6c2a4b3b9e18f41.png)
![img](https://img-blog.csdnimg.cn/img_convert/2caf65ace382ec3b8c264dea4cf3f8cd.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**