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

STM32 输出比较输出PWM控制呼吸灯小实验(2种实现 铁头山羊与江协科技)

文章目录

    • 呼吸灯实验
      • 实验目标与原理(铁头山羊)
      • 参数计算
      • 配置IO口
      • 代码编写初始化
    • 江协科技PWM呼吸灯

呼吸灯实验

实验目标与原理(铁头山羊)

  • 实验目标:在面包板上用两颗开发套件包中的 LED(红、蓝)连接定时器一通道一,产生互补 PWM 信号驱动 LED 实现呼吸灯效果。

  • 工作原理:让 LED 亮度连续变化类似正弦函数,将标准正弦函数 y = sin2πt 通过加 1、乘以 0.5 变换到 0 到 1 范围,通过调节 PWM 占空比模拟正弦信号,使 LED 两端电压按此函数变化。

  • 周期设定:PWM 信号周期设为 1 毫秒,通过配置定时器让其输出该周期且占空比按规律变化的 PWM 波。

    我们将占空比设置为这个正弦函数(这样就可以实现呼吸灯的效果),并且假设周期为1ms。

在这里插入图片描述

  • 输出 PWM 波形分析
    • 电路结构:通用定时器输出比较部分电路左边是 CNT 和 CCR 比较结果,右边是输出比较电路,通过 Tim CH1 输出到 GPL 引脚,有四个同样单元分别输出到 CH2、CH3、CH4。
    • 输出模式控制器:输入是 CNT 和 CCR 大小关系,输出是 REF 高低电平,有 8 种模式可通过寄存器配置,如冻结模式可暂停输出,匹配时电平翻转模式可输出频率可调占空比 50% 的 PWM 波形,PWM 模式一和 PWM 模式 2 可输出频率和占空比都可调的 PWM 波形。
    • 工作流程:以 PWM 模式一为例,配置好定时器单元使 CNT 自增,CNT 与 CCR 比较,根据大小关系改变 REF 电平,经极性选择输出到 GPL 口完成 PWM 波形输出,占空比受 CCR 值调控。

参数计算

在这里插入图片描述

配置IO口

先查看要配置CH1和CH1N对应的IO口。

在这里插入图片描述

找到IO口之后,查看GPIO口的配置模式。

在这里插入图片描述

因为标准的正弦函数,频率为1HZ,是使PWM信号的占空比为这个正弦函数。

占空比等于 CRR1 / 周期 ,周期为 1000 ,所以CRR1等于 这个数值。

在这里插入图片描述

代码编写初始化

  • 初始化函数声明:在模板工程的 main.c 文件中声明 app_pwm_init 函数初始化 PWM 波产生。

  • IO 引脚初始化:开启 GPLA 时钟,声明变量设置 PA8 引脚模式为 GPL_mode_AFPP,最大输入速度两兆赫兹,调用 GPO_init 初始化;PB13 初始化代码类似,修改端口等参数。

  • 定时器 1 初始化:开启定时器一时钟 ; 配置 时基单元参数,PSC 设为 71,arr 设为 999,计数方向上计数,RCR 设为 0;开启 arr 寄存器预加载;闭合开关使时基单元工作。

在这里插入图片描述

在这里插入图片描述

  • 输出比较配置:配置输出比较通道一参数,模式选 PWM1,极性都选正,使能正常输出和互补输出开关;闭合 Moe 主开关。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

设置CCR1的值:前面有进行过计算,设置为值之后 调用下面的比较函数就可以了。

在这里插入图片描述

完整的main.c函数

#include "stm32f10x.h"                  // Device header
#include "math.h"
#include "delay.h"
#include "OLED.h"void App_Pwm_Init(void);int arr[11]= {0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
int main(void)
{App_Pwm_Init();OLED_Init();int i = 0;while(1){//		float t = GetTick()* 1.0e-3f;
//		OLED_ShowNum(1, 1, GetTick(), 6);
//		float duty = 0.5* (sin( 2*3.14*t)+1);
//		uint16_t CRR1 = duty * 1000;
//		OLED_ShowNum(1, 1, CRR1, 6);TIM_SetCompare1(TIM1, arr[(i++)%11]);Delay_ms(200);}
}
void App_Pwm_Init(void)
{//1. 配置GPIO口// 开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;//配置 GPIOA - pin8GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);//配置GPIOB - pin13GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);//2. 配置时基单元参数//2.1 开启定时器1时钟信号RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//2.2 配置时基单元参数(TIM)TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Prescaler = 71;TIM_TimeBaseInitStruct.TIM_Period = 999;TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);//2.3 开启自动重载寄存器预加载TIM_ARRPreloadConfig(TIM1, ENABLE);//2.4 开启总开关TIM_Cmd(TIM1, ENABLE);//配置输出比较模块TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//设置互补输出的极性TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High;//设置正常输出的极性TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//使能后面的开关TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable;TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//捕获比较寄存器的初值 设置为0TIM_OCInitStruct.TIM_Pulse = 0;TIM_OC1Init(TIM1, &TIM_OCInitStruct);//3.闭合MOE总开关TIM_CtrlPWMOutputs(TIM1, ENABLE);// 开启比较寄存器预加载TIM_CCPreloadControl(TIM1, ENABLE);
}

江协科技PWM呼吸灯

设计思路:

在这里插入图片描述

  • PWM 模块建立

    • 添加文件:在 hardware 文件夹右键添加名为 PWM 的 c 文件和 h 文件。
    • 文件初始化:在 c 文件中添加 STDM32 的头文件,开始编写 PWM 初始化函数 void PWM init void 。
  • PWM 初始化步骤

    • 开启时钟:通过 RCC 开启 TIM 外设和 GPIO 外设的时钟。
    • 配置时机单元:包括时钟源选择和时基单元配置,可参考之前定时中断的代码进行复制修改。
    • 配置输出比较单元:使用 Tim OC1EMIT 等四个函数配置输出比较模块,用 Tim OC struct init 给输出比较结构体赋默认值,设置输出比较模式、极性、使能等参数。(一般有的参数这个模块中没有,可以使用这个结构体初始化函数,就如时基单元结构体中定时器一为高级定时器,有个功能其他定时器没有,就不需要配置,但是如果为高级定时器使用就会出现问题)
    • 配置 GPIO:将 PWM 对应的 GPIO 口初始化为复用推挽输出,根据引脚定义表确定 PWM 与 GPO 的对应关系。
    • 运行控制:启动计数器,输出 PWM。
  • 库函数介绍

    • 输出比较配置函数:Tim OC1init 等四个函数用于配置输出比较模块,Tim OC struct init 用于给输出比较结构体赋默认值。
    • 其他小功能函数
      • TIM_ForcedOC1Config 1234 等函数用于配置强制输出模式等小功能,一般了解即可。
      • TIM_OC1PreloadConfig 输出比较函数预加载功能配置
      • TIM_OC1FastConfig配置定时器的输出比较快速模式
      • TIM_ClearOC1Ref 清除定时器通道 1 的参考信号(OC1REF)状态。该函数主要用于高级定时器(如 TIM1、TIM8)的互补输出控制,在故障处理或特定应用场景下需要手动清除参考信号时使用。
      • TIM_OC1NPolarityConfig 高级定时器互补通道的极性 TIM_OC1PolarityConfig 正常模式的极性
      • TIM_GetCapture1 会将当前计数器的值锁存到捕获寄存器(CCR1)中。TIM_GetCapture1 函数的作用就是读取这个锁存值,从而计算外部信号的时间参数 就是上升沿或者下降沿时的捕获数据可以用来计算PWM脉宽 和 频率等数据
    • 运行更改参数函数:TIM_SetCompare11234 这四个函数用于单独更改 CCR 寄存器值,运行时更改占空比需要用到,较为重要。
  • 代码编写

    • 实际单元初始化:复制定时器定时中断工程的初始化代码,去掉打开中断和配置 NV IC 的部分,保留启动定时器部分。
    • 输出比较单元初始化:使用 Tim OCE init 函数初始化 PA0 口对应的第一个输出比较通道,给结构体变量赋初始值并配置相关参数。
    • GPR 初始化:复制 LED 点 c 文件的初始化代码,更改 GPL PIN 和 GPL 模式为复用推挽输出。
    • 设置 PWM 参数:根据公式计算并设置 ARR、PSC 和 CCR 参数,产生特定频率、占空比和分辨率的 PWM 波形。
    • 验证参数:通过示波器采集波形验证参数设置是否正确,调节 CCR 值可改变占空比和 LED 亮度。
    • 实现呼吸灯效果:封装 Tim set compare 一函数,在主循环中通过不断改变 CCR 值实现 LED 呼吸灯效果。
  • 引脚重映射

    • 开启时钟:使用 AFIO 进行引脚重映射,需先开启 AFIO 的时钟。

    • 重映射配置:使用 gplo pin remap config 函数进行重映射配置,根据手册选择合适的重映射方式,如将 Tim 2 的 CG1 从 PA0 挪到 PA15 可选择部分重映射一或完全重映射。

    • 解除调试端口复用:若重映射引脚是调试端口,需使用 GPIO PIN remap configure 函数的相关参数 如果引脚默认有其他功能解除调试端口复用,下面几个函数使用需谨慎。

      • 第一个函数 关闭JTRST调试 使用后 PB4变为正常的Io口
      • 第二个 关闭 JTAG 使用后 PA15 PB3 Pb4 变为正常的Io口
      • 第三个 关闭所有调试功能 SWD 和 JTAG 调试端口全部解除 就没有调试功能 下载之后就没有调试端口 ,之后就不能使用STLink下载进去程序 就要使用串口,下载有调试端口的程序 才可以恢复

在这里插入图片描述

  • 验证重映射:编译下载代码,验证引脚重映射是否成功,成功后 PA0 的呼吸灯不亮,PA15 接上 LED 可实现呼吸灯效果 。

    // PWM.c
    #include "stm32f10x.h"                  // Device header
    void Pwm_Init(void)
    {//配置时基单元和比较输出//定时器2在总线1上RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//将定时器配置为 内部时钟 ,也可以不写 默认为内部时钟TIM_InternalClockConfig(TIM2);//配置时钟选择模式为 内部时钟模式TIM_InternalClockConfig(TIM2);//配置时基单元结构体TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;//滤波的原理是固定f的频率下进行猜样,如果连续N个采样点都相同就说明输入稳定,//如果不相同就说明不稳定就会进行处理,f的来源有两个 内部时钟直接而来,一个就是经过分频器分频来//所以和时基单元关系不大TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//这里要配置 1KHZ 占空比为50% 频率为1%的PWM波形TIM_TimeBaseInitStruct.TIM_Period = 100-1;	// ARRTIM_TimeBaseInitStruct.TIM_Prescaler = 720-1;  // PSCTIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);//TIM_TimeBaseInit 会触发一次update事件 将值写入,所以函数过后将中断标志位清除TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//开始时钟使能TIM_Cmd(TIM2, ENABLE);//配置比较输出模块TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);//配置比较输出模式TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; //ccr 比较器的值 后面会变化 所以配置为0TIM_OCInitStruct.TIM_Pulse = 0;  //CCRTIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;TIM_OC1Init(TIM2, &TIM_OCInitStruct);TIM_CCPreloadControl(TIM2, ENABLE);//配置GPIo口 查看引脚 对应GPIo A0//配置GPIO口 定时器2的ETR外部时钟模式2 的gpio引脚映射是gpioA0RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;//查看Io配置 需要将io口配置为 推挽复用输出GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);
    }void Pwm_compare(uint16_t compare)
    {TIM_SetCompare1(TIM2, compare);
    }
    
    //main.c
    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "OLED.h"
    #include "Pwm.h"
    uint16_t i;
    int main(void)
    {OLED_Init();Pwm_Init();while(1){//周期为100for(i = 0; i < 100; i++){Pwm_compare(i);Delay_ms(20);}//周期为100for(i = 0; i < 100; i++){Pwm_compare(100-i);Delay_ms(20);}}
    }
    

相关文章:

  • 掌阅iReader新形态墨水屏Tango发布:科技与美学共舞,开启灵动阅读新体验
  • HTTP请求全链路剖析:请求头、XHR与状态码的实战指南
  • 8.Java 8 日期时间处理:从 Date 的崩溃到 LocalDate 的优雅自救​
  • ADS学习笔记(二) 交流小信号仿真
  • 2025最新智能优化算法:野燕麦优化算法(Animated Oat Optimization Algorithm, AOO),MATLAB代码
  • HTTP协议版本的发展(HTTP/0.9、1.0、1.1、2、3)
  • 黑马点评-分布式锁Lua脚本
  • 进阶-自定义类型(结构体、位段、枚举、联合)
  • Lua基础语法
  • 在Windows平台基于VSCode准备GO的编译环境
  • Mustache 模板引擎详解_轻量、跨语言、逻辑无关的设计哲学
  • 一文讲透golang channel 的特点、原理及使用场景
  • 正则表达式:字符串模式匹配的利器
  • 历年华南理工大学保研上机真题
  • 什么是前端工程化?它有什么意义
  • 并发编程(6)
  • linux学习第15天(dup和dup2)
  • GO 语言进阶之 进程 OS与 编码,数据格式转换
  • Docker(零):本文为 “Docker系列” 有关博文的简介和目录
  • 二叉树--oj1
  • 电影网站app怎么做的/刷赞网站推广永久
  • 平湖网站设计/百度文章收录查询
  • 网站优化建设苏州/做公司网页
  • 苏州市工业园区规划建设局网站/怎么把平台推广出去
  • 金华网站建设方案开发/优化seo教程
  • 广州一起做网站/门户网站软文