两个LED灯虽然可以闪了,但是总是需要CPU的参与。现在尝试使用一种更为自动化的方法:让脉宽调制(PWM)控制器输出具有一定周期和占空比的方波,以此控制LED灯的亮灭。

一、实现思路


依然使用蓝色和琥珀色的LED灯。开发板上能启用四个PWM通道,每个通道能输出两个互补的方波。我们会启用其中的一个通道,然后让这个通道的两个输出分别控制一个LED灯。但是由于这两个引脚上不存在同一通道的输出,所以需要第三个引脚辅助。
我们将使用PWM的通道0。
1.    PWMH0输出至引脚PA0(外设A)。
2.    PWML0输出至引脚PC0(外设B)。
3.    引脚PD20配置为纯输入引脚。
4.    将PC0和PD20两个引脚短接起来。
这样就可以使这两个LED灯交替闪烁了。

二、PWM设置

  1. 在PMC中启用PWM时钟。

    /* PMC 启用
    * PWM的ID大于31,需要在PMC_PCER1中启用
    */
    PMC->PMC_PCER1 = 1 << (ID_PWM - 32);
  2. 禁用PWM通道。
    通道在启用时不能进行完整的控制,先禁用通道。

    /* 禁用通道0,以进行配置 */
    PWM->PWM_DIS = PWM_DIS_CHID0;
  3. 设置时钟。
    通道选择的时钟直接或间接由主时钟分频得到。由于主时钟频率较高,所以为保证能产生肉眼可见的闪烁,这里会选择尽可能大的分频数。为对PWM的特性有更多的了解,我们将开启它的Clock A。

    通过向PWM时钟控制器的(PWM_CLK)中的PERA字段写入 9,以配置Clock A的输入时钟为MCK / 512;通过向DIVA字段写入125,再将输入时钟进行125分频。配置完成后,CLKA输出的时钟的频率即为MCK / (512 * 125)。初始化时,MCK的频率为4MHz(4000000Hz),所以CLKA输出频率即为62.5 Hz。

    /* clockA */;
    PWM->PWM_CLK = PWM_CLK_DIVA(125)
    | PWM_CLK_PREA(9);
  4. 选择通道的模式。
    为简单起见,将使用默认的属性:周期为左对齐,极性为先输出低电平,不使用中断以及死区发生器。同时,在这里为通道选择时钟CLKA。

    /* 配置通道0 */
    PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;
  5. 配置周期和占空比。
    为观察方便,将输出脉冲方波的周期设置为2秒,占空比50%。因为使用的时钟频率为62.5Hz,所以需要将计数器的周期设置为62.5 * 2 = 125。将比较器阀值设置为63,使占空比大约为50%。

    PWM->PWM_CH_NUM[0].PWM_CPRD = PWM_CPRD_CPRD(125);   /* 周期 */
    PWM->PWM_CH_NUM[0].PWM_CDTY = PWM_CDTY_CDTY(63); /* 占空比,准确来说是阀值 */
  6. 使能PWM通道。

    /* 使能 PWM */
    PWM->PWM_ENA = PWM_ENA_CHID0;

三、PIO设置

在实现思路中已经说明了PIO引脚的配置,而且不是太为复杂,且后面将会给出完整代码,这里就不单独解释了。

附 完整代码

#include <sam.h>

void ConfigPWM(void)
{
/* PMC 启用
* PWM的ID大于31,需要在PMC_PCER1中启用
*/
PMC->PMC_PCER1 = 1 << (ID_PWM - 32); /* 禁用通道0,以进行配置 */
PWM->PWM_DIS = PWM_DIS_CHID0; /* clockA */;
PWM->PWM_CLK = PWM_CLK_DIVA(125)
| PWM_CLK_PREA(9);
/* 配置通道0 */
PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA /* 计数器时钟选择为CLKA */
; /* 周期左对齐,先输出低电平,不使用中断及死区发生器 */ PWM->PWM_CH_NUM[0].PWM_CPRD = PWM_CPRD_CPRD(125); /* 周期 */
PWM->PWM_CH_NUM[0].PWM_CDTY = PWM_CDTY_CDTY(63); /* 占空比,准确来说是阀值 */ /* 使能 PWM */
PWM->PWM_ENA = PWM_ENA_CHID0;
} void ConfigPIO(void)
{
/* 引脚由外设控制 */
PIOA->PIO_PDR = PIO_PA0;
PIOC->PIO_PDR = PIO_PC0;
/* 选择外设 */
/* PIOA选择外设A(将影响PA所有引脚) */
PIOA->PIO_ABCDSR[0] = 0;
PIOA->PIO_ABCDSR[1] = 0;
/* PC0选择外设B */
PIOC->PIO_ABCDSR[0] = PIO_ABCDSR_P0;
PIOC->PIO_ABCDSR[1] = 0; /* 配置PD20为输入 */
PIOD->PIO_PER = PIO_PD20;
PIOD->PIO_ODR = PIO_PD20;
} int main(void)
{
/* Disable WDT */
WDT->WDT_MR = WDT_MR_WDDIS; ConfigPWM();
ConfigPIO(); while (1) {
}
return 0;
}

SAM4E单片机之旅——4、LED闪烁之PWM的更多相关文章

  1. SAM4E单片机之旅——3、LED闪烁之定时器中断

    让一个LED灯闪烁不过瘾,我们应该让这块开发板完成一点更高难度的任务:比如让两个LED灯闪烁. …… 当然了,以我们的现在使用的空循环技术,还是可以实现这点的.但是这样显得略为低端.所以我们使用一个高 ...

  2. SAM4E单片机之旅——23、在AS6(GCC)中使用FPU

    浮点单元(Floating Point Unit,FPU),是用于处理浮点数运算的单元. 为使用FPU,除了需要启用FPU外,还需要对编译器进行设置,以使其针对浮点运算生成特殊的指令.虽然在Atmel ...

  3. SAM4E单片机之旅——2、LED闪烁之轮询定时器

    之前我们使用空循环,达到了延迟的目的,但是这样子的延迟比较不精确.现在就使用实时定时器(RTT)来进行更为精确的计时.RTT虽然不是特别通用,在某些单片机上可能没有,但它较为简单. RTT内部有一个计 ...

  4. SAM4E单片机之旅——1、LED闪烁之空循环

    最近因为导师要写一本关于SAME4单片机的书籍,而我也作为一个嵌入式的初学者看了这本书.现在也让我写写几个小的程序,做做示例.既然写了文档之类的,就发到博客上来吧. 目前关于这芯片能参考的书籍大概就只 ...

  5. SAM4E单片机之旅——7、LED闪烁之TC中断

    RTT主要用做一个全局的定时器,而且不太通用.现在尝试使用一个更为通用的定时器进行定时:定时计数器(Timer Counter, TC). TC提供了广泛的功能,主要可以分为对输入的测量,以及波形的输 ...

  6. SAM4E单片机之旅——6、LED闪烁之按钮控制

    现在试试用按钮控制LED灯……让LED在一个按钮按下时亮起:弹起时灭掉. 主要目的是学习GPIO的输入及中断. 一. 电路 图中的J39-n是几个跳线插座,位置在开发板LCD附近,往下进行前要先确保跳 ...

  7. SAM4E单片机之旅——5、LED呼吸和PWM

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

  8. SAM4E单片机之旅——8、UART初步

    通信还是比让LED灯闪烁实用得多的. 这次试试使用UART,实现开发版和PC间的通信.功能比较简单,就是把PC发向开发版的内容发送回去.这次主要介绍一下UART的配置,至于通信,则使用较为简单的不断查 ...

  9. SAM4E单片机之旅——24、使用DSP库求向量数量积

    DSP(Digital Signal Processing,数字信号处理)中会使用大量的数学运算.Cortex-M4中,配置了一些强大的部件,以提高DSP能力.同时CMSIS提供了一个DSP库,提供了 ...

随机推荐

  1. Redis Cluster 集群的实现和管理

    系统环境 CentOS 7 集群规划 在一台物理机(实际部署应当分散到多个物理机上),创建6个Redis节点,其中3个主节点.3个从节点. 节点表: IP 端口 主从 路径 192.168.1.21 ...

  2. Filter里面实现未登录跳转,已登录权限判断

    package com.erichfund.cljjfof.server.util; import java.io.IOException; /** * @author 作者 zhuzhengquan ...

  3. es6总结 (五)--函数扩展

  4. 【開發時,應注意事項】 vendor tools 無法 work 時,怎麼辦?

    遇到 vendor tools 無法 work 時, 最好的方法直接請 vendor 來, 為什麼呢? 因為 tool 可能 有版本的問題, 譬如: vendor tool A tool 在 buil ...

  5. ping探测在线主机

    一.实验要求: 1.对于给定范围的ip地址进行主机在线测试 2.ping测试结果保存在/tmp/ping目录下以时间戳为文件名的文件里,以便后续查看 二.实验过程: #!/bin/env/ bash# ...

  6. 如何让div中的文字只显示一行,多余的文字隐藏并加上省略号(超链接形式)

    写页面的时候遇到了一个小小的问题,如何让div中一行超链接文字只显示一行,多余的文字隐藏并加上省略号,悬浮时隐藏的文字显示出来?解决问题时发现了css3的一个新标签  text-overflow  , ...

  7. Javascript实现页面滚动时导航智能定位

    遇到的问题: 在做官网的时候,需要滚动定位的区块的图片不确定,无法确定用户浏览区域对应的模块导航 之前的解决方案是: 通过定位滚动条的位置来判断用户浏览区域对应的模块导航,这种方法的弊端是,区块的高度 ...

  8. java并发之hashmap源码

    在上篇博客中分析了hashmap的用法,详情查看java并发之hashmap 本篇博客重点分析下hashmap的源码(基于JDK1.8) 一.成员变量 HashMap有以下主要的成员变量 /** * ...

  9. 快速上手 Echarts

    最近使用到了 百度的 Echarts 数据可视化工具,这里简单介绍如何快速上手. 一.下载 这里选择目前最新版本,4.2.1 地址:https://github.com/apache/incubato ...

  10. SQL盲注工具BBQSQL

    SQL盲注工具BBQSQL   SQL注入是将SQL命令插入到表单.域名或者页面请求的内容中.在进行注入的时候,渗透测试人员可以根据网站反馈的信息,判断注入操作的结果,以决定后续操作.如果网站不反馈具 ...