时间在2021年2月5日,寒假放假在家好好学一学nRF52840
今天还在感冒,休息一波
开发板:初雪的100出头那块 NRF52840 EVAL KIT
下载工具:JINLK V11(最好是JLINK V9以上 也有人用JLINK OB也行,其他的下载器诸如STLINK,DAP不建议用)
版本号: KEIL5编程环境,CMSIS为5.3.0, NRF52840的CMSIS为8.35.0
参考资料: NRF52840-Eval-Kit-Schematic.pdf(原理图)
nRF5_SDK_17.0.2_d674dde(官方例程)
nRF5_SDK_17.0.0_offline_doc(官方文档)
nRF52840_PS_v1.1.pdf(官方数据手册)
已用IO
0.96OLED / 1.29彩色OLED
D0(CLK) -> 12
D1(SDA) -> 23
RES -> 7
DC -> 21
CS -> 19
按键
KEY0 ->11
KEY1 ->24
KEY2 ->20
KEY3->17
LED
LED0 ->13
LED1->14
LED2->32+9=41
LED3->16
串口
TX ->6
RX ->8
ADC
光敏 -> 5
摇杆X -> 28
摇杆Y -> 29
IIC_0.96OLED
SDA -> 32
SCL -> 22
还没用到(空闲)
P0.0 1 2 3 9 10 15 25 26 27 30 31
P1.1 2 3 4 5 6 7 8 10 11 12 13 14 15
这一节是PWM 脉冲宽度调制
PWM模块
PWM 模块可以在 GPIO 上生成脉冲宽度调制信号。 该模块实现了一个向上或向下计数器,带有四个 PWM 通道,用于驱动分配的 GPIO。三个 PWM 模块可提供多达 12 个 PWM 通道,单个频率控制,最多可包含四个通道。每个模块的频率是相同的。此外,内置解码器和 EasyDMA 功能使得可以在没有 CPU 干预的情况下操纵 PWM 占空比。 从数据 RAM 读取任意占空比序列,可以链接以实现乒乓缓冲或重复进入复杂循环。
这里列出的是一个 PWM 模块的主要特征:
• 固定 PWM 基频,带可编程时钟分频器
• 最多四个 PWM 通道,具有独立的极性和占空比值
• PWM 通道上的边沿或中心对齐脉冲
• 数据 RAM 中定义的多个占空比数组(序列)
• 通过 EasyDMA 直接从存储器中自主且无干扰地更新占空比值
• 每个 PWM 周期可能会改变极性,占空比和基频
• 数据 RAM 序列可以重复或连接成循环
PWM周期和占空比
波形计数器负责以占空比产生脉冲。而占空比取决于比较值,并且取决于 COUNTERTOP 的频率。一个 PWM 模块有一个共用的 15 位计数器,带有四个比较通道。因此,所有四个通道将共享相同的周期(PWM 频率),但可以具有单独的占空比和极性。
PWM解码模式
1:Common 模式:称为共用模式,四个 PWM 输出共用极性和比较值设置。
2:Grouped 模式:称为分组模式,每组半个字,两个 PWM 共用极性和比较值设置。
3:Single 模式:称为单信号独立模式,每个通道半个字,每个 PWM 独立的极性和比较值设置。
4:WaveForm 模式:称为波形模式。可以使用特殊操作模式。在此模式下,最多只能使能三个PWM 通道 OUT [0]至 OUT [2]。在 RAM 中,一次加载四个值:第一个,第二个和第三个位置用于加载极性和比较值设置,第四个 RAM 位置用于加载 COUNTERTOP 寄存器。这样,最多可以有三个 PWM 通道,其频率基在每个 PWM 周期的基础上发生变化。这种操作模式对于 LED 照明等应用中的任意波形生成非常有用。
理论不看了, 直接代码走起
先添加驱动文件
..\..\..\..\..\..\modules\nrfx\drivers\src\nrfx_pwm.c
添加SKD_CONFIG文件
同时再引入低速时钟,作为休眠时间跑的晶振
配置完成, 下面加入代码
NRF52840最多只有3个PWM控制器(每个控制器能控制最多4路,其中wave模式最多3路)
这边只用到PWM0控制器
static nrf_drv_pwm_t my_pwm0 = NRF_DRV_PWM_INSTANCE(0); // PWM控制器0,每个控制器可以有4路输出
然后初始化PWM
// 务必为全局变量,我试过放在局部init里面,结果一直调试失败,放全局才成功的
nrf_pwm_values_individual_t my_pwm_sequ_val; //独立模式下的PWM控制4通道的占空比
void MY_PWM_INIT(void)
{
nrfx_pwm_config_t p_config; //定义结构体
p_config.base_clock = NRF_PWM_CLK_1MHz ; // PWM基本时钟: 16M/16 =1M
p_config.count_mode = NRF_PWM_MODE_UP ; //计数模式: 向上计数
p_config.irq_priority = _PRIO_APP_LOWEST ; //中断优先级
p_config.load_mode = NRF_PWM_LOAD_INDIVIDUAL; // 加载模式: 独立模式,4通道分开输出
/*
RF_PWM_LOAD_COMMON //共同模式 四通道一同输出同一个PWM的
1st half word (16-bit) used in all PWM channels (0-3).
NRF_PWM_LOAD_GROUPED //分组模式 组1 和组2 输出同一个PWM, 其中组1是通道0和1,组2是通道2和3
1st half word (16-bit) used in channels 0 and 1; 2nd word in channels 2 and 3.
NRF_PWM_LOAD_INDIVIDUAL //独立模式, 四通道输出独立控制
1st half word (16-bit) used in channel 0; 2nd in channel 1; 3rd in channel 2; 4th in channel 3.
NRF_PWM_LOAD_WAVE_FORM //波形发生器模式,最多3个通道,第4个通道为设置何时复位/置位
1st half word (16-bit) used in channel 0; 2nd in channel 1; ... ; 4th as the top value for the pulse generator counter.
*/
p_config.output_pins[0] = 13 ; //PWM通道0的引脚输出绑定
p_config.output_pins[1] = 14;
p_config.output_pins[2] = 41;
p_config.output_pins[3] = 16;
p_config.step_mode = NRF_PWM_STEP_AUTO ;// 重复计数输出
p_config.top_value = 10000;//脉冲计数的顶点值 1/1M *10000 = 10ms周期
// 使用 PWM控制器0, 初始化内容写入寄存器, 事件中断函数
nrf_drv_pwm_init(&my_pwm0,&p_config,MY_PWM_Interrupt);
my_pwm_sequ_val.channel_0 = 1000;
my_pwm_sequ_val.channel_1 = 3000;
my_pwm_sequ_val.channel_2 = 6000;
my_pwm_sequ_val.channel_3 = 9000;
nrf_pwm_sequence_t p_sequence; //定义播放序列1的结构体
p_sequence.end_delay = 0 ; //播放结束后 不延时
p_sequence.length = 4 ;// 4通道都用上了
p_sequence.repeats = 0 ; // 每个占空比重复时间次数
p_sequence.values.p_individual = &my_pwm_sequ_val;
// 单序列输出PWM 使用PWM0 ,把序列1内容写入结构体,播放次数,播完继续播(循环模式)
nrf_drv_pwm_simple_playback(&my_pwm0, &p_sequence, 1,NRF_DRV_PWM_FLAG_LOOP);
}
主函数 和 中断
实验结果
占空比为10%, 30%,60%,90%
我拿数字示波器抓了下
可以看出, 周期为10ms , 对应代码的 p_config.top_value = 10000;//脉冲计数的顶点值 1/1M *10000 = 10ms周期
占空比为60% ,对应my_pwm_sequ_val.channel_2 = 6000;
代码链接
链接:https://pan.baidu.com/s/1eWX8JxsVaclXD0NVzvwNiw
提取码:ndqg
复制这段内容后打开百度网盘手机App,操作更方便哦
解压到这里