当前位置: 首页 > news >正文

嵌入式物联网开发(三)如何配置N32G45的TIM实现PWM调光

要改变小功率LED灯的亮度,通常可以通过PWM控制LED电源的通断来实现,N32G452的PWM功能可以通过TIM的比较输出来实现,下面我们通过以下几个步骤来实现输出一个2Khz,占空比从0%-100%可调的PWM波形:

  1. 配置GPIO为TIM的比较输出通道,这里使用的是TIM2-CH2, 对应的是GPIOA_1管脚,需要设置为复用功能
void GPIO_Configuration(void)
{GPIO_InitType GPIO_InitStructure;/* 配置GPIO输出,继电器开关 */GPIO_InitStructure.Pin        = GPIO_PIN_2;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);  GPIO_WriteBit(GPIOB, GPIO_PIN_2, Bit_RESET); // 初始化时默认关灯/* 配置 TIM2-CH2 作为PWM调光输出 */GPIO_InitStructure.Pin        = GPIO_PIN_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}
  1. 使能GPIOA和TIM2及IO复用功能的时钟
void RCC_Configuration(void)
{/* Enable GPIO & AFIO clock */GPIO_APBxClkCmd(RCC_APB2_PERIPH_AFIO, ENABLE);GPIO_APBxClkCmd(RCC_APB2_PERIPH_GPIOA, ENABLE);/* Enable TIM2 clock */RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);
}
  1. 配置TIM2实现PWM输出功能,根据手册,TIM2属于AHB1总线下的设备,其时钟最大是36Mhz,初始化代码也将其配置为了36Mhz,它由144M的HCLK经过4分频而来,当AHB1的分频不是1时,TIM2的时钟为AHB1的2倍,即36M*2 = 72M。
    在这里插入图片描述
/*** @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1* prescalers.*/
static void SetSysClock(void)
{	/* 其他代码略 *//* PCLK1 max 36M */if (SYSCLK_FREQ > 72000000){RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV4;}else if (SYSCLK_FREQ > 36000000){RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV2;}else{RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV1;}/* 其他代码略 */
}

为了实现输出2K的频率,需要进行如下配置

void TIM2_PWM_Init(void)
{/*** 以下配置会在TIM2-CH2通道(GPIOA_1)产生2KHz的PWM输出* 特殊占空比: 当Pulse设置为0时,PWM输出保持为低电平, Pulse=100(>Period)时,PWM持续输出高电平,* 由于这个特性,当关灯或开灯时,不必用切换PWM为GPIO的方式来输出高低电平,直接配置PWM的Pulse即可*/uint16_t PrescalerValue = 0;TIM_TimeBaseInitType TIM_TimeBaseStructure;OCInitType TIM_OCInitStructure;uint16_t CCR2_Val       = 0; // Pulse: 0-100, 初始化时默认0%/* TIM2 clock enable */RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);/* Compute the prescaler value *//*** AHB1的时钟是36Mhz,分频不是1,则TIM2的时钟为AHB1的2倍 * 预分频值 = TIM2_CLK / (2000 * (AAR+1)) - 1 = 72000000 / (2000 * (99+1) ) - 1 = 359*/PrescalerValue = 359; /* Time base configuration */TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);/* 为了方便直接输出高电平,设置Pulse为100即可 */TIM_TimeBaseStructure.Period    = 99;TIM_TimeBaseStructure.Prescaler = PrescalerValue;TIM_TimeBaseStructure.ClkDiv    = 0;TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);   /* PWM1 Mode configuration: Channel1 */TIM_InitOcStruct(&TIM_OCInitStructure);TIM_OCInitStructure.OcMode      = TIM_OCMODE_PWM1;TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;TIM_OCInitStructure.Pulse       = CCR2_Val;TIM_OCInitStructure.OcPolarity  = TIM_OC_POLARITY_HIGH;TIM_InitOc2(TIM2, &TIM_OCInitStructure);TIM_ConfigOc2Preload(TIM2, TIM_OC_PRE_LOAD_ENABLE);TIM_ConfigArPreload(TIM2, ENABLE);/* TIM3 enable counter */TIM_Enable(TIM2, ENABLE);
}

其中TIM2的预分频值PSC及重载值AAR(Period)根据以下公式计算:
在这里插入图片描述
在这里插入图片描述
4. 实现一个动态修改占空比的函数:

static void PWM_Output_Controll(int channel, int value)
{/* 继电器的控制 */if ( value == 0){GPIO_WriteBit(GPIOB, GPIO_PIN_2, Bit_RESET);}else if ( value == 100){GPIO_WriteBit(GPIOB, GPIO_PIN_2, Bit_SET);}else{GPIO_WriteBit(GPIOB, GPIO_PIN_2, Bit_SET);}    /* 修改占空比 */TIM_Enable(TIM2, DISABLE);  /* 先停止定时器 */TIM2->CCDAT2 = value;       /* 修改计数值 */TIM_Enable(TIM2, ENABLE);   /* 重新使能定时器 */
}
  1. 验证测试:
/*** @brief  Main program*/
int main(void)
{/* Init the Logger */Logger_Init();TIM2_PWM_Init();int dimm = 0;while(1){printf("dimm: %d\r\n", dimm);PWM_Output_Controll(0, dimm); HAL_Delay(100);dimm++;dimm %= 101;}return (0);
}

上述代码初始化了TIM2的通道2为比较输出模式,然后每隔100毫秒占空比步进1%,通过观察逻辑分析仪抓取GPIOA_1管脚输出的信号,可以看到由正确的波形产生:
从低电平开始到占空比1%
从低电平开始到占空比1%
占空比50%
在这里插入图片描述
占空比从99%到持续高电平(100%)
在这里插入图片描述

如此,PWM调光的核心功能就实现了。

相关文章:

  • 字符串哈希(算法题)
  • 单片机-STM32部分:8、外部中断
  • 极简远程革命:打破公网桎梏,重塑数字生活新体验
  • Java常用API:深度解析与实践应用
  • React知识框架
  • 用kompose将docker-compose文件转换为K8S资源清单
  • Linux下使用openssh搭建sftp服务
  • A. Row GCD(gcd的基本性质)
  • Linux Shell编程和循环语句
  • Sui Basecamp 2025 全栈出击
  • Spring 是什么?它解决了什么问题?
  • Django之账号登录及权限管理
  • GrassRoot备份项目
  • uniapp项目打包的微信小程序,设置uni-popup type=“bottom“时,底部有空隙
  • Qt实现车载多媒体项目,包含天气、音乐、视频、地图、五子棋功能模块,免费下载源文件!
  • Amazon Redshift 使用场景解析与最佳实践
  • 全连接神经网络学习笔记
  • 学习黑客什么是 ARP
  • AutoGen 框架解析:微软开源的多人 Agent 协作新范式
  • 每日学习:DAY24
  • 逆境之上,万物生长
  • 重庆党政代表团在沪考察,陈吉宁龚正与袁家军胡衡华共商两地深化合作工作
  • 国家卫健委:有条件的二级及以上综合医院要开设老年医学科
  • 教育部、国家发改委联合启动实施教师教育能力提升工程
  • 习近平出席俄罗斯总统举行的欢迎仪式
  • 深入贯彻中央八项规定精神学习教育中央第六指导组指导督导中国工商银行见面会召开