UAV021(五):STM32F429实现TIM6计时、TIM3输出4路PWM波、TIM5输入捕获

2023-11-02



现在需要实现计时,输出PWM和输入捕获。其中计时实现0.1ms加1,用于陀螺仪积分计时;输出4路PWM波频率为400Hz,用于驱动无人机电机;输入捕获频率1MHz,用于测量输出的 PWM周期、占空比等,看看PWM波是否正常。

这些功能都需要定时器,STM32F4有14个定时器TIM1~TIM14,但是不同定时器功能并不尽相同,该怎样选择(并且实现)呢?

此处主讲定时器,也在之前的程序基础上做改动。之前使用 TIM3做基本的计时,此处开始改为 TIM6。


一、STM32F4定时器介绍


STM32定时器一览表

STM32
如上图所示,TIM6和TIM7为基本定时器、TIM2~TIM5,TIM9~TIM14为通用定时器,TIM1和TIM8为高级定时器。

首先,要做0.1ms基本定时,基本定时器是首选,因为只是简单定时,不涉及IO应用,基本定时器已经能够满足功能。

其次,要输出4路 400Hz的PWM波,不用互补输出功能但要输出4路,因此TIM2~TIM5 皆可。考虑到 400Hz 对应周期 2.5ms,假设将时钟源90MHz通过90分频得到1MHz的定时器,16位定时器可计数 65535个,最大周期为 65.535ms,已经远远满足 2.5ms 的需求了。因此 16 位定时器即可,此处选择 TIM3。

最后,对于输入捕获,测量高电平时间、测量周期等。假如使用1MHz定时器时钟,16位时可以计数 216= 65535us = 65ms,使用用 32位定时器 TIM5,使用1MHz 的定时器时钟,可以计数 232 us = 4294s。虽然使用16位定时器已经能满足此处PWM波的测量,但是使用32位定时器能够满足秒级别的测量,后期使用测量也可以直接使用,故采用32位的TIM5。


二、定时器配置


2.1 TIM6实现计数

配置定时器实现计数功能,包括以下几个步骤:

  1. 初始化配置。包括选择定时器、配置分配系数、计数模式、自动重装值及时钟分配因子。
  2. 底层配置。开启时钟、配置并使能中断。
  3. 中断服务函数。清除中断标志位、实现计数功能

按照以上步骤,配置如下:

/* 注意:1. 中断相关名称。注意基本定时器TIM6 的中断名为 TIM6_DAC_IRQn,< TIM6 global and DAC1&2 underrun error  interrupts>,其他一些定时器为 TIMx_IRQn(x=2,3,4,7 etc)	*/
/* 中断函数名为 TIM6_DAC_IRQHandler(),而不是 TIM6_IRQHandler()		*/
/* 3. 基本定时器(TIM6, TIM7),通用定时器,高级定时器(TIM1, TIM8),功能越来越多,此处只做个简单计时,基本定时器足够了	*/

#include "timer.h"

uint32_t tim = 0;						// 全局变量,每0.1ms加1
TIM_HandleTypeDef TIM6_Handler;      	//定时器句柄 

/* 基本定时器6初始化						*/
/* 实现 0.1ms 计时中断					*/
/* 90M/90=1M,1M/100 = 10kHz = 0.1ms	*/
void TIM6_Init(void)
{  
    TIM6_Handler.Instance			= TIM6;                  		// 基本定时器
    TIM6_Handler.Init.Prescaler		= 90-1;                 		// 分频系数 90,得到 90M/90=1M 时钟
    TIM6_Handler.Init.CounterMode	= TIM_COUNTERMODE_UP;    		// 向上计数器
    TIM6_Handler.Init.Period		= 100-1;                  		// 自动装载值 100,每 100/1M = 100us=0.1ms中断一次
    TIM6_Handler.Init.ClockDivision	= TIM_CLOCKDIVISION_DIV1;		// 时钟分频因子
    HAL_TIM_Base_Init(&TIM6_Handler);
	
    HAL_TIM_Base_Start_IT(&TIM6_Handler); //使能定时器3和定时器3更新中断:TIM_IT_UPDATE   
}
/* 定时器底册驱动,开启时钟,设置中断优先级	*/
/* 此函数会被HAL_TIM_Base_Init()函数调用		*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM6)
	{
		__HAL_RCC_TIM6_CLK_ENABLE();            						// 使能TIM6时钟,
		HAL_NVIC_SetPriority(TIM6_DAC_IRQn,1,3);    					// 中断优先级:抢占优先级1,子优先级3。
		HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);          					// 开启ITM6中断  
	}
}

/* 定时器6中断服务函数	*/
void TIM6_DAC_IRQHandler(void)
{
	if(__HAL_TIM_GET_IT_SOURCE(&TIM6_Handler, TIM_IT_UPDATE) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(&TIM6_Handler, TIM_IT_UPDATE);				// 清除中断标志位
    }
    tim ++; 														// 又是0.1ms,全局时间计数加1
}

要注意中断及中断函数名称,对于TIM6为 TIM6_DAC_IRQn、TIM6_DAC_IRQHandler()。

还有分频系数与时钟分频因子,为什么有了分频系数还要分频因子呢?不是很理解,可以参考这篇文章


2.2 TIM3输出4路PWM波

与定时不同,配置输出PWM波需要配置I/O口,相应地需要配置相应通道;输出PWM波时可不配置中断。步骤如下:

  1. 初始化配置。选择时钟、配置分频系数、计数模式、自动重装值、分频因子。
  2. 通道配置。配置PWM模式、默认占空比、输出比较极性并且开启对应的通道。
  3. 底层配置。开启时钟、配置相关引脚。

此处,航模电机驱动频率选择常用的 400Hz,定时器重装值选择 5000-1。为了方便实际中调节各个电机的占空比,编写设置于获取占空比的函数,占空比调节精度为 1/1000。

对于I/O选择,使用了TIM3 CH1~CH3,对应引脚参考核心板原理图:

#define PWM_PIN			GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_0 | GPIO_PIN_1
#define PWM_GPIO		GPIOB
#define PWM_ENCLK()		__HAL_RCC_TIM3_CLK_ENABLE();	\
						__HAL_RCC_GPIOB_CLK_ENABLE();	// 使能定时器3,开启GPIOB时钟						

/* 四个电机枚举	*/
typedef enum
{
	MOTOR1 = 0,
	MOTOR2 = 1,
	MOTOR3 = 2,
	MOTOR4 = 3
};
	 
/* TIM3 4路 PWM波输出初始化 		*/
void TIM3_PWM_Init(void)
{ 
    TIM3_Handler.Instance			= TIM3;            		//定时器3
    TIM3_Handler.Init.Prescaler		= 45-1;       			//定时器分频 45,得到 90M/45=2M 时钟
    TIM3_Handler.Init.CounterMode	= TIM_COUNTERMODE_UP;	//向上计数模式
    TIM3_Handler.Init.Period		= 5000-1;          		//自动重装载值 5000,得到PWM频率 2M/5k=400Hz
    TIM3_Handler.Init.ClockDivision	= TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&TIM3_Handler);       					//初始化PWM
    
    TIM3_CHxHandler.OCMode			= TIM_OCMODE_PWM1; 		//模式选择PWM1
    TIM3_CHxHandler.Pulse			= 0;           			//设置比较值,此值用来确定占空比,默认为0
    TIM3_CHxHandler.OCPolarity		= TIM_OCPOLARITY_HIGH; 	//输出比较极性为高
	
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_1);	//配置TIM3通道1
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_1);		//开启PWM通道1
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_2);	//配置TIM3通道2
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_2);		//开启PWM通道2
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_3);	//配置TIM3通道3
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_3);		//开启PWM通道3
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_4);	//配置TIM3通道4
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_4);		//开启PWM通道4
	
}

/* 定时器底层驱动,时钟使能,引脚配置	*/
/* 此函数会被HAL_TIM_PWM_Init()调用	*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
	
	PWM_ENCLK();
	
    GPIO_Initure.Pin		= PWM_PIN; 
    GPIO_Initure.Mode		= GPIO_MODE_AF_PP;  			// 复用推完输出
    GPIO_Initure.Pull		= GPIO_PULLUP;          		// 上拉
    GPIO_Initure.Speed		= GPIO_SPEED_HIGH;     			// 高速
	GPIO_Initure.Alternate	= GPIO_AF2_TIM3;				// 引脚复用
    HAL_GPIO_Init(PWM_GPIO, &GPIO_Initure);
}

/* 设置电机占空比										*/
/* motor: 选择电机,可填MOTOR1, MOTOR2, MOTOR3, MOTOR4	*/
/* duty: 占空比为千分之 duty								*/
void SetMotorDuty(uint8_t motor, uint16_t duty)
{
	if (duty > 1000)
		duty = 1000;
	else if (duty < 0)
		duty = 0;
	
	if (motor == MOTOR1)
		TIM3->CCR1 = duty * 5 - 1;	// 由于计数器重装值ARR为 5000,精度为千分之一,故此处乘以5,减一是因为从0开始计数
	else if (motor == MOTOR2)
		TIM3->CCR2 = duty * 5 - 1;
	else if (motor == MOTOR3)
		TIM3->CCR3 = duty * 5 - 1;
	else if (motor == MOTOR4) 
		TIM3->CCR4 = duty * 5 - 1;
}

/* 获取电机占空比														*/
/* motor选择电机,可填MOTOR1, MOTOR2, MOTOR3, MOTOR4,占空比为千分之返回值	*/
uint16_t GetMotorDuty(uint8_t motor)
{
	uint32_t cap_value;
	if (motor == MOTOR1)
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);		// 读取比较寄存器的值
	else if (motor == MOTOR2)
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);
	else if (motor == MOTOR3)
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);
	else if (motor == MOTOR4) 
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);
	
	return (cap_value+1) / 5;
}				

2.3 TIM5输入捕获

输入捕获也需要配置对应的 I/O 口于通道,而且需要在中断服务函数里实现定时中断、高/低电平时间的测量。步骤如下:

  1. 初始化配置。选择时钟、配置分配系数、计数模式、自动重装值、时钟分频因子。
  2. 通道配置。配置上升/下降沿捕获、引脚对应寄存器、分频因子、滤波效果。
  3. 底层配置。配置引脚、使能时钟、中断优先级与是能。
  4. 中断服务函数。思想很简单,分别读取下降沿、上升沿、下降沿时寄存器数据,计算得到正脉宽、周期等参数。

具体程序如下:

#define CAP_PIN			GPIO_PIN_0
#define CAP_GPIO		GPIOA
#define CAP_ENCLK()		__HAL_RCC_TIM5_CLK_ENABLE();	\
						__HAL_RCC_GPIOA_CLK_ENABLE(); 	//使能TIM5时钟,开启GPIOA时钟

TIM_HandleTypeDef TIM5_Handler;         							//定时器5句柄

uint32_t cap_value1 = 0;			// 检测到上升沿时的计数
uint32_t cap_value2 = 0;			// 检测到下降沿时的计数, cap_value2 - cap_value1 即为正脉冲时间
uint32_t cap_value3 = 0;			// 再次检测到上升沿时的计数, cap_value3 - cap_value1 即为周期

uint8_t cap_sta = 0;				// 输入捕获状态, 0:没有完成捕获,去捕获边沿吧  1:捕获边沿完成,去计算周期吧
uint8_t cap_times = 0;				// 捕获次数

/* 定时器5通道1输入捕获配置 	*/
/* 频率:90M/90/1 = 1MHz		*/
void TIM5_CH1_Cap_Init(void)
{  
    TIM_IC_InitTypeDef TIM5_CH1Config;  
    
    TIM5_Handler.Instance			= TIM5;                         // 通用定时器5
    TIM5_Handler.Init.Prescaler		= 90-1;                     	// 分频系数
    TIM5_Handler.Init.CounterMode	= TIM_COUNTERMODE_UP;    		// 向上计数器
    TIM5_Handler.Init.Period		= 0XFFFFFFFF;                   // 自动装载值
    TIM5_Handler.Init.ClockDivision	= TIM_CLOCKDIVISION_DIV1;		// 时钟分频银子
    HAL_TIM_IC_Init(&TIM5_Handler);									// 初始化输入捕获时基参数
    
    TIM5_CH1Config.ICPolarity		= TIM_ICPOLARITY_RISING;    	// 上升沿捕获
    TIM5_CH1Config.ICSelection		= TIM_ICSELECTION_DIRECTTI;		// 设置引脚与寄存器关系。CH1、CH2用TI1,CH3、CH4用TI2
    TIM5_CH1Config.ICPrescaler		= TIM_ICPSC_DIV1;          		// 配置输入分频,不分频
    TIM5_CH1Config.ICFilter=0;                          			// 配置输入滤波器,不滤波
    HAL_TIM_IC_ConfigChannel(&TIM5_Handler,&TIM5_CH1Config,TIM_CHANNEL_1);//配置TIM5通道1
	
    HAL_TIM_IC_Start_IT(&TIM5_Handler,TIM_CHANNEL_1);   			// 开启TIM5的捕获通道1,并且开启捕获中断
    __HAL_TIM_ENABLE_IT(&TIM5_Handler,TIM_IT_UPDATE);   			// 使能更新中断
}

/* 定时器5底层驱动,时钟使能,引脚配置	*/
/* 此函数会被HAL_TIM_IC_Init()调用	*/
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
	
	CAP_ENCLK();
	
    GPIO_Initure.Pin		= CAP_PIN;            					// 引脚
    GPIO_Initure.Mode		= GPIO_MODE_AF_PP;      				// 复用推挽输出
    GPIO_Initure.Pull		= GPIO_PULLDOWN;        				// 下拉
    GPIO_Initure.Speed		= GPIO_SPEED_HIGH;     					// 高速
    GPIO_Initure.Alternate	= GPIO_AF2_TIM5;   						// PA0复用为TIM5通道1
    HAL_GPIO_Init(CAP_GPIO,&GPIO_Initure);

    HAL_NVIC_SetPriority(TIM5_IRQn,2,0);    						// 设置中断优先级,抢占优先级2,子优先级0
    HAL_NVIC_EnableIRQ(TIM5_IRQn);          						// 开启ITM5中断通道  
}

/* 定时器5中断服务函数			*/
void TIM5_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&TIM5_Handler);								//定时器共用处理函数
}

/* 定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用	*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)			//更新中断(溢出)发生时执行
{
	if (cap_sta == 0)
	{
		switch (cap_times)
		{
			case 0: 				// 清空一切,准备捕获
				cap_value1 = 0;
				cap_value2  = 0;
				cap_value3  = 0;
				__HAL_TIM_DISABLE(&TIM5_Handler);        									//关闭定时器5
				__HAL_TIM_SET_COUNTER(&TIM5_Handler,0);		
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获
				__HAL_TIM_ENABLE(&TIM5_Handler);
				cap_times = 1;
				break;
			case 1:					// 捕获了一次
				cap_value1 = HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);		// 读数一次
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//定时器5通道1设置为上升沿捕获		
				cap_times = 2;
				break;
			case 2:					// 捕获了两次
				cap_value2 = HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);		// 读数一次
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获		
				cap_times = 3;
				break;
			case 3:					// 捕获了三次
				cap_value3 = HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);		// 读数一次
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);	//定时器5通道1设置为上升沿捕获
				cap_times = 0;			
				cap_sta = 1;		// 所有捕获完成,可以去计算了
				break;
		}
	}
}

输入捕获现在主要为了测试PWM波是否正常,因此将这部分内容放置在 pwm.c 里(想想在飞控里单独弄个 capture.c 总让人感觉怪怪的)。同时,编写以下测试任务,将PWM输出引脚与输入捕获引脚连接在一起,即可测试。

void TestPwmTask(void *arg)
{
	const uint16_t test_postime = 100;	// 正常时间为 test_postime / 1000 * 2500 = test_postime * 2.5
	
	uint32_t pos_time;				// 高电平时间
	uint32_t cycle;					// 周期
	uint32_t freq;					// 频率
	float pos_duty;					// 正占空比
	
	SetMotorDuty(MOTOR1, test_postime);						// 电机PWM 400Hz = 2500 us,占空比 100/1000,高电平时间 250us		
	SetMotorDuty(MOTOR2, test_postime);
	SetMotorDuty(MOTOR3, test_postime);
	SetMotorDuty(MOTOR4, test_postime);
		
	while(1)
	{
        if (cap_sta == 1)      		//成功捕获到了一次高电平
		{
			pos_time = cap_value3 - cap_value2;
			cycle = cap_value3 - cap_value1;
			freq = (uint32_t)1000000 / cycle;
			pos_duty = (float) pos_time / (float) cycle;
			
			printf("周期:%d us\t  正脉冲宽:%d us  \r\n", cycle, pos_time);
			printf("频率:%d Hz\t  正占空比:%.2f %%\r\n\r\n", freq, pos_duty*100);

			cap_sta = 0;          		// 搞完事情,开启下一次捕获
		}
		delay_ms(200);
	}
}

用杜邦线将 PB4/PB5/PB0/PB1中的其中一个与 PA0 连接在一起,测量结果如下:

运行结果

可见,确实是我们想要的400Hz,占空比也是我们测试设置的 10%(误差忽略不计)。

完整工程代码下载需积分:https://download.csdn.net/download/weixin_41869763/13054651

— 完 —

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UAV021(五):STM32F429实现TIM6计时、TIM3输出4路PWM波、TIM5输入捕获 的相关文章

  • Qt使用帮助文档Assistant

    我们在学习Qt的时候 遇到不懂的地方 可以求助互联网 看教程书籍 也可以直接看Qt的帮助文档Assistant Qt自带的帮助文档是Assistant软件 这可以从Qt的安装路径中找到 我的电脑里Qt的安装路径是E Qt Qt5 14 2
  • Endnote20 在word里插入参考文献 [快捷键Alt+2]

    https www yuque com duzh929 blog kq5u0u原文地址 墙裂建议看看新方法 更简单的新方法 有效解决Endnote20插入参考文献 Endnote20已经上线了 楼主迫不及待的用上了 发现EndnoteX9里
  • MYSQL注入 基础篇1.0

    就算命运不公 重重阻碍 但我在哪里跌倒就一定会在哪里爬起来 只要坚持不懈 那些嘲笑我的人迟早会被我笑死 SQL注入了解 SQL注入是什么 正常的Web端口访问 SQL注入是如何访问 为什么要深入了解SQL注入 SQL注入漏洞的根本原因 SQ
  • 【华为OD机试真题 python】密室逃生游戏【2022 Q4

    题目描述 密室逃生游戏 小强增在参加 密室逃生 游戏 当前关卡要求找到符合给定 密码K 升序的不重复小写字母组成 的箱子 并给出箱子编号 箱子编号为 1 N 每个箱子中都有一个 字符串s 字符串由大写字母 小写字母 数字 标点符号 空格组成
  • JS中的逻辑与和逻辑或

    JS中的逻辑或 符号 从字面上来说 只有前后都是 false 的时候才返回 false 否则返回 true console log 5 gt 6 6 gt 5 返回true 5 gt 6为false 但是 6 gt 5为true 所以返回
  • python-selenium页面定位不到元素

    1 查看是否有新的url打开 当前页面 mainHandle driver current window handle 获取所有的handle Handles driver window handles 循环遍历 找到不是当前页面的就切换
  • vue获取元素offsetTop,mounted获取不到offsetTop,获取元素距离页面顶边距离

    记录一下开发过程中遇到的坑 今天想做一个功能 当我评论完之后 页面跳到评论区顶部 于是就要获取到评论区距离页面顶部的距离 需要循环获取offsetTop来实现 但是在mounted阶段是无论如何都获取不到offsetParent的 不管是
  • C# 对数据库操作的函数总结

    SqlCommand ExecuteNonQuery 方法对连接执行 Transact SQL 语句并返回受影响的行数 可以写也可以读 1 可以使用ExecuteNonQuery 来执行目录操作 例如查询数据库的结构或创建诸如表等的数据库对
  • Unet 语义分割模型(Keras)

    文章目录 前言 一 什么是语义分割 二 Unet 1 基本原理 2 mini unet 3 Mobilenet unet 4 数据加载部分 参考 前言 最近由于在寻找方向上迷失自我 准备了解更多的计算机视觉任务重的模型 看到语义分割任务重U
  • BAT文件里注释符号

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 在BAT文件批处理中注释的方式如下 1 注释内容 第一个冒号后也可以跟任何一个非字母数字的字符 2 rem 注释内容 不能出现重定向符号和管道符号 3 echo 注释内容
  • nginx配置https访问

    01 http https HTTP HyperText Transfer Protocol 超文本传输协议 是一种用于分布式 协作式和超媒体信息系统的应用层协议 简单来说就是一种发布和接收 HTML 页面的方法 被用于在 Web 浏览器和
  • 在ubuntu上安装splint

    lint lint是最著名的C语言工具之一 是由贝尔实验室SteveJohnson于1979在PCC PortableC Compiler 基础上开发的静态代码分析 一般由UNIX系统提供 工具介绍 与大多数C语言编译器相比 lint可以对
  • 试图理解 Decagon(二)具体方法

    4 图卷积 Deacgon 方法 综述 关系被表示为一个图 G V R 其中 节点N 蛋白质 药物 vi V 和标记的边 vi r vj r代表边的类型 分别由 蛋白质间的作用 某种药物 与其作用蛋白质间的关系 存在于某两种药物间的副作用关
  • SQLSERVER登录与JDBC连接事宜

    这半天都在帮副主席搞这个 比较最重要的两个点 SQLServer创建用户登录 https www cnblogs com vuenote p 10143434 html 使用JDBC连接SQLSERVER数据库 https www cnbl
  • C51单片机期末复习第八章单片机接口技术

    一 总线 传送同类信息的连线 三总线 地址总线AB 数据总线DB 控制总线CB 目录 ppt给的没啥用 乱还不全 8 1 单片机的系统总线 8 2 简单并行I O口扩展 8 3 可编程并行I O口扩展 8 4 D A转换与DAC0832应用
  • vue 自定义月日历日程组件(MSchedule)

    效果图 组件的使用 日程内容可以自定义 状态对应颜色可以自定义
  • vue 动态组件component标签

    vue 提供了一个内置的
  • python笔记:#013#高级变量类型

    高级变量类型 目标 列表 元组 字典 字符串 公共方法 变量高级 知识点回顾 Python 中数据类型可以分为 数字型 和 非数字型 数字型 整型 int 浮点型 float 布尔型 bool 真 True 非 0 数 非零即真 假 Fal
  • Ubuntu root账户登陆电脑

    vi etc pam d gdm autologin 屏蔽 auth required pam succeed if so user root quiet success vi etc pam d gdm password 屏蔽auth r

随机推荐

  • nextLine().split(“[\\s]“)的意思

    Scanner sc new Scanner System in String a sc nextLine split s 这句话的意思是 把输入的字符串以 s 为条件分割成一个String数组 s表示空格 回车 换行等空白符 当然 单表示
  • 学python的第十五天---简单数论

    模运算 一 刷题统计 二 快速幂 三 RSA解密 GCD LCM 四 核桃的数量 最小公倍数 五 Hankson 的趣味题 六 寻找整数 素数 七 笨小孩 八 质数 九 分解质因数 模运算 ab mod m a mod m b mod m
  • Java实现比较版本号

    涉及到客户端的系统中经常需要用到比较版本号的功能 但是比较版本号又不能完全按照字符串比较的方式去用compareTo之类的方法 这就需要我们总结版本号的通用规则 设计一个比较算法并封装成通用方法来使用 通常版本号如 1 3 20 8 6 8
  • RS-485总线前世今生;

    一 RS232和RS485的区别 RS 232采取的是单端不平衡传输方式 其收发端的数据信号都是相对于地信号的 所以共模抑制能力 差 再加上双绞线分布电容的影响 其最大传输距离仅为15米 最高传输速率只有20kbit s 2560Byte
  • bash脚本调试方法

    本文全面系统地介绍了shell脚本调试技术 包括使用echo tee trap等命令输出关键信息 跟踪变量的值 在脚本中植入调试钩子 使用 n 选项进行shell脚本的语法检查 使用 x 选项实现shell脚本逐条语句的跟踪 巧妙地利用sh
  • Bandizip已管理员身份运行

    系列文章目录 文章目录 系列文章目录 前言 一 Bandzib是什么 二 使用步骤 1 引入库 前言 在解压krita源码包时Bandizip报错 一 Bandzib是什么 bandzip官网 Bandizip 是一款压缩软件 它支持Zip
  • 3D空间堆叠PCB设计 ——PCB线路优化项目总结

    3D空间PCB堆叠设计适用于线路板安装空间狭小场合使用 PCB空间排布大大提高空间利用率更加高效 前言 19年的5月下旬有人找我做一个项目 他们要3块比手掌张开还大的电路板 如下图 优化到可以放入水杯类似的圆柱体中 高度越底越好 这种 主体
  • 利用python爬取招聘网站上的相关岗位信息

    这段代码是一个爬取Boss直聘网站上数据岗位信息的爬虫程序 它使用了异步编程库asyncio和网页自动化测试库pyppeteer来实现异步的网页爬取和数据提取 import asyncio 异步编程库 import random 随机数生成
  • 不用看网课就能学到python的文章(第三天)

    紧接着上一篇不用看网课就能学到python的文章 第二天 Why does it work的博客 CSDN博客 如果说到语句 那我们应该了解一些一些python python最具特色的就是使用缩进来表示代码块 不需要使用大括号 行与缩进 i
  • google Guava之EventBus

    文章目录 EventBus基本用法 1 创建Listener 2 创建EventBus并发送消息 Listener之间的继承关系 Subscriber 不同类型参数的Subscribe event 继承关系的event DeadEvent
  • 树莓派3B安装python3 opencv环境

    树莓派3b 若干年前买的 软件具体配置不记得 python缺省版本为3 53 直接用pip命令安装不成功 显示一堆的红字 update upgrade一下 耗时挺长 再安装 成功了 如下图 sudo apt get update sodu
  • C++11 并发指南系列

    本系列文章主要介绍 C 11 并发编程 计划分为 9 章介绍 C 11 的并发和多线程编程 分别如下 C 11 并发指南一 C 11 多线程初探 本章计划 1 2 篇 已完成 1 篇 C 11 并发指南二 std thread 详解 本章计
  • 微信小程序:cavans的使用(一)

    最近用到这个canvas画布这个组件 其实还是挺有意思的 优点是可以给用户绘制宣传海报什么的 这个现在好多小程序都有这个 比如给你一个专属海报有你的头像还有你的二维码 你可以保存在你的相册里 你可以取拿它去拉人 微信小程序canvas组件官
  • 因为好兄弟一句话竞。。。

    职教云查同学考试成绩 本来在打游戏 好兄弟微信问了我一句职教云未公开的考试能不能 打包好的软件下载地址在文章后面 然后在想 考试未公开 只有那老师能看班里同学成绩 先试了抓一下包 发现在学生端啥也没有只能获得考试的ID 好家伙 突然灵光一闪
  • 继承与多态(Java实现)

    继承和多态 一 类的继承 1 继承的实现 语法格式 class 子类名 extends 父类名 类体 注 extends是关键字 Java中只支持单继承 所以子类只有一个父类 但可以多层继承 子类通过继承可以获得父类的public prot
  • PCL 计算点云的高斯曲率和平均曲率

    目录 一 算法原理 二 代码实现 三 结果展示 四 相关链接 一 算法原理 已知某点的主曲率为 k 1 k 2 k 1 k 2 k
  • 基于Opencv实现的多彩隔空画图

    1 问题概述 人工智能带火了计算机视觉的人才需求 作为计算机视觉应用开发框架OpenCV也越来越受到欢迎 市场需求大增 因此 在学习Python的基础上 进行Opencv技术的学习是十分重要且有必要的 该项技术不仅有着成熟的学习框架 更有广
  • 淘宝应对"双11"的技术架构分析

    http www uml org cn zjjs 201311272 asp http www uml org cn 火龙果软件
  • Ubuntu 14.04安装TeamViewer

    1 到官网下载teamviewer的deb包 2 拷贝到 下 打开文件 双击 deb包 3 在Ubuntu软件中心中点击安装 如果缺少依赖包 sudo apt get install f修复依赖关系
  • UAV021(五):STM32F429实现TIM6计时、TIM3输出4路PWM波、TIM5输入捕获

    目录 序 一 STM32F4定时器介绍 二 定时器配置 2 1 TIM6实现计数 2 2 TIM3输出4路PWM波 2 3 TIM5输入捕获 序 现在需要实现计时 输出PWM和输入捕获 其中计时实现0 1ms加1 用于陀螺仪积分计时 输出4