SYD8801定时器使用说明

来源:互联网 发布:腾讯软件管家 编辑:程序博客网 时间:2024/05/01 13:15

SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.syd-tek.com/

SYD8801定时器使用说明

        

Syd8801的定时器是32位的递减定时器,带有自动重装的功能,同时定时器的时钟可以选择内部的32.768khz内部时钟(如果没有经过校准该时钟偏差很大)和外部的32.768khz时钟,外部时钟能做到十分的精准。

使用内部定时器的话必须经过校准,对于外设驱动代码使用LPOCaliWaitUS函数进行校准,如果代码中包含了《syd_ble_keil.lib》库,则调用LPOCalibration函数进行校准。使用内部32.768Khz时钟的定时器程序如下:

uint8_tj=0;

intmain()

{

         uint8_t i=0;

         led_config(LEDALL);   //led初始化

         if(LPOCaliWaitUS(1000)){   //这是内部RC32k晶振的校准函数

                   for(i=0;i<6;i++){   //成功

                            led_turn(LEDALL);

                            delay_ms(300);

                   }

         }else{    //失败

                   for(i=0;i<20;i++){

                            led_turn(LEDALL);

                            delay_ms(300);

                   }

         }

         timer_0_enable(0x1F40,timer0_callback); // 8000 /32.768 ms = 244.140625 ms

         timer_1_enable(0x3E80,timer1_callback); // 16000 /32.768 ms = 488.28125 ms

         timer_2_enable(0x7D00,timer2_callback); // 32000 /31.25 ms = 976.5625 ms

         __enable_irq();

         while(1)

         {

                   if(j>180){   //最晚三分钟必须再校准一次

                            j=0;

                            led_turn(LED3);

                            if(LPOCaliWaitUS(1000)){

                                     for(i=0;i<6;i++){

                                               led_turn(LED3);

                                               delay_ms(300);

                                     }

                            }else{

                                     for(i=0;i<20;i++){

                                               led_turn(LED3);

                                               delay_ms(300);

                                     }

                            }

                   }

         }

}

其中校准函数如下:

/*

内部32Khz时钟校准函数

参数:uint32_tdelay  校准超时时间限制单位1us

返回值:uint8_t 0:校准失败 1:校准成功

注意:内部RC即使校准了依旧会存在16hz的误差 也就是说时钟偏差会在 32.768khz+-0.016khz的范围

*/

uint8_tLPOCaliWaitUS(uint32_t delay)

{

         uint8_t tmp;

         uint32_t cnt = 0;

         BBRFWrite(0x7F,0x01);//bank B

         BBRFWrite(0x0a,0x00);

         BBRFWrite(0x0a,0x02);

         while(++cnt < delay)

         {

                   delay_us(1);

                   BBRFRead(0x0a, &tmp);

                   if((tmp&0x04) == 0x04)

                   {

                            return 1;

                   }

         }

         return 0;

}

这里初始化定时器使三个定时器的溢出时间依次为244ms、488ms和976ms,然后程序主要的任务就是在中断中执行,中断服务函数如下:

staticvoid timer0_callback(void)

{

         led_turn(LED0);

}

staticvoid timer1_callback(void)

{

         led_turn(LED1);

}

staticvoid timer2_callback(void)

{

         led_turn(LED2);

         j++;

}

定时器0、2、3分别翻转LED0、LED1、LED2,因为已经有了内部晶振校准函数,所以定时器的偏差不是很大,下面是实验的波形如下图1:

图1.没有校准的内部定时器波形

         为了能达到更加准确的时钟,我们这里可以使用外部时钟,开发板上接了32.768khz的晶振,下面的程序就是使用了外部晶振的程序,和上面的使用内部RC震荡的区别只在主函数,主函数如下:

         intmain()

{

         uint8_tdata;

         led_config(LEDALL);

         BBRFWrite(0x7F,0x00); // switch Bank A  

         BBRFRead(0x03,&data); //读回要配置的寄存器

         BBRFWrite(0x03,data | 0x04); //置位B_M2_32KXtal_EN,打开外部晶振

        

         BBRFWrite(0x7F,0x02); // switch Bank C

         BBRFRead(0x00,&data); 

         BBRFWrite(0x00,data | 0x01);  //置位RG_CLK32K_SEL,使定时器使用外部32k晶振

         timer_0_enable(0x1F40,timer0_callback); // 8000 /32.768 ms = 244.140625 ms

         timer_1_enable(0x3E80,timer1_callback); // 16000 /32.768 ms = 488.28125 ms

         timer_2_enable(0x7D00,timer2_callback); // 32000 * 31.25 ms = 976.5625 ms

         __enable_irq();

         while(1)

         {

         }

}

         其中的BBRF函数就是使能外部晶振的函数,这时候的实验波形如下图2:

图2.外部晶振定时器波形

这时候的波形就十分的准确了。

         这里有一点值得提示一下,如果不使能外部32k晶振,是不能够在晶振管脚上测试到震荡波形的,使能晶振后的震荡波形如下:

图2.外部晶振波形

 

注意的是定时器使能函数:

void timer_0_enable(uint32_t interval, void*  p_callback)

{

         if(TIMER_CTRL->TIMER_0_EN==1)

                   TIMER_CTRL->TIMER_0_EN= 0;   

    delay_us(100);   //稍微延时 使定时器重启成功

         TIMER_CTRL->TIMER_0_VAL=interval;

         timer0_callback[0]= ((void (*)(void))p_callback);

         TIMER_CTRL->TIMER_0_RGLR=1;

         TIMER_CTRL->TIMER_0_EN= 1;

         NVIC_EnableIRQ(TIMER0_IRQn);

}

这个延时必须要加上,否则会造成软件上已经失能了定时器,但是定时器硬件还没有完全进入失能状态,这时候给定时器赋值就会造成这个值并没有真正的能够赋值给寄存器,将会造成错误


TIMER_CTRL->TIMER_0_RGLR这个寄存器位控制定时器是否自动重装,置一定时器将自动装载重复计数,以TIMER_CTRL->TIMER_0_VAL为间隔产生定时器中断;如果置零则只会产生一次中断,之后定时器停止运行!

 

最后注意一点:PWM和定时器是独立的单元,也就是说SYD8801有三路定时器,三路PWM

另外:SYD8801一共有4路定时器,但是TIMER3留给了内部的ROM区域的代码使用,也就是说TIMER用户是没有办法使用的,并且lib也没有办法使用,他已经完全固化在ROM区域了!


这里上传本博客涉及代码(没有带协议栈):

http://download.csdn.net/detail/chengdong1314/9819150

其中:

《05Timer》使用内部晶振

《05Timer_32KXtal》使用外部晶振


0 0