平衡小车基本外设配置(外设配置、定时器、编码器模式、速度读取、pwm,exti)

基本外设配置

外设配置、定时器、编码器模式、速度读取、pwm,exti

基本外设的程序配置

创建.c文件和.h文件,头文件中注意 #ifndef _xxx

#def _xxx

#endif

配置编码器模式

编码器1——PA0/PA1—TIM2

编码器2——PB6/PB7—TIM4

#标准库 编码器的配置

  //摘自B站天下行走

void Encoder_TIM2_Init(void)

{

	GPIO_InitTypeDef GPIO_InitStruct;

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

	TIM_ICInitTypeDef TIM_ICInitStruct;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启时钟

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;//初始化GPIO--PA0、PA1

	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1;

	GPIO_Init(GPIOA,&GPIO_InitStruct);

	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);//初始化定时器。

	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;

	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;

	TIM_TimeBaseInitStruct.TIM_Period=65535;

	TIM_TimeBaseInitStruct.TIM_Prescaler=0;

	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);

	TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//配置编码器模式

	TIM_ICStructInit(&TIM_ICInitStruct);//初始化输入捕获

	TIM_ICInitStruct.TIM_ICFilter=10;

	TIM_ICInit(TIM2,&TIM_ICInitStruct);

	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//配置溢出更新中断标志位

	TIM_SetCounter(TIM2,0);//清零定时器计数值

	TIM_Cmd(TIM2,ENABLE);//开启定时器

}

1、PA0和PA1浮空输入,开启时钟

2、定时器初始化,TIM2

定时器详解

(定时器:

通用定时器的基本工作原理: 首先,定时器时钟信号送入16位可编程预分配器(Prescaler),该预分配器系数为0~65535之间的任意数值。预分配器溢出后,会向16位的主计数器(Counter Period)发出一个脉冲信号。 预分频器,本质上是一个加法计数器,预分频系数实际上就是加计数的溢出值。

定时器发生中断时间的计算方法: 定时时间 = (Prescaler+1 ) X (Counter Period+1) X 1/ 定时器时钟频率 时钟信号1KHz,Prescaler为9,Counter Period为999,定时时间? (感觉定时器一般需要用到中断,这是要使能中断,然后在回调函数里写中断程序。在main函数里要开启定时器。)
高级定时器timer1,timer8以及通用定时器timer9,timer10,timer11的时钟来源是APB2Z总线
通用定时器timer2~timer5, 通用定时器timer12-14以及基本定时器timer6-timer7时钟来源是APB1总线

定时器就是每隔多少时间单片机做一件事,具体多少时间需要我们自己来设定,譬如间隔1ms,也就是1000HZ,时钟来源的频率/(ARR+1)/(PSC+1)

#例子 (hal库)

/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM2)                  //处理TIM2间隔定时中断  判断传过来的定时器实例是不是TIM2
    {
        AL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
    }
    if(htim->Instance == TIM3)                 //处理TIM3间隔定时中断
    {
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
    }
}
/* USER CODE END 0 */

//main函数里
/* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start_IT(&htim2);        //启动定时器TIM2
    HAL_TIM_Base_Start_IT(&htim3);        //启动定时器TIM3
  /* USER CODE END 2 */

高级控制定时器(TIM1与TIM8)

通用定时器(TIM2~TIM5)

基本定时器(TIM6与TIM7) 我参考的 这个知乎大佬
#这些配置可以在cubemx里完成,也更简单一些:
在这里插入图片描述
slave mode:总共有5中,Disable、外部时钟模式1,复位模式,门级驱动模式,触发模式

还有那个trigger也不懂,一般就选disable吧,希望懂的大佬可以指点一下

具体模式用法及概念我也不懂QAQ

cubemx中定时器配置
在这里插入图片描述

编码器模式

标准库这样

TIM_ICStructInit(&TIM_ICInitStruct);//初始化输入捕获

TIM_ICInitStruct.TIM_ICFilter=10;

cubemx这样
在这里插入图片描述
input filter 滤波器一般在0-15之间,我选的10(别人的经验值),可以不分频,编码器1是在PA0和PA1上,选择通道1和通道2

在初始化中添加打开定时器的encoder模式: HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);

使用函数__HAL_TIM_GET_COUNTER(&htim2)可以实时获取计数值

__HAL_TIM_SET_COUNTER()设置计数器数值


续:其实编码器也就那么回事,跟gpio差不多的,配置相应的参数,调用相应的函数。具体的:(标准库)

TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//配置编码器模式

用TIM2,TIM_EncoderMode参数是模式,是单相计数(只能反映速度)还是两相计数(速度和方向)

TIM_IC1Polarity和TIM_IC2Polarity参数就是通道1、2的捕捉极性。

Countingon TI1 only:TI2为高时(第一行):TI1上升沿则向下计数,下降沿则向上计数。

Countingon TI1 and TI2:一个周期完成4次跳变。精度提高

这个编码器配置完成后就可以用相关函数算出速度了

速度读取

int Read_Speed(int TIMx)
{
	int value_1;
	switch(TIMx)
	{
		case 2:value_1=(short)TIM_GetCounter(TIM2);TIM_SetCounter(TIM2,0);break;//IF是定时器2,1.采集编码器的计数值并保存。2.将定时器的计数值清零。
		case 4:value_1=(short)TIM_GetCounter(TIM4);TIM_SetCounter(TIM4,0);break;
		default:value_1=0;
	}
	return value_1;
}

PWM

void PWM_Init_TIM1(u16 Psc,u16 Per)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO,ENABLE);//开启时钟
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//初始化GPIO--PA8、PA11为复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8 |GPIO_Pin_11;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);//初始化定时器。
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period=Per;
	TIM_TimeBaseInitStruct.TIM_Prescaler=Psc;
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);/*【2】*///TIM2
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//初始化输出比较
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse=0;
	TIM_OC1Init(TIM1,&TIM_OCInitStruct);
	TIM_OC4Init(TIM1,&TIM_OCInitStruct);
	
	TIM_CtrlPWMOutputs(TIM1,ENABLE);//高级定时器专属--MOE主输出使能
	
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);/*【3】*///ENABLE//OC1预装载寄存器使能
	TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);//ENABLE//OC4预装载寄存器使能
	TIM_ARRPreloadConfig(TIM1,ENABLE);//TIM1在ARR上预装载寄存器使能
	
	TIM_Cmd(TIM1,ENABLE);//开定时器。
}

用cubemx使用pwm代码
在这里插入图片描述
时钟为72MHZ,PSC设置为71,一个周期时间:72/72x1000=1ms,
1MHZ的频率时间为1us
然后需要这两个函数:
HAL_TIM_Base_Start_IT(&htim3); //启动定时器 HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3); //开启PWM
重写回调函数,(这里是一个呼吸灯的例子,a为crr的值)

int a=0;
	void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
	{
		if(htim==&htim3)  
		{
		a++;
		__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,a);
			if(a>=999) a=0;
		}
	}

在这里插入图片描述


EXIT

void MPU6050_EXTI_Init(void)
{
	EXTI_InitTypeDef EXTI_InitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);//开启时钟
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;/**【1】**///GPIO_Mode_AF_PP
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//PB5配置为上拉输入
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);	
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);//
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line5;
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStruct);
}

“本站所有文章均为原创,欢迎转载,请注明文章出处:一只菜鸡儿。(https://blog.csdn.net/Linuxzbc/article/details/108207512)百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。”

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值