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;
}
SAM4E单片机之旅——5、LED呼吸和PWM的更多相关文章
- SAM4E单片机之旅——3、LED闪烁之定时器中断
让一个LED灯闪烁不过瘾,我们应该让这块开发板完成一点更高难度的任务:比如让两个LED灯闪烁. …… 当然了,以我们的现在使用的空循环技术,还是可以实现这点的.但是这样显得略为低端.所以我们使用一个高 ...
- SAM4E单片机之旅——2、LED闪烁之轮询定时器
之前我们使用空循环,达到了延迟的目的,但是这样子的延迟比较不精确.现在就使用实时定时器(RTT)来进行更为精确的计时.RTT虽然不是特别通用,在某些单片机上可能没有,但它较为简单. RTT内部有一个计 ...
- SAM4E单片机之旅——1、LED闪烁之空循环
最近因为导师要写一本关于SAME4单片机的书籍,而我也作为一个嵌入式的初学者看了这本书.现在也让我写写几个小的程序,做做示例.既然写了文档之类的,就发到博客上来吧. 目前关于这芯片能参考的书籍大概就只 ...
- SAM4E单片机之旅——7、LED闪烁之TC中断
RTT主要用做一个全局的定时器,而且不太通用.现在尝试使用一个更为通用的定时器进行定时:定时计数器(Timer Counter, TC). TC提供了广泛的功能,主要可以分为对输入的测量,以及波形的输 ...
- SAM4E单片机之旅——6、LED闪烁之按钮控制
现在试试用按钮控制LED灯……让LED在一个按钮按下时亮起:弹起时灭掉. 主要目的是学习GPIO的输入及中断. 一. 电路 图中的J39-n是几个跳线插座,位置在开发板LCD附近,往下进行前要先确保跳 ...
- SAM4E单片机之旅——4、LED闪烁之PWM
两个LED灯虽然可以闪了,但是总是需要CPU的参与.现在尝试使用一种更为自动化的方法:让脉宽调制(PWM)控制器输出具有一定周期和占空比的方波,以此控制LED灯的亮灭. 一.实现思路 依然使用蓝色和琥 ...
- SAM4E单片机之旅——23、在AS6(GCC)中使用FPU
浮点单元(Floating Point Unit,FPU),是用于处理浮点数运算的单元. 为使用FPU,除了需要启用FPU外,还需要对编译器进行设置,以使其针对浮点运算生成特殊的指令.虽然在Atmel ...
- SAM4E单片机之旅——24、使用DSP库求向量数量积
DSP(Digital Signal Processing,数字信号处理)中会使用大量的数学运算.Cortex-M4中,配置了一些强大的部件,以提高DSP能力.同时CMSIS提供了一个DSP库,提供了 ...
- SAM4E单片机之旅——18、通过AFEC(ADC)获取输入的电压
很多时候,一个电压不仅仅需要定性(高电平或者低电平),而且要定量(了解具体电压的数值).这个时候就可以用到模数转换器(ADC)了.这次的内容是测量开发板搭载的滑动变阻器(VR1)的电压,然后把ADC转 ...
随机推荐
- La 4670 AC自动机(模版)
#include<iostream> #include<cstring> #include<queue> #include<cstdio> #inclu ...
- noip 2010 关押罪犯 二分答案+二分图染色 || 并查集
题目链接 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值&q ...
- hdu 1787(欧拉函数)
GCD Again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- ML | SVM
What's xxx An SVM model is a representation of the examples as points in space, mapped so that the e ...
- ubuntu下某些文件目录
1.#include <stdio.h> 2.#include <stdlib.h> stdio.h和stdlib.h的路径:/usr/include
- 编译lua
http://www.lua.org/ 新建一个 static library 工程,把解压得到的目录下的src子目录中的所有.h和.c文件拷贝到新工程目录下. 工程中删除自动生成的 main.c 文 ...
- 在Debian下安装使用Windows下的字体
转载:http://blog.163.com/lixiangqiu_9202/blog/static/53575037201251224553801/ Debian下的字体不太好看,没有windows ...
- oralce中相关的概念整理
[数据库名] 概念:就是一个数据库的标识,作用等同于我们的身份证的作用,假设一台机器上安装了多个数据库,那么每一个数据库都会有一个数据库名称相应,这些数据库名称在数据库被创建的时候,数据库名称也会被 ...
- 强大的开源网络侦查工具:IVRE
IVRE简介 IVRE(又名DRUNK)是一款开源的网络侦查框架工具,IVRE使用Nmap.Zmap进行主动网络探测.使用Bro.P0f等进行网络流量被动分析,探测结果存入数据库中,方便数据的查询.分 ...
- 基于GPU加速的三维空间分析【转】
基于GPU加速的三维空间分析 标签:supermap地理信息系统gisit 文:李凯 随着三维GIS 的快速发展和应用普及,三维空间分析技术以其应用中的实用性成为当前GIS技术研究的热点领域.面对日益 ...