2020.12.4 上午

这周在调某功放,信号源板是同事在fpga开发板上写的,然后楼上楼下都要用,就一块板两边来回抢……于是我陷入沉思,为何不自己写一个呢,遂于昨日开始动工。

自己动手当然是在单片机上写啦,咱又不会玩fpga……而且用cmx配置底层简直不要太开心,唯一问题是hal库不太会用,只能一边百度一边看正点原子例程一边改程序。

本次目标是实现按键控制输出一个频率600k,死区150ns,长度1ms的pwm信号。使用了两个定时器,tim1和tim3。tim1是高级定时器,具有死区设置,控制pwm的产生,tim3是通用定时器,控制pwm输出长度。分析完需求开始动手。

首先打开cmx创建工程,基于f103c8,使能hse,配置pll使得SYSCLK为72M。这样,定时器的输入频率也就是72M了。然后分别配置tim1和tim3。根据72M时钟来计算ARR和PSC,因为定时器时长由两个参数决定,所以给定系统时钟和定时器时长后没有唯一解,我不太会直接计算,所以拉了个excel,可以算出好几组符合要求的arr和psc参数,从中随便挑选一对整数值,输入cmx,完事。然后在tim3的nvic配置里打开tim3的中断。之后在自动生成代码的时候就会生成tim3中断的入口函数,使用的时候只需要写一个回调函数就好了。

//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim==(&htim3))
    {

    }
}

然后是比较复杂的tim1,不过在cmx的协助下,tim1的配置也变得简单了,同上方法配置arr和psc,不过为了方便配置占空比,尽量选取arr比较大psc比较小的一组参数。时钟源选择内部时钟,通道1选择pwm generation ch1 ch1n。然后配置死区时间,因为ckd没有分频,所以计算死区时间的时候输入频率还是72m,根据手册可以得出150ns应填11。然后一定一定要记得填pulse,此处决定pwm占空比。我第一次配置的时候留默认0了,怎么试都没输出,改成arr/2之后立即正常。然后设置输出极性和空闲状态电平,这个根据需要走就行了。

然后是遇到的一个坑……要使能ch1和ch1n的输出是需要两句单独的程序的……我抄原子例程里只有ch1的输出使能,导致一直只有半边输出,我还以为是定时器配置哪里有问题,一个参数一个参数改试了一上午没试出来,淦啦!

HAL_TIM_Base_Start(&htim1);
//开启定时器时基
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
//使能ch1输出
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);//使能ch1n输出

最后一个坑,我中途在寻找ch1n为什么不输出的时候关闭再开了tim1,然后ch1输出设置好像变成了or被我选成了output compare ch1 ch1n,这时候输出pwm频率是arr和psc设置频率的一半,改回pwm generation ch1 ch1n就恢复正常了。

那么我已经基本掌握怎么用定时器输出长度可控并且具有死区的pwm了,入坑32之后这么久才学会用定时器也真是菜得可以了……下一个坑可能是输出个数可控的pwm,这个感觉就更麻烦了emmmmm等需要用到的时候再说吧

吃完饭回来测波形之后更新:是我太天真了,这见鬼的pwm中间都正常就是开头结尾有三个脉冲是同时开启的,不能用做驱动信号,我gg

下班前更新:淦了一下午,去掉了开头的两个低脉冲,但是结尾的那个没去掉,本fw不行了