zoukankan      html  css  js  c++  java
  • cc2530的PWM实现

      本文记录如何利用cc2530的timer1产生pwm输出。文章原创,不以帖代码为目的,旨在让新人理解,欢迎转载

      在此之前,先看看timer1的一些特性。

      先看timer1的操作模式,分别是Free-Running, Modulo, Up-and-Down。

      具体的讲,Free-Running就是在每个时钟沿到来是计数器加1,从0x0000一直加到0xFFFF(如果设置了溢出中断,则发生中断,默认开启中断,在TIMIF.T1OVFIM可以失能中断),计数范围固定不变,可以通过预分频来控制计数频率。

    Modulo则是通过设置T1CC0H,T1CC0L两个寄存器来改变timer1的计数上限。但是,如果timer1启动时,计数值大于T1CC0H,T1CC0L,则timer1会继续向上计数到0xFFFF,然后产生溢出中断。如果timer1启动时,计数值小于T1CC0H,T1CC0L,则当计数值等于T1CC0H,T1CC0L,计数值重置。

    在这个模式下如果使用比较输出的话,T1CC0因为用做比较输出的最大值,所以通道0没有最后两种输出模式。在最后两种模式中,状态转换是与T1CC0和T1CCn(n表示通道)比较得出的。通道0重叠了!!

    另外有一点需要注意,在配置T1CC0H,T1CC0L确保定时器暂停,先写低位在写高位

    Up-and-Down,并不是pwm模式,我看网蜂pdf的定时器章节里,在T1CTL的描述中,把Up-and-Down写成了pwm。实际上,这并不是PWM模式。可以理解是,Modulo模式中加多一个到达计数最大值时,往回计数到0x0000时产生溢出中断。适用于中心对称PWM。

    其实,datasheet里面的图已经很清晰了。

      接下来是比较输出,设置T1CC0H,T1CC0L,当计数值与T1CC0H,T1CC0L相等时,相关通道产生输出。timer1总共有5个通道(0~4)。比较输出总共有9钟模式,但是要注意4~5,6~7这两对是对应着不同操作模式,通过T1CCTLn.CMP来设置。datasheet是这样描述的,还是挺好理解的。

    使用PWM的话,一般应该是选择后6种吧。前2种,如果不软件改变输出状态,那么状态就只改变一次,第3种则没有PWM效果,但是可以实现时间大于0xFFFF的输出翻转。还有就是不是每一个通道都有上述9种模式。比如通道0就没有最后两个模式。

    最后就是设置IO了,将对应的IO口设置为外设IO就可以了。先来看看外设IO分布情况

    可以看出来,timer1的对应的IO口和串口0,1重合,这里为了方便,可以通过PERCFG.U1CFG和PERCFG.U0CFG把IO设置到Alternative 2 location,也就是P1口。否则timer将不会有比较输出。

      弄清楚这些之后就是配置寄存器的问题了。给出我自己的代码(代码仅供参考,具体请根据datasheet配置相关寄存器)。先看定时器部分。

     1 #include "Timer.h"
     2 #include "led.h"
     3 
     4 void Timer1_Init(unsigned char mode, unsigned char div)
     5 {
     6     unsigned char temp;
     7     
     8     T1CCTL0 = 0x24;
     9     T1CC0L = 0x00;    //设置低位,在运行中修改,仅当计数值为0时生效
    10     T1CC0H = 0xF0;    //写入高位时,低位会从buffer中写入
    11     
    12     //配置工作模式和分频系数
    13     temp = div << 2;
    14     temp |= mode;
    15     T1CTL = temp;
    16     
    17     //使能Timer1中断
    18     T1IE = 1;
    19     
    20 }
    21 
    22 #pragma vector = T1_VECTOR
    23     __interrupt void T1_ISR(void)
    24     {
    25         
    26         D0 = ~D0;
    27         T1STAT &= ~(1 << 5);
    28         T1IF = 0;    //清除T1中断标志
    29     }
    Tiemr.c
     1 #ifndef __TIMER_H
     2     #define __TIMER_H
     3     
     4     #include <ioCC2530.h>
     5     
     6     //T1CTL
     7     //预分频设置                                    Free_Running_time
     8     #define DIV_1                        0            //0.004096
     9     #define DIV_8                        1            //0.032768
    10     #define DIV_32                    2            //0.131072
    11     #define DIV_128                    3     //0.524288s
    12     //定时器工作模式
    13     #define Suspended                0
    14     #define Free_Running        1
    15     #define Modulo                    2
    16     #define Up_And_Down            3
    17 
    18     //Timer speed
    19     #define T_32M                            0
    20     #define T_16M                         1
    21     #define T_8M                            2
    22     #define T_4M                            3
    23     #define T_2M                            4
    24     #define T_1M                            5
    25     #define T_500K                        6
    26     #define T_250K                        7
    27 
    28 
    29     //T1STAT
    30 
    31     //function
    32     void Timer1_Init(unsigned char mode, unsigned char div);
    33     
    34 #endif
    Timer.h

    再看LED部分

     1 #include "led.h"
     2 
     3 /* P1.1 | P1.3 | P1.5 | P1.7 | P2.1 | P2.3 | GND
     4  *  D2  |  S2  |      |      |      |      |
     5  * P1.0 | P1.2 | P1.4 | P1.6 | P2.0 | P2.2 | P2.4
     6  *  D1  |  S3  |  D3  |      |  S0  |      |
     7  *-----------------------------------------------
     8  * P0.6 | P0.4 | P0.2 | P0.0  | RESET | GND
     9  *      |      | L_R  |       |  S4   |
    10  * P0.7 | P0.5 | P0.3 | P0.1  | VDD   | VDD
    11  *      |      | L_T  | D4 S1 |       |
    12  *-----------------------------------------------
    13 */
    14 
    15 // D1~D3
    16 
    17 void LED_Init(void)
    18 {
    19   P1SEL &= ~0x13; //设置为GPIO
    20   P1DIR |= 0x13;  //设置为输出
    21   P1INP &= ~0x13; //
    22     
    23     P0SEL |= 0x04;    //设置为外设IO
    24     P0DIR |= 0x04;
    25     P0INP &= ~0x04;
    26   
    27     PERCFG |= 0x03; //设置串口映射到P1
    28     
    29   D0 = LED_OFF;
    30   D1 = LED_OFF;
    31   D2 = LED_OFF;
    32 }
    led.c
     1 #ifndef __LED_H
     2     #define __LED_H
     3     
     4     #include <ioCC2530.h>
     5     
     6     #define LED_ON  0
     7     #define LED_OFF 1
     8     
     9     #define D0    P1_0
    10     #define D1    P1_1
    11     #define D2    P1_4
    12     
    13     #define D0_NUM 1
    14     #define D1_NUM 2
    15     #define D2_NUM 3
    16     
    17     void LED_Init(void);
    18 
    19 #endif
    led.h

    建议仿真文件选择ioCC2530F256.ddf,可以看更多的寄存器情况,方便调试

    最后附上TI E2E社区一个帖子 点我

  • 相关阅读:
    学习笔记-Python基础4-九九乘法表练习
    学习笔记-Python基础4-函数
    学习笔记-Python基础3-程序结构:顺序、分支、循环
    JS根据获取的navigator.userAgent,判断用户打开页面的终端
    代理模式,CGLIB 与Spring AOP实现原理
    ueditor不过滤保存html
    ecstore 新增input控件方法
    ecstore前台模板保留css样式
    ecstore 当前网址
    mysql 导入数据过大报错
  • 原文地址:https://www.cnblogs.com/xiemm/p/3889851.html
Copyright © 2011-2022 走看看