TA的每日心情 | 开心 2023-7-5 11:08 |
---|
签到天数: 120 天 连续签到: 1 天 [LV.7]常住居民III
|
本设备配备有两个PWM模块实例——PWM0与PWM1,遗憾的是,这两个实例均不支持NanoEdge放置功能。不过,通过精密的抖动处理技术,我们依然能够实现细腻的边缘控制效果。值得注意的是,本设备仅采用了PWMn_EXTA输入端口,而PWMn_EXTB输入端口则未被使用。PWM模块内部嵌有多个PWM子模块,每个子模块均可独立操控一个半桥功率级,为用户提供强大的故障通道支持。该模块能够生成多样化的开关模式,即便是高度复杂的波形也不在话下,因此,它无疑是控制各类开关电源(SMPS)拓扑结构的理想之选。
PWM的特点如下:
•用于中心、边缘对齐和不对称PWM的16位分辨率
•当精细边缘放置不可用时,抖动以模拟增强的分辨率
•可以作为互补对或独立通道运行的PWM输出
•能够接受PWM生成的带符号数字
•独立控制每个PWM输出的两个边沿
•持与外部硬件或其他PWM同步
•双缓冲PWM寄存器
—从1到16的整体重新加载速率
—半周期重新加载能力
•每个PWM周期可以通过硬件生成多个输出触发事件
•支持双开关PWM输出
•可以将故障输入分配给控制多个PWM输出
•用于故障输入的可编程滤波器
•独立可编程PWM输出极性
•独立的顶部和底部死区插入
•每个互补对可以使用其自己的PWM频率和死区时间值进行操作
•每个PWM输出的单独软件控制
•所有输出都可以编程为通过FORCE_OUT事件同时改变
•PWM_X引脚可以选择性地从每个子模块输出第三PWM信号
•未用于PWM生成的通道可用于缓冲输出比较功能和输入捕获功能
•增强的双边缘捕获功能
我们实验测试一下:
本开发板载的是MCX N947,封装为184VFBGA,采用M33内核,主频可以达到150MHz,
配置工具添加外设:
时钟配置:
打开例程对应的时钟配置如下:
主频为150MHz,PRO_HF为48M,通过测试可以得知定时器所用的高频时钟为48M。
引脚配置:
例程中使用的是P0_10作为PWM输出引脚,该引脚同时是LED的控制引脚。
一、设置PWM功能流程(在例程中添加一路PWM输出)
1、配置系统时钟
- /* attach FRO 12M to FLEXCOMM4 (debug console) */
- CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u);
- CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
- /* Use FRO HF clock for some of the Ctimers */
- CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1u);
- CLOCK_AttachClk(kFRO_HF_to_CTIMER0);
复制代码 2、配置引脚
打开配置工具的查看引脚功能,P0_10配置为CTIMER0的PWM通道1;
来到代码中可以看到如下初始化:
- /* Enables the clock for PORT0 controller: Enables clock */
- CLOCK_EnableClock(kCLOCK_Port0);
-
- const port_pin_config_t LED_RED = {/* Internal pull-up/down resistor is disabled */
- kPORT_PullDisable,
- /* Low internal pull resistor value is selected. */
- kPORT_LowPullResistor,
- /* Fast slew rate is configured */
- kPORT_FastSlewRate,
- /* Passive input filter is disabled */
- kPORT_PassiveFilterDisable,
- /* Open drain output is disabled */
- kPORT_OpenDrainDisable,
- /* Low drive strength is configured */
- kPORT_LowDriveStrength,
- /* Pin is configured as CT0_MAT0 */
- kPORT_MuxAlt4,
- /* Digital input enabled */
- kPORT_InputBufferEnable,
- /* Digital input is not inverted */
- kPORT_InputNormal,
- /* Pin Control Register fields [15:0] are not locked */
- kPORT_UnlockRegister};
- /* PORT0_10 (pin B12) is configured as CT0_MAT0 */
- PORT_SetPinConfig(BOARD_INITPINS_LED_RED_PORT, BOARD_INITPINS_LED_RED_PIN, &LED_RED);
- /* PORT0_11 (pin B11) is configured as CT0_MAT1 */
- PORT_SetPinMux(PORT0, 11U, kPORT_MuxAlt4);
- PORT0->PCR[11] = ((PORT0->PCR[11] &
- /* Mask bits to zero which are setting */
- (~(PORT_PCR_IBE_MASK)))
- /* Input Buffer Enable: Enables. */
- | PORT_PCR_IBE(PCR_IBE_ibe1));
复制代码 3、配置定时器及通道
板级的初始化已经完成,我们需要通过将我们添加的引脚与对应的定时器添加上。
- /* Get the PWM period match value and pulse width match value of 20Khz PWM signal with 20% dutycycle */
- CTIMER_GetPwmPeriodValue(20000, 20, timerClock);
- CTIMER_SetupPwmPeriod(CTIMER, kCTIMER_Match_3, kCTIMER_Match_0, g_pwmPeriod, g_pulsePeriod, false);
- CTIMER_GetPwmPeriodValue(20000, 50, timerClock);
- CTIMER_SetupPwmPeriod(CTIMER, kCTIMER_Match_2, kCTIMER_Match_1, g_pwmPeriod, g_pulsePeriod , false);
- CTIMER_StartTimer(CTIMER);
复制代码 测试结果正常。
以上为NXP提供的例程中的Ctimer的PWM输出的例子,咱们将在一个空白的工程从0开始创建PWM输出。
二、从零配置Ctimer的PWM输出
1、添加外设
点击“Peripheral drivers”旁边的“+”,选择“Ctimer”,最后确定创建一个外设;
想要得到PWM,分别需要配置定时器和通道信息;
我们看到了一个警告信息,定时器通道没有关联对应的引脚,这种情况我们可以通右键这个警告信息,可以快速进行问题处理:
选择想要关联的引脚就可以了,非常方便。
没有错误以及警告后,更新源代码就可以了,到这里我们就创建了新的外设,以及相关的引脚配置。
2、在主程序中填写如下代码:
- srcClock_Hz = CLOCK_GetCTimerClkFreq(0U);
- PRINTF("srcClock_Hz: %d\n",srcClock_Hz);
- timerClock = 2000000;
- /* Get the PWM period match value and pulse width match value of 20Khz PWM signal with 20% dutycycle */
- CTIMER_GetPwmPeriodValue(20000, 20, timerClock);
- CTIMER_SetupPwmPeriod(CTIMER0, kCTIMER_Match_3, kCTIMER_Match_0, g_pwmPeriod, g_pulsePeriod, false);
- CTIMER_StartTimer(CTIMER0);
复制代码 单路PWM输出效果如下:
在本次的CTimer产生PWM的测试中,主要关注的数据是定时器中的prescaler参数(实际),PWM的pwmPeriod和pulsePeriod,其中定时器中的prescaler要设定的远大于pwmPeriod,理论上越大精度越高。三者关系如下:
- timerClock_Hz = srcClock_Hz/(prescaler + 1U);
- /* Calculate PWM period match value */
- pwmPeriod = (timerClock_Hz / pwmFreqHz) - 1U;
- /* Calculate pulse width match value */
- pulsePeriod = (pwmPeriod + 1U) * (100 - dutyCyclePercent) / 100;
复制代码 接下来再加一路:
添加代码如下:
- CTIMER_GetPwmPeriodValue(20000, 50, timerClock);
- CTIMER_SetupPwmPeriod(CTIMER0, kCTIMER_Match_2, kCTIMER_Match_1, g_pwmPeriod, g_pulsePeriod, f
复制代码 注意两路的的目标频率要一致。
效果如下:
这里可以看到Ctimer输出的双路是边沿对齐的,也无法设置。
三、从零配置SCtimer的PWM输出
创建组件:
定时器基础配置:
需要配置的内容不多,只要配置时钟就好;
通道配置:
可以看到配置你想要的若干通道,在这里遇到了两个问题,一个是配置SCTIMER out 0时连接到P1_4引脚无输出,连接到P2_2则输出正常;另一个就是上图的感叹号问题,要求PWM信号必须被分配到一个初始化的状态,可是并没有相关设置项,我们带着问题进行“更新源代码”,可以看到初始化内容("peripherals.C")中:
- const sctimer_config_t SCT0_initConfig = {
- .enableCounterUnify = true,
- .clockMode = kSCTIMER_System_ClockMode,
- .clockSelect = kSCTIMER_Clock_On_Rise_Input_0,
- .enableBidirection_l = false,
- .enableBidirection_h = false,
- .prescale_l = 0U,
- .prescale_h = 0U,
- .outInitState = (uint8_t)(SCT0_OUTPUT_1 | SCT0_OUTPUT_3),
- .inputsync = 0U
- };
- const sctimer_pwm_signal_param_t SCT0_pwmSignalsConfig[2] = {
- {
- .output = kSCTIMER_Out_0,
- .level = kSCTIMER_HighTrue,
- .dutyCyclePercent = 50U
- },
- {
- .output = kSCTIMER_Out_1,
- .level = kSCTIMER_LowTrue,
- .dutyCyclePercent = 20U
- }
- };
- uint32_t SCT0_pwmEvent[2];
- static void SCT0_init(void) {
- SCTIMER_Init(SCT0_PERIPHERAL, &SCT0_initConfig);
- /* Initialization of state 0 */
- SCTIMER_SetupPwm(SCT0_PERIPHERAL, &SCT0_pwmSignalsConfig[0], kSCTIMER_EdgeAlignedPwm, 20000U, SCT0_CLOCK_FREQ, &SCT0_pwmEvent[0]);
- SCTIMER_StartTimer(SCT0_PERIPHERAL, kSCTIMER_Counter_U);
- }
复制代码 发现相关配置文件已经创建,只是在初始化(SCT0_init(void))中未对有问题的通达进行初始化配置,我们可以通过在外面添加相应的SCTIMER_SetupPwm()重新配置对应的PWM通道。
接下来我们在外部进行对PWM通道进行从新配置:
- sctimer_config_t sctimerInfo;
- sctimer_pwm_signal_param_t pwmParam;
- uint32_t sctimerClock;
- uint32_t event;
- sctimerClock = CLOCK_GetFreq(kCLOCK_BusClk);
- SCTIMER_GetDefaultConfig(&sctimerInfo);
- SCTIMER_Init(SCT0, &sctimerInfo);
- /* Configure first PWM with frequency 24kHZ from first output */
- pwmParam.output = kSCTIMER_Out_0;
- pwmParam.level = kSCTIMER_HighTrue;
- pwmParam.dutyCyclePercent = 50;
- if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 20000U, sctimerClock, &event) == kStatus_Fail)
- {
- return -1;
- }
- /* Configure second PWM with different duty cycle but same frequency as before */
- pwmParam.output = kSCTIMER_Out_1;
- pwmParam.level = kSCTIMER_HighTrue;
- pwmParam.dutyCyclePercent = 20;
- if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 20000U, sctimerClock, &event) == kStatus_Fail)
- {
- return -1;
- }
- SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_U);
复制代码 效果如下:
|
|