NRF52840学习历程(十)PWM04共同模式下之双序列合成输出_呼吸灯+闪烁灯组合

时间在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

 

 

效果

 

呼吸一次(从暗到最亮到最暗(这个时间为10ms * 6 * 50个数组成员 =3秒)),

延时1秒,

再闪2下, 时间为 10ms * 20 =200ms

然后从1/2亮,1/4亮,1/8亮,1/16亮,1/32亮到暗 时间为 10ms * 20 =200ms

重复播放

 

代码


#define My_PWM0_top_value 10000 // 1/1M  * 10000 =10ms
#define  STEP_COUNT  50

void MY_PWM_INIT_02(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).
*/
	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 = 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; 	
	}


	nrf_pwm_sequence_t 	p_sequence0; //定义播放序列1的结构体
	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;
	
	//这个是数组2序列
    static nrf_pwm_values_common_t seq1_values[16]= // 这个序列你看过就知道是什么现象了
	{
		0,					//灭
		My_PWM0_top_value,  //亮
		0,
		My_PWM0_top_value,
		0,
		0,
		My_PWM0_top_value>>1,
		My_PWM0_top_value>>2,
		My_PWM0_top_value>>3,
		My_PWM0_top_value>>4,
		My_PWM0_top_value>>5,
		0,
		0 //后面省略的自动补零
	};
	
	nrf_pwm_sequence_t 	p_sequence1; //定义播放序列2的结构体
	p_sequence1.end_delay = 0 ; //播放结束后 不延时
	p_sequence1.length = NRF_PWM_VALUES_LENGTH(seq1_values) ; // 序列长度
	p_sequence1.repeats =  20 ; // 这个是增加持续周期, 在原来10ms的基础上, *20倍= 持续200ms
	p_sequence1.values.p_common = seq1_values;

	// 双序列输出PWM   使用PWM0 ,把序列1,2内容写入结构体,播放次数,播完继续播(循环模式)
	nrf_drv_pwm_complex_playback(&my_pwm0, &p_sequence0, 
								&p_sequence1,1,NRF_DRV_PWM_FLAG_LOOP);
}


#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();
	

 

 

代码讲解:

  1. 将时间匹配时间设置为宏定义类型 不能用uint16_t
  2. 呼吸灯的步数设置为50次
  3. 从独立模式设为共同模式

 

-----------------------------------------------------------------------------

序列1代码

这个数组为序列数组, 播放PWM就是播放序列里面的内容

这边我设置为50个内容

 

这个是把呼吸灯写到序列内容上面,不懂就多理解几次

 

  1. 定义结构体
  2. 播放完这个序列之后, 会延时 100 * 10ms =1s再播放下一个序列,指的是序列1播放完之后,等待1s再播放序列2
  3. 这个为序列长度, 50个
  4. 6代表 持续时间变为原来的6倍, 原来是 10ms * 50个数组 = 500ms ,现在就是3s

 

-----------------------------------------------------------------------------

序列2代码

就是闪烁灯,和逐渐变暗灯

 

  1. 播放完序列2后不延时
  2. 序列长度为16(我上面直接给的16)
  3. 这个序列2持续的时间为 10ms * 16 * 20 = 3.2s
  4. 序列2数组

-----------------------------------------------------------------------------

 

然后把序列初始化好就行, 设置为循环播放模式

 

 

 

 

 

实验现象没有, 自己试,代码放下面了

 

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

提取码:95pi

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

猜你喜欢

转载自blog.csdn.net/jwdeng1995/article/details/113703311