nrf51822裸机教程-PWM
先简单介绍一下PWM的原理。

原理很简单。 假设COUNTER是个从0开始递增的计数器。 我们设置两个值 counter0 和counter1 在 COUNTER 计数到counter0的值时候翻转输出的电平,然后COUNTER继续计数,在计数到counter1的值的时候再翻转输出电平。 同时清零COUNTER计数器。让其从0开始重新计数,这样就可以产生一个方波。
从上面的图可以看出这个方波的一个周期T的时间是由 counter1来决定的。所以周期的调节就是通过counter1的值来调节。 而counter0的值则影响着方波的占空比。
综上,PWM的实现就是通过调节counter1和counter0的两个值来实现周期和占空比可调。
51822硬件没有PWM模块,所以如果需要使用PWM,从上面的原理介绍可以知道使用timer定时器就可以实现上述功能。
我们可以使用timer定时器中的寄存器cc[1],和cc[0]来设置上面说的counter1值和counter0值。并分别设置当计数器计数到指定值是产生中断。 在中断里面 将电平翻转就可以了。
但是这中方法因为中断的处理需要CPU参数,会影响PWM的周期和占空比。更多的影响是如果timer会频繁产生中断。导致正常的程序执行流程会被频繁打断。
所以这里需要用到 51822的 可编程外围互联系统(PPI), 该系统可以使51822的外围模块在无CPU参与的情况下相互协作。(详见PPI教程)
同时因为使用PPI 让timer模块和GPIO模块来协作产生PWM,所以这里不能使用普通的GPIO,而需要使用针对PPI的GPIOTE模块。(详见GPIOTE教程)

如上图所示。 我们使用timer模块 让其 计数到 counter0 和counter1时分别产生event0,和event1。这两个event通过PPI然后触发同一个task,这个task就是翻转电平。
下面是main.c代码细节。
#include "nrf51.h"
#include "stdio.h"
#include "nrf_gpio.h"
#define PWM_OUT 22
void timer0_init(void){
NRF_TIMER0->PRESCALER = ; //2^4 16分频成1M时钟源
NRF_TIMER0->MODE = ; //timer模式
NRF_TIMER0->BITMODE = ; //32bit
NRF_TIMER0->CC[] = ; //cc[1]的值等于是1s,这里相当于方波的周期为1s
NRF_TIMER0->CC[] =; //调节占空比,这里设置为0.5
NRF_TIMER0->SHORTS = <<; //设置到计数到cc1中的值时 自动清0 重新开始计数
NRF_TIMER0->TASKS_START = ; //启动timer
}
void gpiote_init(void){
NRF_GPIOTE->CONFIG[] = ( << ) //作为task模式
| ( PWM_OUT << ) //设置PWM输出引脚
| ( << ) //设置task为翻转PWM引脚的电平
| ( << ); //初始输出电平为高
}
//使用了两个PPI通道。 通道0 用来将 timer的 event0 (计数到cc0的值产生的事件) 与 上面设置的GPIOTE task绑定在一起
//通道1 用来将timer的event1(计数到cc1的值产生的事件) 也与上面的GPIOTE task事件绑定在一起。
//这样到计数到cc0和cc1时都会自动翻转 PWM_OUT引脚的电平。
void ppi_set(void){
NRF_PPI->CH[].EEP = (uint32_t)(&NRF_TIMER0->EVENTS_COMPARE[]); //注意,这里赋值要取地址
NRF_PPI->CH[].TEP = (uint32_t)(&NRF_GPIOTE->TASKS_OUT[]);
NRF_PPI->CH[].EEP = (uint32_t)(&NRF_TIMER0->EVENTS_COMPARE[]);
NRF_PPI->CH[].TEP = (uint32_t)(&NRF_GPIOTE->TASKS_OUT[]);
//两个通道的task端绑定的都是翻转电平的task
//使能PPI通道 0 和 通道1
NRF_PPI->CHENSET = 0x03;
}
int main(void){
gpiote_init();
ppi_set();
timer0_init();
);
;
}
通过调节cc0和cc1的值就可以分别控制占空比和周期了。这里只是个简单的示例。实际使用简单封装下就可以当做自己的PWM来使用了
nrf51822裸机教程-PWM的更多相关文章
- nrf51822裸机教程-IIC
关于IIC总线的核心有以下几点: :时钟线高电平期间必须保持数据线不变. :时钟线低电平期间可以改变数据. :时钟线和数据线上都要接上拉电阻,以使总线不工作时,两根线的电平都处于高电平状态. :每个传 ...
- nrf51822裸机教程-UART
art硬件模块通常都有内置的硬件接收buff,比如51822的硬件uart模块图如下 因为通常接收到uart数据时都会做一些处理.比如保存到数据,或者对数据做一些判断之类的. 如果uart的波特率设置 ...
- nrf51822裸机教程-RTC
RTC0被协议栈使用了.所以在跑蓝牙程序的情况下.RTC0不能使用. RTC相关寄存器如下: EVTEN,EVTENSET,EVTENCLR. 这三个寄存器用来设置是否使能某个事件.(TICK,OVR ...
- nrf51822裸机教程-PPI
Programmable Peripheral Interconnect即可编程外设互联 系统,该模块是51822 提供的一个特性. 目的是为了让51822 的外围模块可以不通过处理器而自动相互作用. ...
- nrf51822裸机教程-GPIOTE
GPIO通常都会具有中断功能,上一讲的GPIO中并没有涉及到中断的相关寄存器. 51822将GPIO的中断相关做成了一个单独的模块GPIOTE,这个模块不仅提供了GPIO的中断功能,同时提供了 通过t ...
- nrf51822裸机教程-SPI(主)
关于SPI总线的介绍这里就不细说了,网上有很多介绍SPI总线时序的. SPI总线的本质就是一个环形总线结构,在时钟驱动下两个双向移位寄存器进行数据交换. 所以SPI总线的特色就是:传输一字节数据的同时 ...
- nrf51822裸机教程-硬件timer
该讲介绍51822的Timer/Counter模块工作在timer模式下(定时器模式,还可以工作为计数器模式) 如何操作 51822的Timer/Counter结构如下图所示 Timer模块从PCLK ...
- nrf51822裸机教程-GPIO
首先看看一下相关的寄存器说明 Out寄存器 输出设置寄存器 每个比特按顺序对应每个引脚,bit0对应的就是 引脚0 该寄存器用来设置 引脚作为输出的时候的 输出电平为高还是低. 与输出设置相关的 还有 ...
- AVR单片机教程——PWM调光
本文隶属于AVR单片机教程系列. PWM 两位数码管的驱动方式是动态扫描,每一位都只有50%的时间是亮的,我们称这个数值为其占空比.让引脚输出高电平点亮LED,占空比就是100%. 在驱动数码管时 ...
随机推荐
- Python 中文Key 报错问题
例如: # -*- coding=UTF-8 -*- import json data = [] with open('data.json') as f: for line in f: data.ap ...
- http://blog.csdn.net/jiazimo/article/details/17265061
http://blog.csdn.net/jiazimo/article/details/17265061
- java中的String设计原理
首先,必须强调一点:String Pool不是在堆区,也不是在栈区,而是存在于方法区(Method Area) 解析: String Pool是常量池(Constant Pool)中的一块. 我们知 ...
- 如何在 .Net Framework 4.0 项目上使用 OData?
最新的 Microsoft ASP.NET Web API 2.1 OData 5.1.0 已只能在 .Net Framework 4.5 的安装了,如果要在 VS2010的 .Net Framewo ...
- BZOJ3217 : ALOEXT
替罪羊树套Trie,Trie合并用线段树合并,注意常数优化. 顺便AC800题纪念~~~ #include<cstdio> #include<cmath> #include&l ...
- BZOJ 1001 & SPFA
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MB Description 现在小朋友们最喜欢的"喜羊羊与灰太狼 ...
- 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)
http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...
- 【BZOJ】1221: [HNOI2001] 软件开发(最小费用最大流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1221 先吐槽一下,数组依旧开小了RE:在spfa中用了memset和<queue>的版本 ...
- iOS应用程序本地化
一.简介 * 使用本地化功能,可以轻松地将应用程序翻译成多种语言,甚至可以翻译成同一语言的多种方言 * 如果要添加本地化功能,需要为每种支持的语言创建一个子目录,称为”本地化文件夹”,通常使用.lpr ...
- QCheckBox 的按钮响应
Qt中QCheckBox的按键响应如下,其中checkbox为对象名: void YourClass::on_checkbox_toggled(bool state) { // Do somethin ...