STM32之呼吸灯实验

首先,我想引用一下在一片博文里 看到 的一段话,写的很详细,

首先来说,你要使用PWM模式你得先选择用那个定时器来输出PWM吧!除了TIM6、TIM7这两个普通的定时器无法输出PWM外,其余的定时器都可以输出PWM,每个通用定时器可以输出4路PWM,高级定时器TIM1、TIM8每个可输出7路PWM,这里为了方便起见,我们选择与实验相同的TIM3的通道2来说明。选好定时器及通道后,下一步就是要使能定时器的时钟,根据需要看看是否需要重映射IO,然后就是配置输出PWM的IO及定时器,到这里原子的视频及例程都有详细的介绍,这里只需要提一点有些网友疑惑的TIM_TimeBaseStructure.TIM_ClockDivision = 0;这句话是什么作用?其实仔细看过技术手册后发现这句话与PWM输出实验其实是没关系的,这句话是设置定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分频比例的(与输入捕获相关),0表示滤波器的频率和定时器的频率是一样的。至于其余部分,我就不再赘述。

那么,下面就贴上我自己的代码

这个代码可是我改了一天的结果啊。。。。

/*****************************************
利用pwm控制led亮度,
其实我们看到的是灯在呼吸,实际上灯是一直在以很高的频率在闪烁,每次闪烁的亮度都不一样,越来越亮,或者暗
由于人的视觉暂留效应,我们看到灯一直在亮,而且亮度在渐变。

日期:2016.2.25

********************************************/

#include "stm32f10x.h"

/* LED亮度等级 PWM表 */
uint8_t indexWave[] = {1,1,2,2,3,4,6,8,10,14,19,25,33,44,59,80,
    107,143,191,255,255,191,143,107,80,59,44,33,25,19,14,10,8,6,4,3,2,2,1,1};

//函数申明

        void Init_LED(void);
        void NVIC_Config_PWM(void);
        void Init_TIMER(void);
        void Init_PWM(void);
        void Delay_Ms(uint16_t time);
        void Delay_Us(uint16_t time); 

int main(void)
{
            SystemInit();                    //系统时钟配置

            Init_LED();                        //LED初始化
            NVIC_Config_PWM();
            Init_TIMER();                    //定时器初始化
            Init_PWM();            //PWM初始化设置
            GPIO_SetBits(GPIOG,GPIO_Pin_14);    // LED D2 输出为高

            while(1);

}

void Init_LED(void)
{
      GPIO_InitTypeDef GPIO_InitStructure;                    //定义一个GPIO结构体变量

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD| RCC_APB2Periph_GPIOG |RCC_APB2Periph_AFIO,ENABLE);
                                                            //使能各个端口时钟,重要!!!

      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_14;             //配置LED D2端口挂接到PG14端口
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;           //通用输出推挽
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;           //配置端口速度为50M
      GPIO_Init(GPIOG, &GPIO_InitStructure);                       //将端口GPIOD进行初始化配置

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 ;             //配置LED D5端口挂接到13端口
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;               //复用功能输出推挽,这是重映射必要地,AF表示复用
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;           //配置端口速度为50M
      GPIO_Init(GPIOD, &GPIO_InitStructure);                       //将端口GPIOD进行初始化配置

      GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);            //将定时器4通道2重映射到PD13引脚,重要!!
}                                                    //我看很多资料都是这样映射的

//还是野火比较专业,人的吸气呼气通常用时为3秒,算出来是这样的
//TIM_BaseInitStructure.TIM_Period = 256-1;
//TIM_BaseInitStructure.TIM_Prescaler = 2000-1; 

void Init_TIMER(void)
{

    TIM_TimeBaseInitTypeDef     TIM_BaseInitStructure;            //定义一个定时器结构体变量

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);       //使能定时器4,重要!!

//    TIM_DeInit(TIM4);                                          //将TIM4定时器初始化位复位值

//    TIM_InternalClockConfig(TIM4);                                      //配置 TIM4 内部时钟

    //TIM_BaseInitStructure.TIM_Period = 7200-1;         //设置自动重载寄存器值为最大值    0~65535之间  1000000/1000=1000us=1ms
                                                                          //TIM_Period(TIM1_ARR)=7200,计数器向上计数到7200后产生更新事件,
                                                                       //计数值归零 也就是 1MS产生更新事件一次

    TIM_BaseInitStructure.TIM_Period = 256-1;

    TIM_BaseInitStructure.TIM_Prescaler = 2000-1;  //自定义预分频系数为0,即定时器的时钟频率为72M提供给定时器的时钟    0~65535之间

    TIM_BaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割为0

    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;   //TIM向上计数模式 从0开始向上计数,计数到1000后产生更新事件

    TIM_TimeBaseInit(TIM4, &TIM_BaseInitStructure);         //根据指定参数初始化TIM时间基数寄存器    

     TIM_ARRPreloadConfig(TIM4, ENABLE);       //使能TIMx在 ARR 上的预装载寄存器 

    TIM_Cmd(TIM4, ENABLE);         //TIM4总开关:开启 

    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);    //使能定时器中断

    NVIC_Config_PWM();   //配置中断优先级

}

void Init_PWM()
{
    TIM_OCInitTypeDef  TIM_OCInitStructure;                    //定义一个通道输出结构

    TIM_OCStructInit(&TIM_OCInitStructure);                    //设置缺省值

    TIM_OCInitStructure.TIM_Pulse = 0;             //设置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%
                                                                        //PWM的输出频率为Fpwm=72M/7200=1Mhz;  

    /* 下面五句话就把PWM 基本上配置完成,再加上上面定时器的使能,TIM_Cmd(TIM4,ENABLE)   */

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;           //PWM 模式 1 输出     ,

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;    //使能输出状态  需要PWM输出才需要这行代码

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;    //TIM 输出比较极性高 ,就是开始    计数到ccr之前都是high,因为这里的led是正逻辑点亮

  TIM_OC2Init(TIM4, &TIM_OCInitStructure);              //根据参数初始化PWM寄存器 ,使能通道CCR2   

    TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);           //使能 TIMx在 CCR2 上的预装载寄存器,很关键和容易遗漏的一部

  //TIM_CtrlPWMOutputs(TIM4,ENABLE);                          //设置TIM4 的PWM 输出为使能  

}

void NVIC_Config_PWM(void)      //配置嵌套向量中断控制器NVIC
{     

      NVIC_InitTypeDef NVIC_InitStructure;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    //设置中断优先级分组2

        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;    //设定中断源为PC13

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    //中断占优先级为0

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    //副优先级为0

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    //使能中断

        NVIC_Init(&NVIC_InitStructure);    //根据参数初始化中断寄存器

}

void TIM4_IRQHandler(void)    //中断入口函数
{
    static uint8_t pwm_index = 0;            //用于PWM查表
    static uint8_t period_cnt = 0;        //用于计算周期数

    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)    //TIM_IT_Update
     {
            period_cnt++;
            if(period_cnt >= 10)                                        //若输出的周期数大于10,输出下一种脉冲宽的PWM波,在这里野火说他也不知道为什么大于10
            {

                TIM4->CCR2 = indexWave[pwm_index];    //根据PWM表修改定时器的比较寄存器值
                pwm_index++;                                                //标志PWM表的下一个元素

                if( pwm_index >=  40)                                //若PWM脉冲表已经输出完成一遍,重置PWM查表标志
                {
                    pwm_index=0;
                }

                period_cnt=0;                                                //重置周期计数标志
        }

        TIM_ClearITPendingBit (TIM4, TIM_IT_Update);    //必须要清除中断标志位

    }
}

    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: Delay_Ms_Ms
** 功能描述: 延时1MS (可通过仿真来判断他的准确度)
** 参数描述:time (ms) 注意time<65535
** 作   者: Dream
** 日   期: 2011年6月20日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void Delay_Ms(uint16_t time)  //延时函数
{
    uint16_t i,j;
    for(i=0;i<time;i++)
          for(j=0;j<10260;j++);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: Delay_Ms_Us
** 功能描述: 延时1us (可通过仿真来判断他的准确度)
** 参数描述:time (us) 注意time<65535
** 作   者: Dream
** 日   期: 2011年6月20日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void Delay_Us(uint16_t time)  //延时函数
{
    uint16_t i,j;
    for(i=0;i<time;i++)
          for(j=0;j<9;j++);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
End:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
时间: 2024-12-19 02:49:14

STM32之呼吸灯实验的相关文章

PWM呼吸灯实验

PWM室Pulse Width Modulation 的缩写,脉冲宽度调制,利用微处理器的数字输出来对模拟电路进行控制 PWM是一种对模拟信号电平进行数字编码的方法.通过高分率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码,PWM信号仍是数字的 在模拟电路中,模拟信号的值可以连续进行变化,在时间和值的幅度上都几乎没有限制,基本上可以取任何实数值,输入与输出也呈线性变化.所以在模拟电路中,电压和电流可直接用来进行控制对象,例如家用电器设备中的音量开关控制.采用卤素灯泡灯具的亮

STM32呼吸灯

使用STM32开发板和mbed平台实现的一个呼吸灯.材料,LED灯,电阻,STM32开发板. 先上一张效果图. 背景: 我们之前设置GPIO口使用了DigitalOut,数字信号输出.只能是GPIO口为0或1两个值.在LED上体现的即是灭和亮.然而现实世界大量的信号都是模拟信号,如温度.声音.加速度等.百度上:“模拟信号是指信息参数在给定范围内表现为连续的信号. 或在一段连续的时间间隔内,其代表信息的特征量可以在任意瞬间呈现为任意数值的信号.” 理论知识(可以跳过): 模拟信号即可以简单理解为,

好玩的WPF第二弹:电子表字体显示时间+多彩呼吸灯特效button

我们先来看看Quartz MS字体动态显示系统时间的效果,难度相较于上一篇也要简单很多. 首先是定义一个TextBlock例如以下. <Grid> <TextBlock Name="tBlockTime" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="68" Foreground="Green"/>

(原创)用Verilog实现一个参数化的呼吸灯(Verilog,CPLD/FPGA)

1.Abstract     观察到一个有趣的现象,每当把Apple笔记本合上的时候,那个白色的呼吸灯就会反复地由暗渐明,然后又由明渐暗,乍一看就像Apple笔记本在打盹休息一样,十分可爱!于是突发奇想,要不用Verilog也写一个吧,资源也不需要太多,一个LED灯就可以了.为了使用方便,可以把它做成参数化的,可以根据时常进行参数调节:深睡.浅睡跟清醒的时候呼吸频率似乎是不一样的-     下面就来分析和实践一下. 2.Content   2.1 理论分析     根据上述描述的现象,仔细分析一

NE555-DIY呼吸灯的电路图

NE555设计的呼吸灯电路图 再提供一个LM358设计的呼吸灯电路图.

nrf51822之PWM呼吸灯程序

额外链接: 1.JLink-SWD烧写之引脚定义:http://www.openedv.com/posts/list/1747.htm 2.百度文库c语言之PWMhttp://wenku.baidu.com/link?url=2QeCZppvhH81D4OYAyi9eEDP8Sk0p0OQhPKPfo0OXWiWZ5PxBvSMXtP8ejxZw-sxrSOGwrFj3K3q2ewwkM_vAQlk-QMyWnD1eVuLNaANxZm 3.菜农M0助学板PWM呼吸灯小练(寄存器操作方式):ht

CSS 实现按钮及线呼吸灯效果

1. [代码]style    view sourceprint?01<style>02            body{03                font-family:'Segoe UI Light','Segoe UI',Arial,'微软雅黑',sans-serif;04                font-size: 20px;05                color:#333333;06 07            }08            .breath

STM8S PWM 应用 呼吸灯

//主功能接受:使用MCU STM8S105C6 的PWM通道2 PC2 来做呼吸灯 已经验证OK,呵 //呵,这个PWM设置刚开始用还是有点麻烦,因为是自己摸索,花点时间,还是攻克了 . //所用子函数都是调用STM8S的库函数stm8s_tim.c 中的. 宏定义: //分频宏 //计数器的时钟频率(fCK_CNT)等于fCK_PSC/( PSCR[15:0]+1). #define TIM1_PRESCALER_1 ((u16)0x00) #define TIM1_PRESCALER_2

PWM(脉宽调制)——LED特效呼吸灯设计

简述PWM PWM--脉宽调制信号(Pulse Width Modulation),它利用微处理器的数字输出来实现,是对模拟电路控制的一种非常有效的技术,广泛应用于测量.通信.功率控制与变化等许多领域. LED特效呼吸灯原理 采用pwm的方式,在固定的频率下,采用占空比的方式来实现LED亮度的变化.占空比为0,LED灯不亮,占空比为100%,则LED灯最亮.所以将占空比从0到100%,再从100%到0不断变化,就可以实现LED灯实现特效呼吸. 设计思路.框图 变亮:当cnt2 < cnt3时为高