自学S32K144(6)————PWM

1PWM外设配置流程

1.1进入PWM外设配置界面

双击Components >> 双击 ftm_pwm(灵活定时器模块–脉宽调制)
在这里插入图片描述

1.2进入配置界面

双击新出现的组件文件夹,进入配置界面
在这里插入图片描述

1.3部分配置选项介绍

1.3.1 定时器外设相关配置

在这里插入图片描述

1.3.2 pwm相关配置介绍

在这里插入图片描述

2PWM小实验

本次实验使用FTM0的四个通道输出PWM波控制四路小灯
结合之前学习的adc和按键输入
实现调整滑动变阻器控制小灯的亮灭
通过按键调整PWM的占空比和频率

2.1硬件电路

FTM0_CH1-PTD16-LEDG_1,
FTM0_CH0-PTD15-LEDR_2,
FTM0_CH3-PTD1-LEDY_3,
FTM0_CH2-PTD0-LEDB_4
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用的按键
key1-PTC12,key2-PTC13
在这里插入图片描述
在这里插入图片描述
使用到的adc通道和变阻器
ADC0-CH2
在这里插入图片描述
在这里插入图片描述

2.2pwm,ADC详细配置

通道极性高电平有效、占空比50%
在这里插入图片描述
adc配置
在这里插入图片描述
在这里插入图片描述

2.3pinmux配置及注意事项

若通道对应管脚已经被设置为其他功能如gpio,需恢复默认状态。
确认没有其他功能占用后,将io从新映射为定时器输出。
在这里插入图片描述
key——io配置
在这里插入图片描述
在这里插入图片描述

2.4 使用到的函数及参数介绍

(gpio和adc函数不在此赘述)
定时器外设初始化:
uint32_t instance:定时器实例即要使用的定时器
const ftm_user_config_t * info :定时器配置结构体
ftm_state_t *state:定时器结构体

status_t FTM_DRV_Init(uint32_t instance,const ftm_user_config_t * info, ftm_state_t *state);

PWM初始化:
uint32_t instance:pwm实例即要使用的定时器
const ftm_pwm_param_t * param:PWM配置结构体

status_t FTM_DRV_InitPwm(uint32_t instance,const ftm_pwm_param_t * param)

PWM通道更新函数:
uint32_t instance:pwm实例即要使用的定时器
uint8_t channel:需要更新的通道
ftm_pwm_update_option_t typeOfUpdate:通道变更类型
uint16_t firstEdge:占空比(第一翻转边沿)
uint16_t secondEdge:第二翻转边沿(用于中心对齐模式)
bool softwareTrigger:是否软件触发更新(true/flase)

status_t FTM_DRV_UpdatePwmChannel(uint32_t instance,uint8_t channel, ftm_pwm_update_option_t typeOfUpdate, uint16_t firstEdge,uint16_t secondEdge,bool softwareTrigger);

参数详解
参数 类型 说明
instance uint32_t FTM模块实例号,如 0 对应 FTM0,1 对应 FTM1。
typeOfUpdate ftm_pwm_update_option_t PWM对齐模式:
newValue uint32_t 新的PWM周期值:写入 FTMx_MOD 寄存器,决定PWM频率。
计算公式:
• 边沿对齐:PWM频率 = FTM时钟 / (newValue + 1)
• 中心对齐:PWM频率 = FTM时钟 / (2 * (newValue + 1))
softwareTrigger bool • true:立即更新周期值(写入 FTMx_MOD)
• false:等待硬件触发(如下一个计数器溢出)

status_t FTM_DRV_UpdatePwmPeriod(uint32_t instance,ftm_pwm_update_option_t typeOfUpdate,uint32_t newValue,bool softwareTrigger)

2.4具体代码

/* ###################################################################
**     Filename    : main.c
**     Processor   : S32K1xx
**     Abstract    :
**         Main module.
**         This module contains user's application code.
**     Settings    :
**     Contents    :
**         No public methods
**
** ###################################################################*/
/*!
** @file main.c
** @version 01.00
** @brief
**         Main module.
**         This module contains user's application code.
*/         
/*!
**  @addtogroup main_module main module documentation
**  @{
*/         
/* MODULE main */


/* Including necessary module. Cpu.h contains other modules needed for compiling.*/
#include "Cpu.h"

  volatile int exit_code = 0;

/* User includes (#include below this line is not maintained by Processor Expert) */
#include "delay.h"



#define ADC_VREFH   3.3f    // 最大参考电压
#define ADC_VREFL   0.0f    // 最小参考电压
float adcValue;             // 变阻器电压
uint16_t adcreval;          // 实际采样数值
uint16_t adcmax;            // 最大量程实际数值
// 定义按键引脚和掩码
#define KEY1_PIN_MASK    (1U << 12)  // PTC12
#define KEY2_PIN_MASK    (1U << 13)  // PTC13
#define DEBOUNCE_DELAY_MS 20         // 去抖动延时

// 按键检测函数(非阻塞式)
int Check_Keys(void) {
    static uint8_t key_pressed = 0; // 记录当前按下的按键(0:无, 1:KEY1, 2:KEY2)

    // 读取当前所有按键状态
    uint32_t pinState = PINS_DRV_ReadPins(PTC);

    // 检测 KEY1 (PTC12)
    if ((pinState & KEY1_PIN_MASK) && (key_pressed != 1)) {
        delay_ms(DEBOUNCE_DELAY_MS);
        if (PINS_DRV_ReadPins(PTC) & KEY1_PIN_MASK) {
            key_pressed = 1;
            return 1; // 返回 KEY1 按下
        }
    }

    // 检测 KEY2 (PTC13)
    if ((pinState & KEY2_PIN_MASK) && (key_pressed != 2)) {
        delay_ms(DEBOUNCE_DELAY_MS);
        if (PINS_DRV_ReadPins(PTC) & KEY2_PIN_MASK) {
            key_pressed = 2;
            return 2; // 返回 KEY2 按下
        }
    }

    // 检测按键释放
    if (!(pinState & (KEY1_PIN_MASK | KEY2_PIN_MASK))) {
        key_pressed = 0; // 重置状态
    }

    return 0; // 无按键按下
}

float read_adc_CH2(void)
{
    ADC_DRV_ConfigChan(INST_ADCONV1, 0, &adConv1_ChnConfig0);
    // 读取ADC2通道的值
    ADC_DRV_WaitConvDone(INST_ADCONV1);
    ADC_DRV_GetChanResult(INST_ADCONV1, 0, (uint16_t * const)&adcreval);
    adcValue = ((float)adcreval / adcmax) * (ADC_VREFH - ADC_VREFL); // 计算电压值
    return adcValue;
}


void FTM0_Dutycycle_Output(int chn, int value)  // 设置PWM占空比
{
	FTM_DRV_UpdatePwmChannel(INST_FLEXTIMER_PWM1,chn,FTM_PWM_UPDATE_IN_DUTY_CYCLE,value * 327.68,0,true);
}

  void FTM0_Period_Output(int tick) // 设置PWM周期
  {
	FTM_DRV_UpdatePwmPeriod(INST_FLEXTIMER_PWM1,FTM_PWM_UPDATE_IN_TICKS,tick,true);
}
/*! 
  \brief The main function for the project.
  \details The startup initialization sequence is the following:
 * - startup asm routine
 * - main()
*/
int main(void)
{
  /* Write your local variable definition here */
  float adcValue1; // 变阻器电压
  int Duty_precent_adc;          // adc获得的要修改pwm占空百分比
  int Duty_precent_adc_last;      // 上次的pwm占空百分比
  int key_Duty = 0;
  int key_Period = 1000;
  int key_num; // 按键值
	int MCU_Freq;
	ftm_state_t ftmStateStruct1;
  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of Processor Expert internal initialization.                    ***/

  /* Write your code here */
  /* For example: for(;;) { } */
    //根据配置确定阈值
    if(adConv1_ConvConfig0.resolution == ADC_RESOLUTION_8BIT)
    {
        adcmax = (1 << 8);        
    }
    else if(adConv1_ConvConfig0.resolution == ADC_RESOLUTION_10BIT)
    {
        adcmax = (1 << 10);
    }
    else if(adConv1_ConvConfig0.resolution == ADC_RESOLUTION_12BIT)
    {
        adcmax = (1 << 12);
    }
	CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
	CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
	MCU_Freq = delay_init();//初始化delay函数

	FTM_DRV_Init(INST_FLEXTIMER_PWM1, &flexTimer_pwm1_InitConfig,&ftmStateStruct1); // 初始化FTM0
	FTM_DRV_InitPwm(INST_FLEXTIMER_PWM1, &flexTimer_pwm1_PwmConfig);  // 初始化PWM
  PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr); // 初始化引脚
  ADC_DRV_ConfigConverter(INST_ADCONV1, &adConv1_ConvConfig0);	//	配置ADC0
  ADC_DRV_AutoCalibration(INST_ADCONV1);	// 自校验

  while (1)
  {
          // 读取ADC2通道的值
      adcValue1 = read_adc_CH2();
          //放大浮点类型变为int型
      Duty_precent_adc  = (int)((adcValue1 / 3.3) * 100 + 0.5);

      if(Duty_precent_adc != Duty_precent_adc_last) // 如果当前值和上次值不一样,才更新pwm占空比
      {
          FTM0_Dutycycle_Output(0, Duty_precent_adc); // 更新pwm占空比
          FTM0_Dutycycle_Output(1, Duty_precent_adc); // 更新pwm占空比
          FTM0_Dutycycle_Output(2, Duty_precent_adc); // 更新pwm占空比
          FTM0_Dutycycle_Output(3, Duty_precent_adc); // 更新pwm占空比
          Duty_precent_adc_last = Duty_precent_adc; // 更新上次值
      }
      key_num = Check_Keys(); // 读取按键值
      if(key_num == 1) // 按键1按下
      {
        //百分比限制在0 - 100之间
          key_Duty += 10; // 增加10%
          if(key_Duty > 100)
          {
              key_Duty = 0;
          }
          FTM0_Dutycycle_Output(0, key_Duty); // 更新pwm占空比
          FTM0_Dutycycle_Output(1, key_Duty); // 更新pwm占空比
          FTM0_Dutycycle_Output(2, key_Duty); // 更新pwm占空比
          FTM0_Dutycycle_Output(3, key_Duty); // 更新pwm占空比
          key_num = 0; // 清除按键值
      }
      else if(key_num == 2) // 按键2按下
      {
          key_Period += 1000; // 增加10%
          if(key_Period > 10000)
          {
              key_Period = 0;
          }
          FTM0_Period_Output(key_Period); // 设置PWM周期
          key_num = 0; // 清除按键值
      }
  }
  

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;) {
    if(exit_code != 0) {
      break;
    }
  }
  return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

void SysTick_Handler(void) {

}
/* END main */
/*!
** @}
*/
/*
** ###################################################################
**
**     This file was created by Processor Expert 10.1 [05.21]
**     for the NXP S32K series of microcontrollers.
**
** ###################################################################
*/

### S32K344 微控制器 PWM 配置与使用 S32K344 是一款基于 ARM Cortex-M 的高性能微控制器,广泛应用于汽车电子和其他嵌入式领域。其脉宽调制 (PWM) 功能由 FlexTimer 模块实现,该模块提供了丰富的功能来满足不同的应用场景需求。 #### 1. PWM 基本原理 PWM(Pulse Width Modulation)是一种通过调节信号占空比来控制功率输出的技术。在 S32K344 中,FlexTimer 模块可以被配置为多种工作模式,其中包括边沿对齐和中心对齐的 PWM 输出模式[^4]。 #### 2. FlexTimer 模块概述 S32K344 提供多个 FlexTimer 实例用于生成 PWM 波形。这些实例可以通过寄存器编程灵活地调整频率、占空比以及其他参数。以下是主要涉及的寄存器及其作用: - **MOD 寄存器**: 定义计数器的最大值,决定了 PWM 的周期。 - **CNT 寄存器**: 当前计数值,通常不需要手动设置,在硬件上自动更新。 - **CnV 寄存器**: 设置比较匹配值,决定占空比。 - **SC 寄存器**: 控制启动/停止以及定时器的工作模式。 以下是一个简单的初始化代码示例,展示如何配置 FlexTimer 来生成基本的 PWM 波形: ```c #include "s32k344.h" void FTM_Init(void){ SIM->SCGC |= SIM_SCGC_FTM0_MASK; // Enable clock gate for FTM0 FTM0_MOD = 999; // Set period to 1ms at 1MHz timer base frequency. FTM0_C0SC &= ~FTM_CnSC_CHF_MASK; FTM0_C0SC |= FTM_CnSC_MSA(1); // Select Edge-Aligned PWM mode. FTM0_CNTIN = 0; // Initialize counter value to zero. FTM0_SC |= FTM_SC_CLKS(1); // Select internal clock source divided by prescaler. } int main(){ FTM_Init(); while(1); } ``` 上述代码片段展示了如何启用 FTM0 并将其配置为边缘对齐的 PWM 工作模式。其中 `FTM0_MOD` 和 `FTM0_C0V` 分别定义了波形的周期和占空比[^5]。 #### 3. 使用注意事项 当利用 S32K344 进行 PWM 应用开发时需要注意以下几点: - 确保正确分配外设时钟源并使能相应的时钟门控位。 - 如果需要更高的分辨率,则应合理选择预分频系数以降低基础时钟频率。 - 对于多通道同步操作场景下,可能还需要额外考虑死区时间插入等功能的支持情况[^6]。 #### 4. 数据类型的声明 对于某些特定场合下的数据处理或者驱动程序编写过程中可能会涉及到只读型变量的操作。此时可参照如下方式来进行相应类型定义以便后续引用: ```c typedef volatile const uint32_t ro_u32; typedef volatile const uint16_t ro_u16; typedef volatile const uint8_t ro_u8; ``` 以上代码片段遵循了类似的命名约定原则,即通过添加前缀 'ro_' 表明此类对象仅允许作为输入参数参与运算而不应该尝试修改它们的内容[^7]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值