NRF52840学习历程(十)PWM05共同模式之单通道呼吸灯_播完停止_按键控制继续播

时间在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);
}

 

代码讲解:

这两个定义为全局变量,后面就可以通过按键修改播放序列的内容了

 

  1. NRF_DRV_PWM_PIN_INVERTED为 播放完成之后,置为高电平(灯熄灭),如果没有这个,播完之后LED会变亮
  2. 其他通道就不用

 

1播放5次

2 播完拉倒

 

按键中断

1 按下KEY0,会重新播放序列5次,再停下来

2 按下KEY1,可以修改序列的第一个元素,那么也就可以说自由修改播放内容了

3 同理KEY2一样效果

 

 

效果自己下载看,我这边就不展示了

 

链接:https://pan.baidu.com/s/1R_l53MmmpligHeyyHmDQ8A

提取码:lhiy

复制这段内容后打开百度网盘手机App,操作更方便哦

猜你喜欢

转载自blog.csdn.net/jwdeng1995/article/details/113703799
今日推荐