该讲介绍51822的Timer/Counter模块工作在timer模式下(定时器模式,还可以工作为计数器模式) 如何操作

51822的Timer/Counter结构如下图所示

Timer模块从PCLK16M/PCLK1M 处获得时钟源,然后经分频后得到的时钟作为timer模块的时钟 ( 上图Ftimer)。当timer模块选择为timer模式时,Counter会在Ftimer的每个tick 计数一次当计数值与cc[n](n为0,1,2,3)寄存器中的值相等时就会触发对应的Compare[n]事件,如果我们设置了compare[n]事件产生时触发中断(关于事件与中断看前一篇GPIOTE),那么就可以在counter计数到与 cc[n]寄存器中的值相等时触发中断,也就能实现我们需要的定时器功能了

所以根据上面的模块结构图和说明想要实现定时器,我们需要做如下几个步骤:

1    选择Timer/Countermo模块为timer模式,并设置bitmode(8,16,,2,32位)

2    通过设置分屏来设置timer的时钟

3    设置cc[n](后面我们的例子选择使用cc0),来设置计数到多少产生compares[n]事件(当计数值技术到cc[n]的值时对应产生compare[n]事件)

4    设置compare事件产生时触发中断。

5     通过NVIC函数启动MCU 的timer中断

6    最后启动timer就可以了。

通过查看 数据手册看以看到

1

设置模式 通过 寄存器MODE 设置 0为timer模式 1为counter模式。

2

设置timer的时钟  通过以下公式设置

fTIMER = 16 MHz / (2^PRESCALER)

这里可能有个疑问,上面的图解中不是有两个时钟源 16M和1M吗,怎么这个公式只能通过16M来分频获得timer时钟。 这是因为51822为了降低功耗内部自动 做了时钟源切换,当Ftimer <= 1M时会自动切换成1M时钟源

举两个例子解释下

如果需要timer的时钟为 4M,那么4 = Ftimer = 16M/2^2

即我们只需设置分频寄存器 PRESCALER为2,就能或得4M的时钟给timer了

当需要timer的时钟为500Khz时,根据公式 我们设置PRESCALER寄存器的值为5, 500kHZ = Ftimer = 16M/2^5。 这个时候Ftimer<=1M,所以51882内部会自动切换成1M的时钟源然后分频后获得500K的timer时钟。 不过这些都是51822自动切换的了

也就是说设置timer时钟只要根据上面的公式设置就可以了,时钟源的切换是51822自动完成的

3

设置cc[n]寄存器的值,定时就是通过这个值来设置的。 下面的例子会做一个一秒定时亮灯/灭灯的程序, 我们设置timer时钟为1M,即分频寄存器PRESCALER写值为4。 1M的时钟源则一个tick为1us,所以要定时1s,则cc[0]的值我们填入 1000000就行了。(这里也可以选择cc[1],cc[2],或cc[3],只要下面对应的compare事件产生中断设置成对应的就可以了)

4

通过寄存器INTENSET 第16bit位设置compare[0]事件产生时触发中断。

5

通过NVIC的功能函数NVIC_EnableIRQ 来使能MCU的Timer0中断

6

最后通过Timer/Counter模块的 START 启动timer。 

 

注意:这里裸板例子代码我们用的是timer0,如果跑了协议栈就不能用timer0,可以使用timer1和timer2

新建一个工程选择自己的芯片型号

下面的代码我们不使用nrf提供的库函数,而按照上面说明的顺序直接设置寄存器来使用timer0,因为没用别的功能。所以下面勾选一个core和startup。因为用到了点灯所以勾选一下nrf_drivers下的Nrf_gpio

下面是源代码,为了更好理解模块,都是直接操作寄存器

Main.c

#include "nrf51.h"
#include "nrf_gpio.h"

//定义自己板子上的LED灯
#define LED  22

int main(){

    nrf_gpio_cfg_output(LED);
    //NRF_TIMER0定义在nrf51.h中,该指针指向timer0中的寄存器组

    NRF_TIMER0->PRESCALER  = ;     //2^4   16分频得到1M timer时钟
    NRF_TIMER0->MODE = ;           //timer模式
    NRF_TIMER0->BITMODE = ;        // 设置32bit
    NRF_TIMER0->CC[] = ;    //一个tick是1us,1000000代表1s
    NRF_TIMER0->INTENSET = <<;//设置compare[0]事件产生时触发中断

    //该设置使timer模块中的conter计数到cc[0]值时会自动清零,以带到重//新计数的目的
    NRF_TIMER0->SHORTS = ;

    //启动timer模块
    NRF_TIMER0->TASKS_START = ;

    //开启MCU的timer0中断
    NVIC_SetPriority(TIMER0_IRQn, );
    NVIC_ClearPendingIRQ(TIMER0_IRQn);
    NVIC_EnableIRQ(TIMER0_IRQn);

    );

    ;
}

//中断函数中翻转灯状态
void TIMER0_IRQHandler(){
    ] == ){
       NRF_TIMER0->EVENTS_COMPARE[] = ;     //清除事件,不然会导致一
                                              //直产生中断
       nrf_gpio_pin_toggle(LED);
    }
}

nrf51822裸机教程-硬件timer的更多相关文章

  1. nrf51822裸机教程-PWM

    先简单介绍一下PWM的原理. 原理很简单. 假设COUNTER是个从0开始递增的计数器.  我们设置两个值 counter0 和counter1 在 COUNTER 计数到counter0的值时候翻转 ...

  2. nrf51822裸机教程-IIC

    关于IIC总线的核心有以下几点: :时钟线高电平期间必须保持数据线不变. :时钟线低电平期间可以改变数据. :时钟线和数据线上都要接上拉电阻,以使总线不工作时,两根线的电平都处于高电平状态. :每个传 ...

  3. nrf51822裸机教程-UART

    art硬件模块通常都有内置的硬件接收buff,比如51822的硬件uart模块图如下 因为通常接收到uart数据时都会做一些处理.比如保存到数据,或者对数据做一些判断之类的. 如果uart的波特率设置 ...

  4. nrf51822裸机教程-RTC

    RTC0被协议栈使用了.所以在跑蓝牙程序的情况下.RTC0不能使用. RTC相关寄存器如下: EVTEN,EVTENSET,EVTENCLR. 这三个寄存器用来设置是否使能某个事件.(TICK,OVR ...

  5. nrf51822裸机教程-PPI

    Programmable Peripheral Interconnect即可编程外设互联 系统,该模块是51822 提供的一个特性. 目的是为了让51822 的外围模块可以不通过处理器而自动相互作用. ...

  6. nrf51822裸机教程-GPIOTE

    GPIO通常都会具有中断功能,上一讲的GPIO中并没有涉及到中断的相关寄存器. 51822将GPIO的中断相关做成了一个单独的模块GPIOTE,这个模块不仅提供了GPIO的中断功能,同时提供了 通过t ...

  7. nrf51822裸机教程-SPI(主)

    关于SPI总线的介绍这里就不细说了,网上有很多介绍SPI总线时序的. SPI总线的本质就是一个环形总线结构,在时钟驱动下两个双向移位寄存器进行数据交换. 所以SPI总线的特色就是:传输一字节数据的同时 ...

  8. nrf51822裸机教程-GPIO

    首先看看一下相关的寄存器说明 Out寄存器 输出设置寄存器 每个比特按顺序对应每个引脚,bit0对应的就是 引脚0 该寄存器用来设置 引脚作为输出的时候的 输出电平为高还是低. 与输出设置相关的 还有 ...

  9. 迅为4412开发板Linux驱动教程/硬件知识及原理图的使用

    视频教程下载地址:http://pan.baidu.com/s/1pJwxUfL 嵌入式研发流程介绍 • PCB研发流程介绍 – 方案,原理图(网表) – layoutproject师(gerber文 ...

随机推荐

  1. 微信SDK开发学习

    public class MainActivity extends Activity { // 应用程序的id,就是在网上开发平台创建应用的appid public static final Stri ...

  2. Hark的数据结构与算法练习之圈排序

    算法说明 圈排序是选择排序的一种.其实感觉和快排有一点点像,但根本不同之处就是丫的移动的是当前数字,而不像快排一样移动的是其它数字.根据比较移动到不需要移动时,就代表一圈结束.最终要进行n-1圈的比较 ...

  3. js:语言精髓笔记7----原型继承

    面向对象有三个基本特性:封装,继承,多态:如果都满足的话称为面向对象语言:而部分满足则称为基于对象语言: 数据类型实现模型描述: JavaScript对象模型: 构造过程:函数->构造器 构造器 ...

  4. BZOJ4182 : Shopping

    最后选择的一定是树上的一个连通块,考虑树分治,每次只需考虑重心必选的情况,这就变成了以重心为根的树形依赖多重背包问题. 设f[x][j]表示从根节点到x这条路径及其左边的所有节点,以及以x为根的子树的 ...

  5. Java多线程编程详解

    转自:http://programming.iteye.com/blog/158568 线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Ja ...

  6. [Java] StringBuffer类

    http://www.cnblogs.com/springcsc/archive/2009/12/03/1616330.html 注: StringBuffer类和String一样,也用来代表字符串, ...

  7. WebRTC手记之WebRtcVideoEngine2模块

    转载请注明出处:http://www.cnblogs.com/fangkm/p/4401143.html 终于讲到视频数据的编码发送模块了,不容易.总体来说也看了不少时间WebRTC的源码了,最大的感 ...

  8. 定时任务之Spring与Quartz的整合(有修改)

    转摘:http://www.javaweb1024.com/java/JavaWebzhongji/2015/04/13/548.html 在Spring中使用Quartz有两种方式实现:第一种是任务 ...

  9. 连接mysql遇到的问题

    1. 首先使用一个用户名不行时,可以新建一个用户名点击用户,输入名和密码,此时一定要记住密码,别忘了.不过也可以点击编辑用户改.此时连接时发现还是连接不上.出现错误信息为: Access denied ...

  10. Trie

    字典树 class Trie { public: Trie() { root = new Node(); } ~Trie() { destroy(root); } void insert(string ...