当前位置: 首页 > news >正文

STM32FreeRTOS任务通知(STM32cube高效开发)

文章目录

  • 一、任务通知
    • (一)任务通知概述
      • 1、任务通知可模拟队列和信号量
      • 2、任务通知优势和局限性
    • (二) 任务通知函数
      • 1、xTaskNotify()发送通知值不返回先前通知值的函数
      • 2、xTaskNotifyFromISR()发送通知函数ISR版本
      • 3、xTaskNotifyAndQuery()发送通知值且返回先前通知值的函数
      • 4、xTaskNotifyGive()函数-发送通知值使通知值+1的函数
      • 5、xTaskNotifyWait()函数-等待任务通知和接收通知值
      • 6、ulTaskNotifyTake()函数--二值信号量或计数信号量获取任务通知
      • 7、xTaskNotifyStateClear()函数-清除任务通知值
  • 二、任务通知传递数据
    • (一)任务通知值模拟二值信号量
      • 1、目标
      • 2、STM32cubemx配置
      • 3、代码编写
    • (二)任务通知值模拟计数型信号量
      • 1、目标
      • 2、STM32cubemx设置
      • 3、代码编写

一、任务通知

(一)任务通知概述

1、任务通知可模拟队列和信号量

任务通知是FreeRTOS另外一种进程间通信技术。不需要创建任何中间对象,可以直接从任务向任务或ISR向任务发送通知,传递一个通知值任务通知可以模拟二值信号量、计数信号量、或长度为1的消息队列,使用任务通知,一般效率更高,消耗内存更少

在这里插入图片描述

在这里插入图片描述
任务通知和队列信号量事件组区别如下

  • 队列信号量事件组:

    使用队列、信号量、事件标志组时都需另外创建一个结构体,通过中间的结构体进行间接通信!

  • 任务通知:

    使用任务通知时,任务结构体TCB中就包含了内部对象,可以直接接收别人发过来的"通知"

2、任务通知优势和局限性

(1)任务通知值优势

在这里插入图片描述

  • 效率更高: 使用任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快得多
  • 使用内存更少: 使用其他方法时都要先创建对应的结构体,使用任务通知时无需额外创建结构体

(2)任务通知值局限

在这里插入图片描述

  • 无法发送数据给ISR: ISR没有任务结构体,所以无法给ISR发送数据。但是ISR可以使用任务通知的功能,发数据给任务。
  • 无法广播给多个任务: 任务通知只能是被指定的一个任务接收并处理
  • 无法缓存多个数据; 任务通知是通过更新任务通知值来发送数据的,任务结构体中只有一个任务通知值,只能保持一个数据。
  • 发送受阻不支持阻塞: 发送方无法进入阻塞状态等待

(二) 任务通知函数

在这里插入图片描述

1、xTaskNotify()发送通知值不返回先前通知值的函数

向一个任务发送通知的函数
参数1:任务通知句柄
参数2:要发送的通知值(此参数的使用取决于参数3)
参数3:通知值得作用方式(可以传入五种不同得枚举值)

在这里插入图片描述

/*
参数1:接收者任务句柄
参数2:要发送的通知值(此参数的使用取决于参数3)
参数3:通知值作用方式(可以传入五种不同得枚举值eNotifyAction)
参数4:为NULL表明不会返回通知前的数值
通知值和枚举值共同决定了如何修改接收者通知值
返回值是更新后的通知值
*/
#define xTaskNotify( xTaskToNotify, ulValue, eAction ) 
xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL )

xTaskNotify()在调用函数xTaskGenericNotify()时没有传递最后一个参数,所以不能返回接收者更新之前的通知值。函数xTaskNotify()返回的是更新之后的接收者的通知值。

参数3的枚举值如下所示:
在这里插入图片描述

typedef enum
{eNoAction = 0, /* 无操作:只发通知,不改变接收者的通知值 */eSetBits, /* 更新指定bit: 接收者的通知值与ulValue按位或运算,适用于当做事件组使用 */eIncrement, /* t将接收者的通知值加1,适用于当做二值信号量或计数信号量使用 */eSetValueWithOverwrite,/* 覆写通知值:用ulValue覆盖接收者的通知值,即使前一次的通知未被处理 */eSetValueWithoutOverwrite /* 不覆写通知值:接收者处于非挂起状态时,用ulValue更新其通知值,否则不更新*/
} eNotifyAction;

参数3枚举值:
(1)传入eSetBits时(适用于任务通知做事件组时使用)
在这里插入图片描述
接收者的通知值与u1value进行按位或运算

(2)传入eIncrement(适用于当作计数型信号量或二值信号量场景)
在这里插入图片描述
接收者的通知值+1运算

(3)覆写
在这里插入图片描述
用u1value覆盖接收者的通知值(即使前一次的通知未被处理)
(4)不覆写更新通知值
在这里插入图片描述
接收者处于非挂起状态时,用u1value更新其通知值,否则不更新

宏函数实际调用执行的函数:

/*
参数1:任务通知句柄
参数2:要发送的通知值(此参数的使用取决于参数3)
参数3:通知值得作用方式(可以传入五种不同得枚举值eNotifyAction)
参数4:返回接收者的通知值被改变之前的值(NULL表明不会返回通知前的数值)
*/#if( configUSE_TASK_NOTIFICATIONS == 1 )BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue,eNotifyAction eAction,uint32_t *pulPreviousNotificationValue ){}#endif /* configUSE_TASK_NOTIFICATIONS */

在这里插入图片描述

2、xTaskNotifyFromISR()发送通知函数ISR版本

ISR版本比任务中的发送函数多一个参数(最后一个参数是指是否需要进行上下文切换)

#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction,pxHigherPriorityTaskWoken ) 
xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( HigherPriorityTaskWoken ) )

pxHigherPriorityTaskWoken是一个*BaseType_t 类型的指针,实际上是一个返回数据,表示退出中断ISR函数之后是否需要进行上下文切换

申请进行上下文切换调用函数portYIELD_FROM_ISR()

3、xTaskNotifyAndQuery()发送通知值且返回先前通知值的函数

函数xTaskNotifyAndQuery()与xTaskNotify()的功能相同,但是能返回接收者通知值改变之前的值。(还有一个ISR版本)
在这里插入图片描述
参数pulPreviousNotifyValue用于获取接收者之前的通知值,是uint32_t *类型的指针变量

示意代码如下:

uint32_t previousValue=0;
uint32_t currentValue=0;
currentValue =xTaskNotifyAndQuery(xTaskToNotify, ulValue, eAction, &previousValue);

4、xTaskNotifyGive()函数-发送通知值使通知值+1的函数

函数 xTaskNotifyGive() 是xTaskNotify()的一种功能简化版本(并有一个ISR版本)
参数eAction设置为eIncrement,所以,函数xTaskNotifyGive()的功能就是使接收者的通知值加1,这使其适用于 将任务通知当做二值信号量或计数信号量使用的场合。
在这里插入图片描述

注意:
发送通知API函数可以用于任务和中断服务函数中;接收通知API函数只能用在任务中。
在这里插入图片描述

5、xTaskNotifyWait()函数-等待任务通知和接收通知值

接收者使用函数xTaskNotifyWait()进入阻塞状态等待任务通知并获取通知值

BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit,uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;参数1:函数进入时需要清零的通知值的位掩码。(需要清零的位在掩码中用1表示,否则用0表示)计算方式是当前值按位取反后再与通知值按位与运算,用计算的结果用来更新通知值,如果设置为0表示不更新通知值,如果设置为0xffffffff表示将所有位清零
参数2:函数在退出时需要清零的通知值的位的掩码。(0就是不更改通知值,0xFFFFFFFF就是将通知值设置为0)参数3:是一个uint32_t *类型的指针,用于返回接收到的通知值。
参数4:超时阻塞时间(函数在阻塞状态等待的节拍数)
返回值:是pdTRUE或pdFALSE,pdTRUE表示接收到了任务通知,包括函数一进入就读取已挂起的任务通知

如果是未挂起的任务,也就是没有任务通知任务进入阻塞状态等待任务通知。
如果任务是挂起状态,有未处理的任务通知就立刻读取通知值然后返回。
任务接收到通知或者超时则会退出阻塞状态

6、ulTaskNotifyTake()函数–二值信号量或计数信号量获取任务通知

获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减一。
当任务通知用作二值信号量或者计数信号量的时候,使用此函数来获取信号量。

在这里插入图片描述

uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;参数1:pdTRUE或pdFALSE
(1)取值为pdTRUE时,函数接收到通知并退出时将通知值清零,这种情况下是将通知值当做二值信号量使用
(2)取值为pdFALSE时,函数接收到通知并退出时将通知值减1,这种情况下是将通知值当做计数信号量使用
参数2:超时等待时间(进入阻塞状态等待任务通知的节拍数)
返回值:减1或清零之前的通知值

函数ulTaskNotifyTake()一般与函数xTaskNotifyGive()搭配使用,将任务通知值当做二值信号量或计数信号量使用。

在这里插入图片描述

在这里插入图片描述

注意:
当任务通知用作于信号量时,使用函数获取信号量:ulTaskNotifyTake()
当任务通知用作于事件标志组或队列时,使用此函数来获取: xTaskNotifyWait()

在这里插入图片描述

7、xTaskNotifyStateClear()函数-清除任务通知值

清除接收者的任务通知等待状态使其变为未挂起状态,不会将接收者的通知值清零(参数是需要操作的任务句柄,设置为NULL表示当前的任务)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、任务通知传递数据

(一)任务通知值模拟二值信号量

1、目标

使用中断方式进行ADC转换,通过任务通知将ADC转换结果作为通知值发送给另外一个任务
(1)ADC1在定时器TIM3的触发下进行周期为500ms的ADC数据采集,在ADC的ISR函数里通过函数xTaskNotifyFromISR()将转换结果发送给任务Task_Show
(2)任务Task_Show总是使用函数xTaskNotifyWait()等待任务通知,读取出通知值后在LCD上显示数据

2、STM32cubemx配置

(1)复制只有LCD的cube文件并重命名

在这里插入图片描述

(2)RCC

在这里插入图片描述

(3)SYS选择TIM6作为FreeRTOS的基础时钟源
在这里插入图片描述
(4)定时器3选择内部时钟
在这里插入图片描述
TIM3挂载到APB1总线,84MHZ,如果将其划分为1khz的话,分频系数就需要设为84k
在这里插入图片描述
但是分频器最大65535,达不到8万4, 就设为8400-1获得一个10000h频率即定时0.1ms,由于希望获得到周期是500ms的延时,所以计数周期可以设置为5000-1,并且选择更新事件。
在这里插入图片描述
(5)ADC设置
选择通道5,选择定时器3触发事件,采样选择15
在这里插入图片描述
使能ADC的NVIC
在这里插入图片描述
(6)启动Freertos选择V2版本,并且对默认任务进行修改将栈空间设为256字
在这里插入图片描述
(7)设置NVIC
要在ADC的ISR中调用freertos的函数,所以ADC中断优先级不能比5高
在这里插入图片描述

生成代码

3、代码编写

(1)LCD部分
移植BSP文件夹到工程目录中并且添加相关路径到头文件中,并调用相关的头文件实现lcd的初始化和数据显示测试。 可以实现LCD的数据显示以后进行下一步
(2)main.c文件主函数
LCD初始化、LCD测试、启动定时器和ADC
在这里插入图片描述

 /* USER CODE BEGIN 2 */TFTLCD_Init();LCD_ShowString(10, 10+0*20, tftlcd_data.width, tftlcd_data.height, 12, "tasknotify test bin");//以中断方式启动adc1HAL_ADC_Start_IT(&hadc1);//启动定时器3HAL_TIM_Base_Start(&htim3);/* USER CODE END 2 */

main.h添加头文件(从main.c调用头文件处复制即可)
在这里插入图片描述

(3)Freertos代码编写

ADC1在定时器TIM3的触发下进行周期为500ms的ADC数据采集,在ADC的ISR函数里通过函数xTaskNotifyFromISR()将转换结果发送给任务Task_Show

/* USER CODE BEGIN Application */void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{//由于定时器3每500ms更新一次事件,adc在500ms触发下周期性的进行adc转换,转换完就会触发这个回调函数//	//先查询是不是adc1的通道5if(hadc->Instance==ADC1)//adc1{uint32_t adc_value=HAL_ADC_GetValue(&hadc1);//获取ADC的数值,并赋值给局部变量//以任务通知的形式将数据发送给任务,且以覆写的形式进行//首先保证任务句柄存在才写入数据if(Task_showHandle!=NULL){BaseType_t pxHigherPriorityTaskWoken=pdFALSE;//默认不进行任务调度//使用ISTR写入数据函数//参数1接收数据的任务句柄,参数2:传输数值//参数3:覆写,参数4:是否进行上下文切换xTaskNotifyFromISR(Task_showHandle,adc_value,eSetValueWithOverwrite,&pxHigherPriorityTaskWoken);//防止优先级反转需要传入数值来判断推出前是否需要进行一次任务调度申请portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);}}
}/* USER CODE END Application */

任务Task_Show总是使用函数xTaskNotifyWait()等待任务通知,读取出通知值后在LCD上显示数据

/* USER CODE END Header_AppTask_show */
void AppTask_show(void *argument)
{/* USER CODE BEGIN AppTask_show */uint32_t pulNotificationValue=0;//接收的值/* Infinite loop */for(;;){//参数1:函数进入时不更新通知值(0),0xffffffff表示将所有位清零//参数2:函数退出时清零所有位(0xffffffff),0就是不更改通知值//参数3:返回的通知值,参数4:超时等待时间BaseType_t result=xTaskNotifyWait(0, 0xffffffff, &pulNotificationValue, portMAX_DELAY);if(result==pdPASS)//表示接收到了通知{uint32_t adc_value=pulNotificationValue;uint8_t data[20];sprintf(data,"adc_value=%d    ",adc_value);LCD_ShowString(10,10+2*20,tftlcd_data.width,tftlcd_data.height,12,data);sprintf(data,"volatge=%d  mv  ",adc_value*3300>>12);//>>12就是除以4096LCD_ShowString(10,10+3*20,tftlcd_data.width,tftlcd_data.height,12,data);}//没有加入vtaskdelay表明一直在等待通知值的到来}/* USER CODE END AppTask_show */
}

(二)任务通知值模拟计数型信号量

使用函数xTaskNotifyGive()发送通知,使接收者的通知值加1,使用函数ulTaskNotifyTake()读取通知,使通知值减1或清零
在这里插入图片描述
在这里插入图片描述

1、目标

使用任务通知模拟计数信号量,表示如图所示的餐厅前排队的人数变化。
在这里插入图片描述

(1)在FreeRTOS中创建一个任务Task_CheckIn,其通知值表示当前在排队的人数。
(2)在任务Task_CheckIn中连续检测key1键,当Key1键按下时执行函数ulTaskNotifyTake()使通知值减1,表示允许1人进店,使排队人数减1。
(3) 设置RTC周期唤醒周期为2秒,在周期唤醒中断里执行函数vTaskNotifyGiveFromISR()向任务Task_CheckIn发送通知,使其通知值加1,表示又来1人加入排队的队伍。

2、STM32cubemx设置

(1)复制按键和LCD的cebemx文件并重命名
在这里插入图片描述
(2)RCC设置
由于要使用RTC,开启外部低速时钟
在这里插入图片描述
(3)SYS设置Freertos基础时钟源
在这里插入图片描述
(4)启用RTC
激活RTC、周期唤醒、二进制数据、2s唤醒一次
在这里插入图片描述
使能RTC中断
在这里插入图片描述
(5)启用Freertos并修改默认任务
栈空间设置为256字
在这里插入图片描述

(6)在原来基础之上设置RTC时钟源
在这里插入图片描述

3、代码编写

(1)移植BSP文件夹到工程目录中,并且添加头文件路径到工程中以及添加lcd头文件调用,实现LCD的初始化和显示测试
(2)main.c
lcd初始化和lcd显示测试
在这里插入图片描述
main.h调用头文件
在这里插入图片描述

(3)freeRTOS代码编写

任务函数

void AppTask_CheckIn(void *argument)
{/* USER CODE BEGIN AppTask_CheckIn *//* Infinite loop */for(;;){KEYS value=key_scan(20);if(value==KEY_1)//如果是按�?1按下{//参数1:pdfalse表示计数信号量,pdfalse表示通知值不清零,进行-1操作//参数2:一直等待//返回值是上一次的通知值uint32_t precount=ulTaskNotifyTake( pdFALSE, portMAX_DELAY );uint8_t str[20];sprintf(str,"people in waiting= %d     ",precount-1);LCD_ShowString(10, 10+2*20, tftlcd_data.width, tftlcd_data.height, 12, str);vTaskDelay(300);//消抖延时}elsevTaskDelay(5);}/* USER CODE END AppTask_CheckIn */
}

RTC唤醒中断函数

void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{LED1_TOGGLE();//2s进入回调函数一次BaseType_t pxHigherPriorityTaskWoken=pdFALSE;//不进行上下文切换//参数1:写入的任务句柄,参数2:是否进行上下文切换vTaskNotifyGiveFromISR(Task_CheckInHandle, &pxHigherPriorityTaskWoken);portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
}

(1)LED1闪烁,表示RTC的中断ISR函数在执行,每2秒钟发送一次任务通知
(2)按下Key1键时, LCD上显示当前排队人数,连续按Key1键时会使排队人数减少,直到减少为0,任务Task_CheckIn就会进入阻塞等待状态。
(3)除了函数ulTaskNotifyTake()和xTaskNotifyWait()之外,没有其他函数能读取任务的当前通知值, 所以程序不能实时显示排队人数,只有在按下Key1键执行一次ulTaskNotifyTake()函数后才会显示当前排队人数

相关文章:

STM32FreeRTOS任务通知(STM32cube高效开发)

文章目录 一、任务通知(一)任务通知概述1、任务通知可模拟队列和信号量2、任务通知优势和局限性 (二) 任务通知函数1、xTaskNotify()发送通知值不返回先前通知值的函数2、xTaskNotifyFromISR()发送通知函数ISR版本3、x…...

基于element-plus的Dialog选择控件

翻看之前工程师写的vue2的代码,很多都是复制、粘贴,也真是搞不懂,明明可以写一个控件,不就可以重复使用。很多前端总喜欢element搞一下,ant-design也搞一下,有啥意义,控件也不是自己写的&#x…...

手把手教使用静默 搭建Oracle 19c 一主一备ADG集群

一、环境搭建 主机IPora19192.168.134.239ora19std192.168.134.240 1.配置yum源 1.配置网络yum源 1.删除redhat7.0系统自带的yum软件包; rpm -qa|grep yum >oldyum.pkg 备份原信息rpm -qa|grep yum|xargs rpm -e --nodeps 不检查依赖,直接删除…...

使用协程库httpx并发请求

httpx和aiohttp都是比较常用的异步请求库,当然requests多线程或requestsgevent也是不错的选择。 一个使用httpx进行并发请求的脚本如下: import functools import sys import timeimport anyio import httpxasync def fetch(client, results, index) -…...

js的同步异步

JavaScript(JS)是一门单线程的编程语言,这意味着它一次只能处理一个任务。然而,JS 支持同步和异步操作。 同步操作是指代码按照顺序执行,每个操作必须在前一个操作完成后才能进行。这意味着当一个操作在执行时&#x…...

C# MG.CamCtrl 工业相机库(开源) 海康 大恒

C# MG.CamCtrl 相机库(开源) 海康 大恒 介绍工厂模式创建实例选取对应SN号的相机,初始化启动相机取图注销相机参数设置/获取接口 介绍 c# 相机库,含海康、大恒品牌2D相机的常用功能。 底层采用回调信号量模式封装 ,最…...

【Redis】redis的基本使用

📝个人主页:五敷有你 🔥系列专栏:Redis ⛺️稳中求进,晒太阳 Redis的概述 为什么要有redis? redis是数据库,mysql也是数据库,redis做缓存的意义就是为了减轻数据库压力 数据库为什么…...

植物病害识别:YOLO水稻病害识别数据集(3000多张,3个类别,yolo标注)

YOLO水稻病害识别数据集,包含细菌性枯萎病,水稻瘟疫,褐斑病3个常见病害类别,共3000多张图像,yolo标注完整,可直接训练。 适用于CV项目,毕设,科研,实验等 需要此数据集或…...

Java实现Tron(波场)区块链的开发实践(三)波场链水龙头、WEB3测试实战

上一节我们具体讲到Java实现Tron波场链的逻辑代码实现。 这一节我们通过部署和开发好的代码,针对测试链进行自测开发,准备测试环境。 1. 创建离线地址 首先我们需要一个离线地址,我们不需要在线进行创建,直接可以通过第一节的离…...

010-$nextTick

$nextTick 1、问题2、$nextTick3、应用场景 1、问题 Vue 实现响应式,在 data 更新后,一定时间内,没有继续操作DOM,然后会触发浏览器渲染引擎去更新DOM,更新DOM也是需要时间的,所以 data 更新引起的 DOM更新…...

[IAGC] Kafka消费者组的负载均衡策略

在Apache Kafka中,负载均衡是通过将主题的每个分区分配给消费者组中的一个消费者来实现的。Kafka的负载均衡算法会尽可能平均地将分区分配给每个消费者。 文章目录 分配策略Kafka的重新平衡扩展性参考资源 分配策略 在Kafka中,有两种内置的分区分配策略…...

2024年会声会影 迎接来了七大新功能

我喜欢Corel VideoStudio 会声会影2024旗舰版,因为它使用起来很有趣。它很容易使用,但仍然给你很多功能和力量。VideoStudio让我与世界分享我的想法!“这个产品的功能非常多,我几乎没有触及它的表面,我可以做大量的编辑…...

AIGC、3D模型、轻量化、格式转换、可视化、数字孪生引擎等(老子云三维模型可视化优化服务平台)

老子云概述 老子云3D可视化快速开发平台,集云压缩、云烘焙、云存储云展示于一体,使3D模型资源自动输出至移动端PC端、Web端,能在多设备、全平台进行展示和交互,是全球领先、自主可控的自动化3D云引擎。 平台架构 平台特性 基于 H…...

JMM(Java Memory Model)内存模型

Java内存模型,规范了计算机内存与java虚拟机之间的协调工作,即规定了 将java 虚拟机中的变量存储到内存中和从内从中取出来的内存细节。 Java内存模型中规定了所有的变量都存储在内存中,每条线程还有自己的工作内存,线程对变量的…...

.NET 简介:跨平台、开源、高性能的开发平台

.NET 简介 .NET 是微软开发的一个免费、开源、跨平台的开发人员平台,用于构建各种类型的应用程序。它可以运行使用多种语言编写的程序,其中 C# 是最常用的语言。.NET 依赖于许多大规模应用在生产中使用的高性能运行时。 .NET 平台具有以下特点&#xf…...

m序列生成器

function [m] mserial_generator(tap_set) % m序列产生器 % 输出为m序列,未进行极性变换。 L 2^(length(tap_set)-1)-1; x [zeros(1,(length(tap_set)-2)) 1]; for i 1:1:Lm(i)x(end);for j 1:1:length(tap_set)-1sum_vector(j)tap_set(j1)*x(j);endsum_x mod…...

go的数据类型看这一篇就够了

目录 一:类型分类 二:介绍 一:类型分类 go的数据类型包含11种,可以分为以下四类。 1:基础类型:布尔,数字和字符串: 2:复合类型:数组和结构体 3:引用类型: 指针,channel通道,切片,map字典,函数 4:接口类型 二:介绍 1:布尔 一个布尔类型的值只有两种:tr…...

【机器学习300问】28、什么是决策树?

〇、两个预测任务 (1)任务一:银行预测偿还能力 当前,某银行正致力于发掘潜在的放贷用户。他们掌握了每位用户的三个关键特征:房产状况、婚姻状况以及年收入。此外,银行还拥有过往这些用户的债务偿还能力的…...

嵌入式学习33-网络通信

网络: 数据传输,数据共享 1.网络协议模型: OSI协议模型 7 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式&…...

FFmepg--内存IO模式

功能: 内存IO模式:avio_alloc_context(): 自定义读写文件方式,打开文件 api // 自定义IO AVIOContext * avio_alloc_context (unsigend char * buffer;int buffer_size;void *opaque;int (*read_packet)(void * opaque, uint8_t * buf,in…...

centos 7 部署awstats 网站访问检测

一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

Python常用模块:time、os、shutil与flask初探

一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...