zoukankan      html  css  js  c++  java
  • SAM4E单片机之旅——5、LED呼吸和PWM

    PWM在高频情况下,一个很好的用处就是通过控制占空比来控制输出的功率,比如控制风扇转速、LED灯的亮度等。这次就利用PWM的中断功能,动态改变脉冲的占空比,来实现呼吸灯的效果。

    一、实现思路

    PWM可以选择让计数器在周期结束产生中断(在周期中央对齐时,可能选择在周期中央也产生中断),并且可以在运行的时候动态地调整占空比、周期、极性等属性。所以可以在中断处理函数中动态地改变占空比以改变LED灯的亮度。
    这次也将使用通道0和引脚PA0。

    二、PWM设置

    这里需要用到较高频率的时钟,所以选择使用主时钟经32分频后的时钟(12.5 kHz)。计数器周期为400,即输出脉冲频率为125000/400 = 312.5 Hz。同时需要使能相应的中断。
    PWM的主要配置代码如下:

    #define PERIOD_VALUE    400
    
    /* 时钟选择 */
    PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_MCK_DIV_32;
    /* 启用中断 */
    PWM->PWM_IER1 = PWM_IER1_CHID0;
    /* 周期及占空比 */
    PWM->PWM_CH_NUM[0].PWM_CPRD= PWM_CPRD_CPRD(PERIOD_VALUE);   
    PWM->PWM_CH_NUM[0].PWM_CDTY = PWM_CDTY_CDTY(0); 
    /* 使能中断 */
    NVIC_ClearPendingIRQ(PWM_IRQn);
    NVIC_SetPriority(PWM_IRQn, 0);
    NVIC_EnableIRQ(PWM_IRQn);

    三、PWM中断处理

    在每个周期结束后,会产生一个中断。然后在中断处理函数中,改变占空比。需要注意的是,在PWM使能时,需要通过写入PWM占空比修改寄存器(PWM_CDTYUPD)来改变占空比。默认情况下,该修改在下一个周期生效。 
    为得到更好的效果,可以在两次呼吸之间设置一断间隔。
    注意,需要通过读取PWM_ISR1来拉低产生的中断。中断处理函数在后面的完整代码中贴出。

    附 完整代码

    #include <sam.h>
    
    #define PERIOD_VALUE	400
    #define BREATH_INTERVAL_PERIOD	200    /* 两次呼吸间隔的周期 */
    
    void ConfigPWM(void) 
    {
    	/* PMC 启用
    	 * PWM的ID大于31,需要在PMC_PCER1中启用
    	 */
    	PMC->PMC_PCER1 = 1 << (ID_PWM - 32);
    
    	/* 禁用通道0,以进行配置 */
    	PWM->PWM_DIS = PWM_DIS_CHID0;
    	
    	/* 配置通道0 */
    	PWM->PWM_CH_NUM[0].PWM_CMR =
    			 PWM_CMR_CPRE_MCK_DIV_32	/* 计数器时钟选择为CLKA */
    				;						/* 周期左对齐,先输出低电平,不使用死区发生器 */
    	/* 启用中断 */
    	PWM->PWM_IER1 = PWM_IER1_CHID0;
    
    	PWM->PWM_CH_NUM[0].PWM_CPRD = PWM_CPRD_CPRD(PERIOD_VALUE);   /* 周期 */
    	PWM->PWM_CH_NUM[0].PWM_CDTY = PWM_CDTY_CDTY(0);    /* 占空比,准确来说是阀值 */
    
    	/* 使能中断 */
    	NVIC_ClearPendingIRQ(PWM_IRQn);
    	NVIC_SetPriority(PWM_IRQn, 0);
    	NVIC_EnableIRQ(PWM_IRQn);
     
    	/* 使能 PWM */	
    	PWM->PWM_ENA = PWM_ENA_CHID0;
    }
    
    /* PWM 中断处理函数 */
    void PWM_Handler(void)
    {
    	static uint32_t ul_duty = 0;  /* PWM 占空比*/
    	static uint8_t fade_in = 1;   /* LED 淡入标志 */
    	static uint8_t dark_period = 0;	/* LED 完全暗下来的周期 */
    	
    	/* 读取PWM_ISR1,同时可以拉低中断 */
    	uint32_t events = PWM->PWM_ISR1;
    
    	/* 先确定是否是指定的中断 */
    	if ((events & PWM_ISR1_CHID0) != 0)
    	{
    		if (dark_period != 0)
    		{
    			dark_period--;
    			return;
    		}
    
    		/* 淡入 */
    		if (fade_in)
    		{
    			ul_duty++;
    			if (ul_duty == PERIOD_VALUE)
    			{
    				fade_in = 0;
    			}
    		}
    		else
    		{
    			/* 淡出 */
    			ul_duty--;
    			if (ul_duty == 0)
    			{
    				fade_in = 1;
    				/* LED暗下来一定的周期再淡入 */
    				dark_period = BREATH_INTERVAL_PERIOD;
    			}
    		}
    
    		/* 设置新的占空比 */
    		PWM->PWM_CH_NUM[0].PWM_CDTYUPD = PWM_CDTY_CDTY(ul_duty);
    	}
    }
    
    void ConfigPIO(void) 
    {
    	/* 引脚由外设控制 */
    	PIOA->PIO_PDR = PIO_PA0;
    	/* 选择外设 */
    	/* PIOA选择外设A(将影响PA所有引脚) */
    	PIOA->PIO_ABCDSR[0] = 0;
    	PIOA->PIO_ABCDSR[1] = 0;
    }
    
    int main(void)
    {
    	/* Disable WDT */
    	WDT->WDT_MR = WDT_MR_WDDIS;
    	
    	ConfigPWM();
    	ConfigPIO();
    
    	while (1) {
    	}
    	return 0;
    }
  • 相关阅读:
    JavaScript之DOM文档对象模型--对HTML元素的增删操作
    JavaScript之DOM文档对象模型--对HTML元素的访问操作
    JavaScript之BOM浏览器对象模型-history
    SpringBoot配置自定义日期参数转换器
    SpringMVC参数绑定(未完待续)
    一个简单的SpringBoot入门程序
    四种JavaEE架构简介
    浏览器禁用Cookie后的Session处理
    基础回顾: 关于Session的一些细节
    使用Cookie实现用户商品历史浏览记录
  • 原文地址:https://www.cnblogs.com/h46incon/p/3409321.html
Copyright © 2011-2022 走看看