引言
查看前文方式:订阅我的设计自己的STM32智能小车
我i们一起完成了选购与接线,但是在上节课中我们还需要A1117芯片!咱们之后再整理。
今天我们开始学习构建代码库。(Keil5)
寄语
很多人喜欢使用CubeMX来生成初始化配置,但是我想说的是,自己构建初始化时你需要去库中自己寻找,自己寻找库函数的定义,自己去分析每一个函数的内容,学会分析方法!即使芯片产品更新换代但是咱们的分析与学习能力永远不会被淘汰!!!
功能分析
我们要让小车动起来,一定是控制电机的转动来!那么我们需要实现哪些功能呢:
小车的前进
小车的停止
小车的左转
小车的右转
其他还会有许多功能!我们暂时还没想到,所以先写这么多(在嵌入式中我们做的最多的便是不断的调试与补充!)
原理分析
我们接线方案是PB6——PB9
为什么我们选择这些引脚!
将军莫急,且看此图!这些引脚上的复用模式上告诉我们,他们上面其实还挂载了定时器!
那为什么要这样选择呢,我们先聊聊定时器的功能。
定时器
寄语
我这里不想大刀阔斧的通篇讲定时器,网上的课有很多,大家可以自己去查。而我这里就事论事我们的TIM4定时器,那我们该如何去学习呢,上网或者是问AI,但是如果你正在学习很前沿东西,那你该如何去学习呢!这里就用到了我们的芯片参考手册!·
参考手册
寻找位置
我们使用了TIM4所以先寻找TIM4在手册中的位置,我们发现TIM4出现在14章节的通用定时器!
进去学习一下吧!
寻找功能
很好,我们看看有点啥功能(和买菜一样哈)
能够计数,能够分频产生我们想要的频段,捕获输入,比较输出,PWM生成,使用外部信号控制定时器,产生中断,编码,触发控制定时器。
我们挑一下我们需要啥菜:PWM生成!因为PWM顾名思义看我的博客之前讲过:
我们继续看手册啦,流程框图我不看,这个要讲就成大工程了。那么我大致讲一下流程。
流程
我将其分为三个部分!
信号源的选取与配置
通道选取
捕获与比较
时基单元
到这里你自然就知道要和代码打交道了!
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
/* Set the default configuration */
TIM_TimeBaseInitStruct->TIM_Period = 0xFFFF;
TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000;
TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct->TIM_RepetitionCounter = 0x0000;
}
为什么我们要进入这个函数,时基函数顾名思义TimeBase。想要看这个函数里有些什么东西我们就需要查看XXXXStructInit而不是XXXXInit!!!
看完函数后我们就需要知到每个成员是什么:这里自己去看手册吧!这里我教你的是计算过程。
时钟选择
从模式指的是不依赖于任何外部模块的使用,即使使用自己的基本时钟定时,成为一个基本定时器!
意思是引脚的电平控制定时器的计数。
计数器打开,时钟沿上升沿检测,当上升沿检测到引脚为高电平时,计时器加一,标志位被置一。
这里的ETR引脚指的是外部时钟引脚,即是我们的时钟源依靠外部时钟!通俗点讲我们引脚上连接了一个时钟!(之后会使用,不急!)
捕获与比较
捕获输入,比较输出。这样子我们可以捕获到时钟高电平的时间,比较高电平在整个周期中的占比。我们一般都配合PWM模式使用!
PWM
该模式是输入捕获模式的一个特例,除下列区别外,操作与输入捕获模式相同。
我们在我们的模式一情况下,引脚上升沿时开始捕获在引脚下降沿时结束捕获,并计算脉冲宽度,计算一个周期的宽度!!!原理很简单!
当然还有很多模式,自己去手册上自学即可哈。
作用与功能
所以它可以自主产生一段有确定频率的高电平信号,当频率很低时高电平信号就是一个开关可以控制设备的打开与关闭。而当频率很高的时 ,元件不会及时反映电平的变化所以不会控制元件的打开与关闭。此时我们的高电平在周期中的时间越长,元件接收到的电压就越大!
所以PWM的作用我归结为:作为开关,控制电压
这不正好吗!控制电压就等于控制电机的转速!!!
我们需要这里就看看我们需要配置些什么吧!他都说了,它的配置与捕获比较模式的配置基本相似。
配置
很好,我们需要配置这么多东西!
模式
我们模式有这么多我们选取我么我你需要的PWM1模式!
这就是PWM1模式的波形,简单点来说就是
REF为PWM参考信号,IF为标志位。
输出比较状态
我们需要产生固定的高电平就需要使用到比较!
所以需要打开
占空比设置
由此来看自己设置就行
极性设置
决定我们占空比是(高电平/周期)还是(低电平/周期)我们使用的是前者!!所以设置High就行。
剩下的我们不需要理会,带N的指的是删除之前的配置。
时钟
最后记得打开时钟与使能时钟!!!!
初始化代码构建
迎来激动人心的时候了
这样子就可以使用引脚,定时器,捕获比较器的函数了!当然在配置是一定要打开时钟,始终不开连电都上不了跟何谈配置呢!
开始配置成员的值吧!
熟悉的引脚初始化,唯一注意的就是我们要选择输出模式。
定时器函数中这么多成员,我们并不全部使用,所以不用的我们则么办!程序运行到这里发现成员没有值,直接罢工了。
因此我们需要写一个函数将所有成员初始化为默认值!
就是这个!!!并且适用于所有固件库模块!
接下来说说对于ARR与PSC的配置,我们PWM占空比自然希望越精细越好,这就要求我们对系统时钟71MHz分得越细越好,对于脉冲周期掌握的越短越好。但要注意ARR与PSC对应的寄存器都是16位的二进制组成的。所以最大值是!!!!
PSC=31
这样子72MHz的主频就被分成2MHz——1s会产生2000 000次的震动。
假设我们以ARR=99
因此最小可以完成100/2000 000*1S(0.00002S)的定时。所以我们的精度这么高,小车的运动速度也会非常平稳。
并且我们不进行预分频。
接下来配置捕获比较
先把占空比设置为0,总不能初始化完小车就跑起来吧!
我们在流程图中发现,我们要使用PWM我们就需要是能预分频寄存器!并且使能预装载寄存器!
最后要进行初始化了(将我们配置的值赋给需要的一个寄存器)
最后我们该打开我们的定时器了!!!
初始化完工
附上初始化代码:
#include "stm32f10x.h"
void PWM(void)
{
GPIO_InitTypeDef gpio;
TIM_TimeBaseInitTypeDef time;
TIM_OCInitTypeDef pwm;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
gpio.GPIO_Mode=GPIO_Mode_AF_PP;
gpio.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
gpio.GPIO_Speed=GPIO_Speed_50MHz;
TIM_TimeBaseStructInit(&time);
time.TIM_Period=99;
time.TIM_Prescaler=31;
TIM_OCStructInit(&pwm);
time.TIM_CounterMode=TIM_CounterMode_Up;
pwm.TIM_OCMode=TIM_OCMode_PWM1;
pwm.TIM_OCPolarity=TIM_OCPolarity_High;
pwm.TIM_OutputState=TIM_OutputState_Enable;
pwm.TIM_Pulse=0;
GPIO_Init(GPIOB, &gpio);
TIM_TimeBaseInit(TIM4, &time);
TIM_OC1Init(TIM4, &pwm);
TIM_OC2Init(TIM4, &pwm);
TIM_OC3Init(TIM4, &pwm);
TIM_OC4Init(TIM4, &pwm);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM4, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
接下里该如何使用,我们下节课见。
标签:起来,定时器,TIM4,1.3,小车,引脚,TIM,GPIO,我们 From: https://blog.csdn.net/2301_76726104/article/details/140398492