定时器的小应用

第一个项目

第一步,RCC开启时钟,这个基本上每个代码都是第一步,不用多想,在这里打开时钟后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

第二步,选择时基单元的时钟源,对于定时中断,我们就选择内部时钟源

TIM_InternalClockConfig(TIM2);//很多人不写这个函数,因为定时器上电后默认就是内部时钟

第三步,配置时基单元,包括预分频器、自动重装器、计数模式等等,这些参数用一个struct就可以配置好

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //ARR自动重装器的值【0-65535】
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //PSC预分频器的值【0-65535】,两者取值都不是唯一的
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值(高级定时器c)
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
上面并没有CNT计数器的参数,如果我们需要的话,可以用之前说的SetCounter和GetCounter这两个函数来操作计数器

如果我们想定时1秒(也就是定时频率为1Hz),用下面这个公式来算

计数器溢出频率: C K _ C N T _ O V = C K _ C N T / ( A R R + 1 ) = C K _ P S C / ( P S C + 1 ) / ( A R R + 1 ) CK\_CNT\_OV = CK\_CNT / (ARR + 1) = CK\_PSC / (PSC + 1) / (ARR + 1) CK_CNT_OV=CK_CNT/(ARR+1)=CK_PSC/(PSC+1)/(ARR+1)

TIM_TimeBaseInitStructure

typedef struct
{uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.This parameter can be a number between 0x0000 and 0xFFFF */uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.This parameter can be a value of @ref TIM_Counter_Mode */uint16_t TIM_Period;            /*!< Specifies the period value to be loaded into the activeAuto-Reload Register at the next update event.This parameter must be a number between 0x0000 and 0xFFFF.  */ uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.//指定时钟分频This parameter can be a value of @ref TIM_Clock_Division_CKD */ //TIM_Clock_Division_CKD是用来干啥的呢?滤波器可以滤掉信号的抖动干扰,怎么工作的呢?就是在一个固定时钟频率f下进行采样,如果连续N个采样点都为相同的电平,那就代表输入信号稳定了,就把采样值输出出去,如果这N个采样值不全都相同,那就说明信号有抖动,这时就保持上一次的输出,或者直接输出低电平也行,这样就可以保证输出信号在一定程度上的滤波了,这里的采样频率f(可以内部时钟直接而来,也可以由内部时钟加一个时钟分频而来,分频多少就是由TIM_Clock_Division_CKD决定,这个参数和时基单元关系并不大,我们随便配一个就行)和采样点N都是滤波器的参数,频率越低,采样点数越多,那滤波效果就越好,不过相应的信号延迟就大uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounterreaches zero, an update event is generated and counting restartsfrom the RCR value (N).This means in PWM mode that (N+1) corresponds to:- the number of PWM periods in edge-aligned mode- the number of half PWM period in center-aligned modeThis parameter must be a number between 0x00 and 0xFF. @note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;      

TIM_Clock_Division_CKD

/** @defgroup TIM_Clock_Division_CKD * @{*/#define TIM_CKD_DIV1                       ((uint16_t)0x0000) //不分频
#define TIM_CKD_DIV2                       ((uint16_t)0x0100) //二分频
#define TIM_CKD_DIV4                       ((uint16_t)0x0200) //四分频
#define IS_TIM_CKD_DIV(DIV) (((DIV) == TIM_CKD_DIV1) || \((DIV) == TIM_CKD_DIV2) || \((DIV) == TIM_CKD_DIV4))
/*** @}*/

TIM_Counter_Mode

/** @defgroup TIM_Counter_Mode * @{*/#define TIM_CounterMode_Up                 ((uint16_t)0x0000) //向上计数
#define TIM_CounterMode_Down               ((uint16_t)0x0010) //向下计数
#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020) //三种中央对齐模式
#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)
#define IS_TIM_COUNTER_MODE(MODE) (((MODE) == TIM_CounterMode_Up) ||  \((MODE) == TIM_CounterMode_Down) || \((MODE) == TIM_CounterMode_CenterAligned1) || \((MODE) == TIM_CounterMode_CenterAligned2) || \((MODE) == TIM_CounterMode_CenterAligned3))
/*** @}*/ 

第四步,配置输出中断控制,允许更新中断输出到NVIC

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//开启了更新中断到NVIC的通路

/*** @brief  Enables or disables the specified TIM interrupts.* @param  TIMx: where x can be 1 to 17 to select the TIMx peripheral.* @param  TIM_IT: specifies the TIM interrupts sources to be enabled or disabled.*   This parameter can be any combination of the following values:*     @arg TIM_IT_Update: TIM update Interrupt source \\ 更新中断*     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source*     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source*     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source*     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source*     @arg TIM_IT_COM: TIM Commutation Interrupt source*     @arg TIM_IT_Trigger: TIM Trigger Interrupt source*     @arg TIM_IT_Break: TIM Break Interrupt source* @note *   - TIM6 and TIM7 can only generate an update interrupt.*   - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,*      TIM_IT_CC2 or TIM_IT_Trigger. *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.   *   - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. *   - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.    * @param  NewState: new state of the TIM interrupts.*   This parameter can be: ENABLE or DISABLE.* @retval None*/
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
{  /* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_IT(TIM_IT));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Enable the Interrupt sources */TIMx->DIER |= TIM_IT;}else{/* Disable the Interrupt sources */TIMx->DIER &= (uint16_t)~TIM_IT;}
}

第五步,配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级(和中断那一节流程一样)

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);

第六步,运行控制

TIM_Cmd(TIM2, ENABLE);

整个模块配置完成后,我们还需要使能一下计数器(要不然计数器不会运行),当定时器使能后,计数器就会开始计数了,当数器更新时,触发中断

最后我们再写一个定时器的中断函数

void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

这样这个中断函数每隔一段时间就能自动执行一次了

定时器的库函数

void TIM_DeInit(TIM_TypeDef* TIMx);void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); //时基单元初始化,它就是用来配置这个图里这里的时基单元的
//第一个TIMx选择某个定时器,第二个是结构体,里面包含了配置时基单元的一些参数void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);//结构体变量赋一个默认值,void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);//这个是用来使能计数器的,对应的就是图里面的运行控制,第二个NewState新的状态,也就是使能还是失能void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);//这个是用来使能外设的中断输出信号的,对应的就是图里面的中断输出控制,第二个TIM_IT,选择要配置哪个中断输出,第三个,使能与否下面6个函数对应的就是时基单元的时钟选择部分,可以选择RCC内部时钟、ETR外部时钟、ITRx其他定时器、TIx捕获通道这些void TIM_InternalClockConfig(TIM_TypeDef* TIMx);//选择内部时钟void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);//选择ITRx其他定时器的时钟,InputTriggerSource:选择要接入哪个其他的定时器void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);//选择TIx捕获通道的时钟,TIxExternalCLKSource,选择TIx具体的某个引脚,接着还有两个参数ICPolarity和CFilter,输入的极性和滤波器,对于外部引脚的波形,一般都会有极性选择和滤波器,这样更灵活一些void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);//选择ETR通过外部时钟模式1输入的时钟,ExtTRGPrescaler,外部触发预分频器(这里可以对ETR的外部时钟再提前做一个分频),接下来两个和上面那个函数参数一样
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);//选择ETR通过外部时钟模式2输入的时钟
//对于ETR输入的外部时钟而言,上面这两个函数是等效的,它们的参数是一样的,如果不需要触发输入的功能,那这两个函数可以互换void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);//这个不是用来选择时钟的,就是单独用来配置ETR引脚的预分频器、极性、滤波器这些参数的

TIM_ITRxExternalClockConfig

Snipaste_2024-11-17_13-14-46

Snipaste_2024-11-17_13-18-17

Snipaste_2024-11-17_13-19-34

Snipaste_2024-11-17_13-23-05

因为在初始化结构体里有很多关键的参数,比如自动重装值和预分频值等等,这些参数可能会在初始化之后还需要更改,如果为了改某个参数,再调用一次初始化函数,这样太麻烦了,所以这里有一些单独的函数,可以方便地更改这些关键参数

void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); //单独用来写预分频值的,Prescaler,要写入的预分频值,TIM_PSCReloadMode,写入的模式(预分频器有一个缓冲器,这个参数决定这个影子寄存器是否生效,或者是在写入后,手动产生一个更新事件,让这个值立刻生效)void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode); //改变计数器的计数模式的,TIM_CounterMode:选择新的计数器模式void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);//自动重装器预装功能配置,有无预装是可以自己选择的,使能与否就可以使这个是否有无预装void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);//给计数器写入一个值,如果你想手动给一个计数值,就可以用这个函数void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);//给自动重装器写入一个值uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);//获取当前计数器的值uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);//获取当前预分频器的值下面四个就是之前中断里面学习的那四个函数,获取标志位和清除标志位的
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

主函数内容

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"uint16_t Num;int main(void)
{OLED_Init();Timer_Init();OLED_ShowString(1, 1, "Num:");while (1){OLED_ShowNum(1, 5, Num, 5);}
}
//为了不让Num跨文件,所以把中断函数放到了这个
void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){Num ++;TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

我们调试运行发现,每次复位Num都是从1开始计数的,按理说Num的初始值是0,应该是从0开始计数的,这说明中断函数在初始化之后就立刻进入了一次,这是怎么回事呢?

打开一下TIM_TimeBaseInit函数的定义

Snipaste_2024-11-17_20-45-58

英文意思是:生成一个更新事件,来重新装载预分频器和重复计数器的值,立刻

我们知道这个预分频器是有个缓冲寄存器的,我们写的值只有在更新事件时,才会真正起作用,这里为了让值立刻起作用,所以在这最后,手动生成了一个更新事件,这样预分频器的值就有效了,但同时,它的副作用就是,更新事件和更新中断是同时发生的,更新中断会置更新中断标志位,当我们之后一但初始化完了,更新中断就会立刻进入,这就是我们刚一上电,就立该进中断的原因

解决方案:在TIM_TimeBaseInit后面,开启中断的前面,再手动调用一下TIM_ClearFlag(TIM2, TIM_FLAG_Update);

第二个项目

接线图:

6-2 定时器外部时钟

这个PA0引脚就是TIM2的ETR引脚,我们在这个引脚输入一个外部时钟

TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);//通过ETR引脚的外部时钟模式2配置
/*** @brief  Configures the External clock Mode2* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler. 外部触发预分频器,可以是下面这些值*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. //不需要分频就选择第一个*     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.*     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.*     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.* @param  TIM_ExtTRGPolarity: The external Trigger Polarity. //外部触发的极性*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active. //反向,就是低电平或下降沿有效*     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.//不反向,高电平或上升沿有效(目前选这个)* @param  ExtTRGFilter: External Trigger Filter.外部触发滤波器,这个值必须是0x00到0x0F之间的一个值,这个值就是来决定上面讲的滤波器的f和N的*   This parameter must be a value between 0x00 and 0x0F* @retval None*/
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter)
{/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));/* Configure the ETR Clock source */TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter);/* Enable the External clock mode2 */TIMx->SMCR |= TIM_SMCR_ECE;
}

ExtTRGFilter的取值

Snipaste_2024-11-17_22-38-16

我们暂时不用滤波器,所以写0x00就行了

因为引脚用到了GPIO所以我们也要初始化GPIO

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

Snipaste_2024-11-17_22-41-58

但是浮空输入(如果你外部的输入信号功率很小,内部的这个上拉电阻可能会影响到这个输入信号,这时采用浮空输入,防止外部输入的电平)会导致电平跳个没完,所以还是给了上拉输入

TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; //从0计到9就行了
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;//手动模拟的输入没有那么快,所以不需要分频

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

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

相关文章

JVM--内存结构

目录 1. PC Register&#xff08;程序计数器&#xff09; 1.1 定义 1.2 工作原理 1.3 特点 1.4 应用 2.虚拟机栈 2.1定义与特性 2.2内存模型 2.3工作原理 2.4异常处理 2.5应用场景 2.6 Slot 复用 2.7 动态链接详解 1. 栈帧与动态链接 动态链接的作用&#xff1a…

一文读懂Redis6的--bigkeys选项源码以及redis-bigkey-online项目介绍

一文读懂Redis6的--bigkeys选项源码以及redis-bigkey-online项目介绍 本文分为两个部分&#xff0c;第一是详细讲解Redis6的--bigkeys选项相关源码是怎样实现的&#xff0c;第二部分为自己对--bigkeys源码的优化项目redis-bigkey-online的介绍。redis-bigkey-online是自己开发的…

Go语言跨平台桌面应用开发新纪元:LCL、CEF与Webview全解析

开篇寄语 在Go语言的广阔生态中&#xff0c;桌面应用开发一直是一个备受关注的领域。今天&#xff0c;我将为大家介绍三款基于Go语言的跨平台桌面应用开发框架——LCL、CEF与Webview&#xff0c;它们分别拥有独特的魅力和广泛的应用场景。通过这三款框架&#xff0c;你将能够轻…

音视频入门基础:MPEG2-TS专题(5)——FFmpeg源码中,判断某文件是否为TS文件的实现

一、引言 通过FFmpeg命令&#xff1a; ./ffmpeg -i XXX.ts 可以判断出某个文件是否为TS文件&#xff1a; 所以FFmpeg是怎样判断出某个文件是否为TS文件呢&#xff1f;它内部其实是通过mpegts_probe函数来判断的。从《FFmpeg源码&#xff1a;av_probe_input_format3函数和AVI…

C++初阶学习第十一弹——list的用法和模拟实现

目录 一、list的使用 二.list的模拟实现 三.总结 一、list的使用 list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向 其前一个元素和后一个元素。 常见的list的函数的使用 std::list<int> It {1,…

Qlik Sense QVD 文件

QVD 文件 QVD (QlikView Data) 文件是包含从 Qlik Sense 或 QlikView 中所导出数据的表格的文件。QVD 是本地 Qlik 格式&#xff0c;只能由 Qlik Sense 或 QlikView 写入和读取。当从 Qlik Sense 脚本中读取数据时&#xff0c;该文件格式可提升速度&#xff0c;同时又非常紧凑…

攻防世界 Web新手练习区

GFSJ0475 get_post 获取在线场景后&#xff0c;点开网址 依据提示在搜索框输入信息 给出第二条提示信息 打开hackbar&#xff0c;将网址Load下来&#xff0c;勾选Post data&#xff0c;在下方输入框输入b2 点击Execute 出现flag值 GFSJ0476 robots 打开御剑扫描域名&#…

MySQL —— explain 查看执行计划与 MySQL 优化

文章目录 explain 查看执行计划explain 的作用——查看执行计划explain 查看执行计划返回信息详解表的读取顺序&#xff08;id&#xff09;查询类型&#xff08;select_type&#xff09;数据库表名&#xff08;table&#xff09;联接类型&#xff08;type&#xff09;可用的索引…

前端研发高德地图,如何根据经纬度获取地点名称和两点之间的距离?

地理编码与逆地理编码 引入插件&#xff0c;此示例采用异步引入&#xff0c;更多引入方式 https://lbs.amap.com/api/javascript-api-v2/guide/abc/plugins AMap.plugin("AMap.Geocoder", function () {var geocoder new AMap.Geocoder({city: "010", /…

React(二)

文章目录 项目地址七、数据流7.1 子组件传递数据给父组件7.1.1 方式一:給父设置回调函数,传递给子7.1.2 方式二:直接将父的setState传递给子7.2 给props传递jsx7.2.1 方式一:直接传递组件给子类7.2.2 方式二:传递函数给子组件7.3 props类型验证7.4 props的多层传递7.5 cla…

SpringBootTest常见错误解决

1.启动类所在包错误 问题 由于启动类所在包与需要自动注入的类的包不在一个包下&#xff1a; 启动类所在包&#xff1a; com.exmaple.test_02 但是对于需要注入的类却不在com.exmaple.test_02下或者其子包下&#xff0c;就会导致启动类无法扫描到该类&#xff0c;从而无法对…

Redis面试篇笔记(持续更新)

一、redis主从集群 单节点redis的并发能力是由上限的&#xff0c;要进一步提高redis的并发能力可以搭建主从集群&#xff0c;实现读写分离&#xff0c;一主多从&#xff0c;主节点写数据&#xff0c;从节点读数据 部署redis主从节点的docker-compose文件命令解析 version: &q…

ISUP协议视频平台EasyCVR私有化视频平台新能源汽车充电停车管理方案的创新与实践

在环保意识提升和能源转型的大背景下&#xff0c;新能源汽车作为低碳出行的选择&#xff0c;正在全球迅速推广。但这种快速增长也引发了充电基础设施短缺和停车秩序混乱等挑战&#xff0c;特别是在城市中心和人口密集的居住区&#xff0c;这些问题更加明显。因此&#xff0c;开…

goland单元测试

一、单元测试的概念 1.1 什么是单元测试&#xff0c;有什么用&#xff1f; 单元测试是针对于函数的测试&#xff0c;用来保证该函数的逻辑正确性。 1.2 单元测试的要求&#xff1f; 1. 单元测试在正式上线之前应该全部自动执行&#xff0c;并且需要保证全部通过 2. 单元测试需…

连接数据库:通过链和代理查询鲜花信息

目录 新的数据库查询范式 实战案例背景信息 创建数据库表 用 Chain 查询数据库 用 Agent 查询数据库 一直以来&#xff0c;在计算机编程和数据库管理领域&#xff0c;所有的操作都需要通过严格、专业且结构化的语法来完成。这就是结构化查询语言&#xff08;SQL&#xff0…

【c++丨STL】stack和queue的使用及模拟实现

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 一、什么是容器适配器 二、stack的使用及模拟实现 1. stack的使用 empty size top push和pop swap 2. stack的模拟实现 三、queue的…

aws上安装ssm-agent

aws-cloudwatch 连接机器 下载ssm-agent aws-ec2 安装ssm-agent aws-linux安装ssm-agent 使用 SSM 代理查找 AMI 预装 先运行&#xff1a;systemctl status amazon-ssm-agent 查看sshm-agent的状态。 然后安装提示&#xff0c;执行 systemctl start amazon-ssm-agent 启动即…

百度世界2024:智能体引领AI应用新纪元

在近日盛大举行的百度世界2024大会上&#xff0c;百度创始人李彦宏以一场题为“文心一言”的精彩演讲&#xff0c;再次将全球科技界的目光聚焦于人工智能&#xff08;AI&#xff09;的无限可能。作为一名科技自媒体&#xff0c;我深感这场演讲不仅是对百度AI技术实力的一次全面…

纯血鸿蒙NEXT-组件导航 (Navigation)

Navigation组件是路由导航的根视图容器&#xff0c;一般作为Page页面的根容器使用&#xff0c;其内部默认包含了标题栏、内容区和工具栏&#xff0c;其中内容区默认首页显示导航内容&#xff08;Navigation的子组件&#xff09;或非首页显示&#xff08;NavDestination的子组件…

C语言 | Leetcode C语言题解之第564题寻找最近的回文数

题目&#xff1a; 题解&#xff1a; #define MAX_STR_LEN 32 typedef unsigned long long ULL;void reverseStr(char * str) {int n strlen(str);for (int l 0, r n-1; l < r; l, r--) {char c str[l];str[l] str[r];str[r] c;} }ULL * getCandidates(const char * n…