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社區一個帖子 點我


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM