时间在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
效果
呼吸灯5次之后,就暂停播放
按按键KEY0,可以继续播5次
代码如下:
nrf_pwm_sequence_t p_sequence0; //定义播放序列1的结构体
static nrf_pwm_values_common_t seq0_values[STEP_COUNT]; //序列1数组
void MY_PWM_INIT_03(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_COMMON; // 加载模式: 共同模式
/*
NRF_PWM_LOAD_COMMON //共同模式 四通道一同输出同一个PWM的
1st half word (16-bit) used in all PWM channels (0-3).
*/ //NRF_DRV_PWM_PIN_INVERTED说是改变极性的
p_config.output_pins[0] = 13 |NRF_DRV_PWM_PIN_INVERTED; //PWM通道0的引脚输出绑定
p_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; //不使用
p_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; //不使用
p_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; //不使用
p_config.step_mode = NRF_PWM_STEP_AUTO ;// 重复计数输出
p_config.top_value = My_PWM0_top_value;//脉冲计数的顶点值 1/1M *10000 = 10ms周期
// 使用 PWM控制器0, 初始化内容写入寄存器, 事件中断函数
nrf_drv_pwm_init(&my_pwm0,&p_config,NULL);
// This array cannot be allocated on stack (hence "static") and it must
// be in RAM.这个数组不能在堆栈上分配(因此是“静态的”),它必须在RAM中。
// 因此 数组必须是已知数量的
// 这个是序列1数组
// static nrf_pwm_values_common_t seq0_values[STEP_COUNT];
// 下面给序列数组赋值为呼吸灯
uint8_t i = 0;
uint16_t dat = 0;
uint16_t step = My_PWM0_top_value / STEP_COUNT;//等分 将10000 平分 50分,每份200,这个就是步进数
/*下面两个 for 循环 构成一个呼吸灯 */
for(i=0; i<STEP_COUNT/2; i++)
{
dat += step; // 每次加 step 步进数 (这里是200)
seq0_values[i] = dat;
}
for(i=(STEP_COUNT/2); i< STEP_COUNT; i++)
{
dat -= step; // 每次减 step 步进数 (这里是200)
seq0_values[i] = dat;
}
p_sequence0.end_delay = 100 ; //播放结束后 延时 100次( 100 * 10ms = 1s)
p_sequence0.length = NRF_PWM_VALUES_LENGTH(seq0_values) ; // 序列长度
// 每个占空比重复时间次数,这里重复6次, 这里我理解错了, 这个是增加持续周期, 在原来10ms的基础上, *6倍= 持续60ms
p_sequence0.repeats = 6 ;
p_sequence0.values.p_common = seq0_values;
// 单序列输出PWM 使用PWM0 ,把序列1内容写入结构体,播放次数,播完停止(播完拉倒)
nrf_drv_pwm_simple_playback(&my_pwm0, &p_sequence0,5,NRF_DRV_PWM_FLAG_STOP);
}
#define Turn_OFF_Other_Light 1 //灯不够用, 先把灯停掉
int main(void)
{
LED_KEY_INIT();
KEY_GPIOTE_INIT();
UART_INIT();
TIMER4_INIT();//灯不够用, 先把它的灯停掉
RTC_TIMER_INIT(); //灯不够用, 先把它的灯停掉
ADC_PPI_TIMER0_INIT();
// MY_PWM_INIT();
// MY_PWM_INIT_02();
MY_PWM_INIT_03();
按键中断
void KEY_Interrupt(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
if(KEY0 == pin)
nrf_drv_pwm_simple_playback(&my_pwm0, &p_sequence0,5,NRF_DRV_PWM_FLAG_STOP);
// nrf_gpio_pin_toggle(LED0);
if(KEY1 == pin)
seq0_values[0] = 10000;
// nrf_gpio_pin_toggle(LED1);
if(KEY2 == pin)
seq0_values[0] = 0;
// nrf_gpio_pin_toggle(LED2);
if(KEY3 == pin)
nrf_gpio_pin_toggle(LED3);
}
代码讲解:
这两个定义为全局变量,后面就可以通过按键修改播放序列的内容了
- NRF_DRV_PWM_PIN_INVERTED为 播放完成之后,置为高电平(灯熄灭),如果没有这个,播完之后LED会变亮
- 其他通道就不用
1播放5次
2 播完拉倒
按键中断
1 按下KEY0,会重新播放序列5次,再停下来
2 按下KEY1,可以修改序列的第一个元素,那么也就可以说自由修改播放内容了
3 同理KEY2一样效果
效果自己下载看,我这边就不展示了
链接:https://pan.baidu.com/s/1R_l53MmmpligHeyyHmDQ8A
提取码:lhiy
复制这段内容后打开百度网盘手机App,操作更方便哦