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

一、pwm简介

PWM英文名叫Pulse Width Modulation,中文名叫脉宽调制。那它到底是什么呢?其实它是由定时器产生的,比普通的定时器多了一个比较寄存器。PWM里面有一个词叫占空比,即一个周期内,高电平持续时间与周期的比值。如下图:

占空比(dutycycle) = t/T。

PWM用途:控制电机调速,控制蜂鸣器播放音乐,控制led灯亮度等

二、Timer,Ppi,Gpiote之间的关系

由Timer产生一个事件,PPI捕获这个事件并把这个事件转化为任务传递给GPIOTE,由GPIOTE模块执行最终指定操作(该操作后面会讲到):

三、Timer定时器

要产生PWM波,需要将定时器产生的信号通过指定的引脚输出。定时器有两种模式,即计数器模式和定时器模式,要产生PWM波,自然要选择定时器模式,然而定时器模式里面也有一个计数器寄存器,即Counter。定时器模式还有一个捕获/比较寄存器,即CC寄存器。nRF51822的Timer中的Counter是递增的方式计数,当Counter的计数值与CC寄存器中的值相等时,就会产生一个事件。

nRF51822里面有三个定时器,因为TIMER0被CPU占用,所以只能使用TIMER1和TIMER2来做4路PWM波。使用TIMER1的CC[0]和CC[1]分别控制一路PWM波的频率和占空比,CC[2]和CC[3]分别控制第二路PWM波的频率和占空比。TIMER2类推,这样就可以做出4路PWM波。以下是第一路PWM波的timer init函数, 其他三路的timer init函数可以由此类推,eg:

timer init函数

{

NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;

NRF_CLOCK->TASKS_HFCLKSTART = 1;

while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)

{

}

NRF_TIMER1->MODE =TIMER_MODE_MODE_Timer;

NRF_TIMER1->TASKS_CLEAR = 1;

NRF_TIMER1->CC[1]= 1;//控制占空比

NRF_TIMER1->SHORTS=(TIMER_SHORTS_COMPARE0_CLEAR_Enabled<<TIMER_SHORTS_COMPARE0_CLEAR_Pos);

NVIC_EnableIRQ(TIMER1_IRQn);

NVIC_SetPriority(TIMER1_IRQn,APP_IRQ_PRIORITY_HIGH);

}

{

//cc0 controlperiod, cc1 controls the duty cycle

NRF_TIMER1->EVENTS_COMPARE[0]= 0;

//cc2 control period, cc3 controls the duty cycle

NRF_TIMER1->EVENTS_COMPARE[2] = 0;

NRF_TIMER1->CC[3] = duty_cycle1_23;

}

四、ProgrammablePeripheral Interconnect (PPI)

nRF51822的寄存器分为三类:

Task寄存器:外设可以执行的task;

Event寄存器:外设带有的event;

普通寄存器;

Task寄存器和Event寄存器在PPI中的使用非常重要,例如,在PPI中,设置EEP寄存器为某个外设A的Event寄存器地址,TEP寄存器设为另外一个外设Task寄存器地址,那么当外设A的event发生时可以直接触发外设B的Task,而不经过CPU。

eg:

{

// Configure PPI channel 01 to togglePWM_OUTPUT_PIN on every TIMER1 COMPARE match.

NRF_PPI->CH[0].EEP =(uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];

NRF_PPI->CH[0].TEP =(uint32_t)&NRF_GPIOTE->TASKS_OUT[0];

NRF_PPI->CH[1].EEP =(uint32_t)&NRF_TIMER1->EVENTS_COMPARE[1];

NRF_PPI->CH[1].TEP =(uint32_t)&NRF_GPIOTE->TASKS_OUT[0];

// Configure PPI channel 23 to toggle PWM_OUTPUT_PIN on every TIMER1COMPARE match.

NRF_PPI->CH[2].EEP =(uint32_t)&NRF_TIMER1->EVENTS_COMPARE[2];

NRF_PPI->CH[2].TEP =(uint32_t)&NRF_GPIOTE->TASKS_OUT[1];

NRF_PPI->CH[3].EEP =(uint32_t)&NRF_TIMER1->EVENTS_COMPARE[3];

NRF_PPI->CH[3].TEP =(uint32_t)&NRF_GPIOTE->TASKS_OUT[1];

// Configure PPI channel 45 to toggle PWM_OUTPUT_PIN on every TIMER2COMPARE match.

NRF_PPI->CH[4].EEP =(uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];

NRF_PPI->CH[4].TEP =(uint32_t)&NRF_GPIOTE->TASKS_OUT[2];

NRF_PPI->CH[5].EEP =(uint32_t)&NRF_TIMER2->EVENTS_COMPARE[1];

NRF_PPI->CH[5].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[2];

// Configure PPI channel 67 to toggle PWM_OUTPUT_PIN on every TIMER2COMPARE match.

NRF_PPI->CH[6].EEP =(uint32_t)&NRF_TIMER2->EVENTS_COMPARE[2];

NRF_PPI->CH[6].TEP =(uint32_t)&NRF_GPIOTE->TASKS_OUT[3];

NRF_PPI->CH[7].EEP =(uint32_t)&NRF_TIMER2->EVENTS_COMPARE[3];

NRF_PPI->CH[7].TEP =(uint32_t)&NRF_GPIOTE->TASKS_OUT[3];

// Enable PPI channels 0-7.

NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled<< PPI_CHEN_CH0_Pos)

| (PPI_CHEN_CH1_Enabled<< PPI_CHEN_CH1_Pos)

| (PPI_CHEN_CH2_Enabled<< PPI_CHEN_CH2_Pos)

| (PPI_CHEN_CH3_Enabled<< PPI_CHEN_CH3_Pos)

只有坚韧不拔向着目标奋进,成功后将在不远处等待着你的到来。

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

相关文章:

你感兴趣的文章:

标签云: