• cc2530 timer 1 PWM 输出


    需要在ZStack 协议栈里使用PWM,于是使用其16bit的timer 1来实现之。使用 P1_0口输出,使用的是正计数/倒计数模式,占空比为50%。代码如下:

     1 #include <ioCC2530.h>
     2 
     3 /*使用P1_0口为输出、外设端口,来输出PWM波形*/
     4 void init_port(void)
     5 {
     6     P1DIR |= 0x01;    // p1_0 output
     7     P1SEL |= 0x01;    // p1_0  peripheral
     8     P2SEL &= 0xEE;    // Give priority to Timer 1
     9     PERCFG |= 0x40; // set timer_1 I/O位置为2
    10     return ;
    11 }
    12 
    13 /*
    14     将基准值放入T1CC0 寄存器, 将被比较值放入T1CC2寄存器
    15     当T1CC2中的值与T1CC0中的值相等时,则T1CC2 设置or清除
    16 */
    17 
    18 void init_timer(void)
    19 {
    20     T1CC0L = 0xff;   //PWM duty cycle  周期
    21     T1CC0H = 0x7f;
    22     
    23     T1CC2L = 0x00;  //     PWM signal period 占空比
    24     T1CC2H = 0x00;
    25     
    26     T1CCTL2 = 0x34;    // 等于T1CC0中的数值时候,输出高电平 1; 等于T1CC2中的数值时候,输出低电平 0  ,其实整个占空比就为50%了
    27     T1CTL |= 0x0f; // divide with 128 and to do i up-down mode
    28     return ;
    29 }
    30 
    31 void start_pwm(void) 
    32 {
    33     init_port();
    34     init_timer();
    35 //    IEN1 |=0x02;     //Timer 1 中断使能
    36 //    EA = 1;            //全局中断使能
    37 //    while(1) {;}
    38     return ;
    39 }
    40 
    41 #if 0
    42 /*irq function*/
    43 #pragma vector=T1_VECTOR
    44 //__interrupt void T1_IRQ(void)
    45 volatile unsigned char count = 0;
    46 __interrupt void _irq_timer1(void)
    47 {
    48     //TODO....
    49 }
    50 
    51 #endif /*_irq_timer1*/

    使用的时候,将start_pwm() 函数 放在需要的地方即可。注意不要和原来的timer 冲突。自己是选择注释掉原来的timer的代码,直接写寄存器,不用协议栈给出的API了。

    解释下:

    1、

    1 P2SEL &= 0xEE;    // Give priority to Timer 1

    其中,P2SEL 寄存器的名字叫 "端口2功能选择寄存器",但是它的管的范围可不只有端口2 ,它的[2:0] 分别指定 P2.0、 P2_3、P2_4 是作为通用I/O还是外设引脚功能;而

    [6:3] 则分别指定端口1 外设优先级的--一个端口可能同时可以被uart 和timer使用,那么谁优先使用这个端口,则是它来指定的。3 ~6 bit 分别对应端口 1的 P1_0 ~ P1_3.。

    当然,类似于P2SEL这样多功能的寄存器还有其他的,比如P2DIR,它同时指定端口2的方向,也管理着端口0的外设优先级。这个是奇怪了点,但还是按照数据手册来吧。

    2、

    1     PERCFG |= 0x40; // set timer_1 I/O位置为2

    PERCFG 这个寄存器名字叫“外设I/O控制寄存器”,其实它的功能就像一个拨码开关一样,起一个选择路的作用。

    看下面贴图:

    什么乱七八糟的备用位置1 备用位置2,我是没明白的,但是看第一张图,要使用timer 1 并且在P1_0,那么就必须设置到 Alt 2的位置上。那么相应的寄存器就是PERCFG 了,开始还纠结了一把,没搞明白。 <ps:手册里的I/O口映射并没有标Alt 1,只是标了 Alt 2:如上图USART1在P0端口,就是使用的Alt 1。如果有需要的话,还是一样的用寄存器 PERCFG设置到 备用位置1 即可>

    我程序里是 timer 1 P1_0,那么设置到 Alt 2的话,代码显然就该:

    1 PERCFG |= 0x40; // set timer_1 I/O位置为2

    3、32MHz / 128 = 250 Hz ?  不知道计算错了没,反正就是这么个公式吧。以这样的频率,计时器从0单步单步走到同T1CC2寄存器里面的值相等的时候,进行一次操作;然后继续走到T1CC0 处再操作一次 --  比如给I/O端口的电平取反什么的,都可以,看心情。

    4、其他,其他就没了,其他的寄存器在手册里面很容易理解了。 

    5、 我和同事一起整理了个小的学习备忘录文档,链接如下:

    文档链接: http://pan.baidu.com/s/1o6qIjOY 

    <ps:文档表述不一定非常准确>

    关键字: cc2530 timer1 pwm PWM

  • 相关阅读:
    安卓权限详解
    Android 中使用自定义字体的方法
    Android 开发笔记——通过 Intent 传递类对象
    Android中Log机制详解
    Android开发规范——命名
    android 软键盘回车键捕获
    Android ViewPager使用详解
    Inflater与findViewById()区别
    Android屏幕适配和文字屏幕适配
    Android软件开发之EditText 详解(八)
  • 原文地址:https://www.cnblogs.com/chineseboy/p/3664355.html
Copyright © 2020-2023  润新知