nRF51822 的两路 PWM 极性

  忙了一阵这个PWM,玩着玩着终于发现了些规律。Nordic 也挺会坑爹的。

  nRF51822 是没有硬件 PWM 的,只能靠一系列难以理解的 PPI /GPIOTE/TIMER来实现,其实我想说,我醉了。

  幸好SDK有这个的demo,不然真的很醉。这里说的是SDK9.0.0。

  即便是有SDK,相信很多人都像我一样,看下去会觉得晕头转向的,不过知道几个函数的应用就可以了。

  先记下怎么开始用一个PWM。这里我要用2路极性相反的PWM。

先来初始化两个个PWM实例,名字是PWM1、PWM2,用硬件Timer1/Timer2作为基础,千万要切记Timer1/Timer2没被占用,然后记得打开Timer1/Timer2的宏。

#define TIMER1_ENABLED 1
#define TIMER2_ENABLED 1
APP_PWM_INSTANCE(PWM1,1);
APP_PWM_INSTANCE(PWM1,1);

然后初始化一个PWM。

void pwm_init(uint32_t freq)
{
    static uint8_t flag=0;

    uint32_t period_us = 1000000UL/freq;

     /* 2-channel PWM, 200Hz, output on DK LED pins. */
    app_pwm_config_t pwm_cfg = APP_PWM_DEFAULT_CONFIG_1CH(period_us, BEEF_PIN_E1);
    app_pwm_config_t pwm_cfg2 = APP_PWM_DEFAULT_CONFIG_1CH(period_us, BEEF_PIN_E2);

//    pwm_cfg2.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
    /* Switch the polarity of the second channel. */
//  pwm_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW;
#if 1
    if(flag)
        pwm_cfg2.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW;
    else
        pwm_cfg2.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
#endif

    flag = !flag;
    /* Initialize and enable PWM. */
    ret_code_t err_code;
    err_code = app_pwm_init(&PWM1,&pwm_cfg,pwm_ready_callback);
    APP_ERROR_CHECK(err_code);
    err_code = app_pwm_init(&PWM2,&pwm_cfg2,pwm_ready_callback);
    APP_ERROR_CHECK(err_code); 

}

上面的代码你会注意到,我用了一个 flag 。这就是我想要说的重点。

这个函数是可以反复使用以修改 PWM的频率的,在再次使用时,先uninit它,如下:

void pwm_uninit(void)
{
    app_pwm_uninit(&PWM1);
    app_pwm_uninit(&PWM2);
}

我要说的重点是,第二次使用pwm_init()后然后enable_pwm,你就会发现这两路 的PWM的极性变成一样的了,所以我用一个flag,每次切换一下。解决了这个问题。

另外我发现修改占空比时,要等上一段时间才能修改完成,这点非常奇怪,懒得去追究原因了,所以才用了两个定时器来做这两路PWM。

void pwm_on(void)
{

    app_pwm_enable(&PWM1);
    app_pwm_enable(&PWM2);

    app_pwm_channel_duty_set(&PWM1, 0, 50);
    app_pwm_channel_duty_set(&PWM2, 0, 50);

//    ready_flag = false;
//    while (app_pwm_channel_duty_set(&PWM1, 0, 50) == NRF_ERROR_BUSY);
//    while(!ready_flag);
 //   APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 1, 50));
}

就是这两个怪事。记下来。

时间: 2024-08-10 02:04:41

nRF51822 的两路 PWM 极性的相关文章

混杂设备驱动--输出两路PWM

尝试用2440的TOUT0和TOUT1输出PWM驱动两个电机,电机的硬件驱动电路是使用L298N. 先单独测试TOUT0的PWM输出: (1)驱动程序:使用misc混杂设备驱动模型,当然也可以使用基本的字符设备模型. 使用misc设备驱动模型步骤: ①初始化一个struct miscdevice结构体:主要是file_operation结构体成员和name ②使用misc_register和misc_deregister注册和注销这个结构体 代码示例: #include <linux/modul

nRF51822使用Timer制作4路PWM波详解

Date:2015.5.8 Author:杨正  QQ:1209758756 <[email protected]> 一.            pwm简介 PWM英文名叫Pulse Width Modulation,中文名叫脉宽调制.那它到底是什么呢?其实它是由定时器产生的,比普通的定时器多了一个比较寄存器.PWM里面有一个词叫占空比,即一个周期内,高电平持续时间与周期的比值.如下图: 占空比(dutycycle) = t/T. PWM用途:控制电机调速,控制蜂鸣器播放音乐,控制led灯亮度

两路归并排序

链表两路归并 #include<iostream> #include<assert.h> using namespace std; struct node { int val; node * next; node(int v) { val=v; next=NULL; } }; node * merge(node* list1 , node * list2) { assert(list1!=NULL&&list2!=NULL);//括号中是希望出现的正确的情况  no

[TM4C123单片机实战] 两路ADC检测,短路报警

如果最终得到的数据是两路数据的差值, 我们可以采用ADC的 Difference 工作模式 #include <stdbool.h> #include <stdint.h> #include "inc/hw_memmap.h" #include "driverlib/adc.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #in

AR9344在Linux下启用两路UART

AR9344支持两路UART,平常用的调试串口都是UART0,驱动是使用8250的,今天因项目需求启用UART1,配置过程中需要注意几点 1. 9344的GPIO口是复用的,可以灵活配置大多数支持的功能,需要找两个GPIO,配置成UART1_TD和UART1_RD功能(如果使用硬件流控,需要再找两个GPIO配置成CTS和RTS) 2. 驱动可以使用ar93xx_uart.c,如果不使用硬件CTS和RTS功能,需要在驱动中配置成禁用硬件流控,一开始调试就是RX接收正常但TX的数据总是发送失败,最后

STM32F207 两路ADC连续转换及GPIO模拟I2C给Camera Sensor初始化参数

1.为了更好的方便调试,串口必须要有的,主要打印一些信息,当前时钟.转换后的电压值和I2C读出的数据. 2.通过GPIO 模拟I2C对镁光的MT9V024进行参数初始化.之前用我以前公司SP0A19芯片,是I2C是8位宽的,而镁光的地址是8位,而数据位是16个字节, 其实不管是8位还是16位,每次发送都是8个字节然后一个应答位,所以只要稍微改下代码即可. 3.实现两路ADC连续转换,两路ADC转换:一路是检测锂电池电压:一路是检测压力传感器,其实都是检测电压,当检测到压力为零,并累计多长时间后进

排序--两路排序

#include<iostream> using namespace std; #define SIZE 21 typedef int Sqlist[SIZE]; void TwayTnsertSort(Sqlist &T,Sqlist &S,int n) { int i,j,k; int first=0; int last = 0; S[first]= S[last] = T[0]; for(i=1;i<n;++i) { if(T[i] >= S[last]) {

FFmpeg 学习之 定时器解码两路视频并进行对比

两路视频跳帧的一些想法: 关于多路视频,如果不涉及对比的话,多线程是最佳选择,来一路视频的话,直接开一个线程去显示处理,非常有效,方便. 但如果说要求两路视频的图像的相似度,那么便牵扯到解码同步问题,如果说一路是本地视频文件,一路是网络视频流,那么很可能由于其帧型的不同,导致解码效率不同,相同序号的帧出现在两个时刻.感觉对比的话,应该是在线程里,当然,鉴于计算量比较大,比较的时候可以再开线程,此为后话. 再说同步的问题,可设置标志位,标定帧号.由于解码本地视频丢帧率较小,且由于帧型而导致解码效率

Arduino控制16路PWM舵机驱动板(PCA9685)

最近买了块16路PWM舵机驱动板,测试后做个总结. 舵机原理网上资料很多就不详细介绍了,一般以9g舵机为例,一个20ms的周期内通过0.5ms到2.5ms的脉冲宽度控制舵机角度. 板子为16通道12bit PWM舵机驱动,用2个引脚通过I2C就可以驱动16个舵机. 修改例子为可以通过串口设置舵机角度 1 #include <Wire.h> 2 #include <Adafruit_PWMServoDriver.h> 3 4 //默认地址 0x40 5 Adafruit_PWMSer