引脚分配
首先需要将PG10和PG12拉低
PA6是刹车引脚,低电平就停止PWM的输出了
输出:TIM1的CH1(PE9)和CH1N(PE8)
输入:TIM8_CH1(PC6)
时间
时钟选择
内部时钟 CK_INT 即来自于芯片内部,等于 168M,一般情况下,我们都是使用内部时钟。
死区时间计算
1、原理
- 死区时间是PWM输出时,为了使H桥或半H桥的上下管不会因为开关的关断延迟问题发生同时导通而设置的一个保护时段,通常也指pwm响应时间。
- 因为有关断延时,此时如果立马导通另外一个,就会出现同时导通的现象发生。因此有必要设置死区时间,也就是上下桥臂同时关断时间。
- 死区时间设置的大,模块工作更加可靠,但会带来输出波形的失真及降低输出效率。死区时间小,输出波形要好一些,只是会降低可靠性,一般为us级。
- 一般来说死区时间是不可以改变的,只取决于功率元件制作工艺。
2、计算
计算方法:DTG[7:0]为ff。首先因为[7:5]位为111,所以选择方法四。死区时间=(32+DTG[4:0]也就是31)×16×(1/168M也就是前面设置的CKD为不分频)=6us
视频,39
- TIM_BDTRInitStructure.DeadTime = 0xff;//死区时间根据驱动芯片选择,计算结果为6us。
- TIM_TimeBaseStructure.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;一分频就是不分频,主要为定时器的其他器件提供一个时基(死区发生器和数字滤波器)就是168M
- BDTR寄存器,断路和死区寄存器。这个就是短路死区寄存器的7:0位。
这两个间隔就是6us
HAL库配置互补PWM输出
配置
1、设置输出通道
- 设置输出通道1为CH1和CH1N也可以设置为仅CH1(因为CH1和CH1N就是合在一起的,见下下图)
- 分别给CH1和CH1N选择一个合适的GPIO。
- 一个通道对应多个GPIO,这个通道即可作为输入用,也可作为输出。
2、参数设置
- 这里的预分频是给计数器用的,只对计数器的时钟起作用。
- PWM输输出周期=(168*10000)/168MHz(频率:168MHz/168 一个的时间:168MHz/168)
- 占空比= TIM1->CCR1(捕获比较寄存器) / ARR(自动重载寄存器)
- 是CR1控制寄存器的9:8位。此此位域指示定时器时钟 (CK_INT) 频率与死区发生器以及数字滤波器(ETR、TIx)所使用的 死区及采样时钟 (tDTS) 之间的分频比
- auto-reload preload 这里使能的话,改变ARR(自动重装载)的值不会马上生效,而是要等一个计数周期完成后才会生效
- BRK State:刹车状态使能。
- BRK Polarity:低电平有效,刹车引脚输入低电平时,PWM输出关闭(正反两路)。当又重新变为高电平时,瞬间恢复。
- automatic output state:自动输出状态使能。当检测到低电平时(前面设置了低电平),就自动关闭PWM输出。
- 后面两个off什么的设置使能就行
- lock configuration:上锁配置。可以设置上锁等级,这样之后某些参数就不可更改了。
- dead time:死区时间设置。看代码里面6us的话就是要填0xff。而网上挺多这里写的是6/168MHz。我直接使用6,输出的死区几乎没有。而cubemx填0xff,代码里面的DeadTime这项也就是0xff,看示波器显示的死区时间就是6us。
- PWM1模式:CNT递增模式:先有效(高电平),后无效(低电平) ;递减模式:先低电平后高电平; PWM2相反
- pulse:不用加1或者减一,写的是CCR(捕获/比较寄存器)的值。
- output compare preload:输出比较装载值使能,该选项就像自动重装载一样,使能后可修改 ARR(自动重载寄存器)和CCRx(捕获比较寄存器)来改变频率和占空比。
- 快速模式关闭。
- CH Polarity :配合pwm模式,CH通道的有效电平为高电平。CHn通道的有效电平也为高电平。如果有效电平设置为低电平,那么脉宽就变成了低电平。比如我们设置脉宽为30%的,那么CH1本应该先30的高电平,再70的低电平,这样就变成了先30的低电平,再70的高电平。这个时候改变pulse也就是改变到了前面的低电平那里了。
- CH和CHn空闲时或者禁止时(也就是刹车的时候)输出低电平。下图为设置一高一低(应该设置两个都为低,这样mos管就关闭了)
一点讲解
1、PWM输出模式
2、高电平有效还是低电平有效
正常是这个样子的
TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;//高电平有效还是低电平有效,CCER(捕获/比较使能寄存器)。如果将这个改为低电平,那么就会从原来的互补,变为波形一致了
TIM_OCInitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH;
如果改为这样,互补电平就变为一致了,如下图所示
TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_LOW;//高电平有效还是低电平有效,CCER(捕获/比较使能寄存器)。如果将这个改为低电平,那么就会从原来的互补,变为波形一致了
TIM_OCInitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH;
3、输出寄存器的配置
程序的配置就是配置这一块的功能
1:TIMx_CCER:输出比较使能寄存器
CC4P位 :0 OC1高电平有效 1 OC1低电平有效
若设置为1,当OC4_REF输出为低电平,OC4为高电平
后面的TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;
TIM_OCInitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH;使用的就是这个位
输入捕获之PWM输入模式
PWM输入模式工作原理
- 测量脉宽和频率一个更简便的方法就是使用 PWM 输入模式(不然可以使用一个通道捕获上升沿和下降沿),该模式是输入捕获的特例。使用该模式只能使用通道1和通道2,通道3和通道4使用不了。
- 使用通道CH1(也就是TI1)。设置CH1为直连,CH2为非直连,这样就可以将输入的PWM中的周期和占空比分别由捕获寄存器捕获。在这个过程中,我们需要设置触发输入为TI1FP1并设置极性比如为上升沿,TI1FP2为下降沿。那么当有一个脉宽在前的信号输入时,就会启动触发信号开始捕获,同时把计数器CNT复位清零。
- 一句话概括就是:选定输入通道,确定触发信号,然后设置触发信号的极性即可
举例:
PWM 信号由输入通道 TI1 进入,配置 TI1FP1 为触发信号,上升沿捕获。当上升沿的时候 IC1 和IC2 同时捕获,计数器 CNT 清零,到了下降沿的时候,IC2 捕获,此时计数器 CNT 的值被锁存到捕获寄存器 CCR2 中,到了下一个上升沿的时候,IC1 捕获,计数器 CNT 的值被锁存到捕获寄存器 CCR1 中。其中 CCR2+1 测量的是脉宽,CCR1+1 测量的是周期。这里要注意的是 CCR2 和CCR1 的值在计算占空比和频率的时候都必须加 1,因为计数器是从 0 开始计数的。
HAL库配置
- 从模式:这里我们选复位模式,即当启动触发信号时,同时把CNT复位清零。还有禁止从模式,编码器模式123,复位模式,门控模式,触发模式,外部时钟模式1。详见下图
- 触发源:选择TI1FP1。设置为触发信号也就是触发源的那一路对应的就是周期,另外一路就是占空比了。
- 内部时钟,168MHz。
- 直连和非直连:使两个捕获寄存器用到一起。
- 设置通道1为上升沿捕获,通道2为下降沿捕获。
- 输入捕获通道预分频器,可设置 1、2、4、8 分频,它设定 CCMRx 寄存器的ICxPSC[1:0] 位的值。如果需要捕获输入信号的每个有效边沿,则设置 1 分频即可。
- 一般不使用滤波器,设置为0即可。见下图
中断
勾选了这个就会出现再下面这张图,这个时候才能使用中断回调函数。我想应该是勾选后,就是在NVIC中注册了这个中断,然后在函数中调用函数使能,这个时候就能产生中断了。
HAL按键
这几个拉低禁用
API
资源包讲解
回调函数,可以从下面这两个地方找到
__HAL_TIM_SetCompare —— 设置CCR(脉宽)的值
//__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,ChannelPulse);
htim1.Instance->CCR1 = ChannelPulse;//直接这样也可以 CCR1就代表通道1
参考
代码
main
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM1_Init();
MX_TIM8_Init(