S12學習筆記

把學習筆記整理一下,懶得忘了。看了很多網上的資料,但是終覺得記不住,水過鴨背,糊里糊塗,決定嘗試把它從自己嘴裏吐出來。另外由於暫時缺乏硬件,只能停留在知識點層面,應用程序以後再說了。

;>P.S.(任何資料都是google所得,如有雷同,純粹抄襲)

PIT (Periodic Inerrupt Timer):


圖片

 

如圖,實際上就是一個8位計數器產生一個時鐘信號,提供給下一個16位計數器計數,當溢出後就產生中斷。公式:time-out period=(PITMTLD+1)*(PITLD+1)/fBUS

圖片

 

各個寄存器中,

PITMUX用來爲416位計數器選擇各自的時鐘(接上哪一個8位計數器)。PITMLDn8位計數器的預存值,同理,PITDL則爲16位計數器的預存值,而PITCNn爲當前計數值。

PITTFPITINTE分別爲溢出標誌位以及溢出中斷使能位。

PITCE是使能各個16位計數器通道。

PITFLT是用來強迫16位計數器進行reload

PITCFLMT用來強迫8位計數器進行reload,並且其中有一個PITE這個總使能標誌位。

總的來說,PIT就是像它英文所描述那樣,通過自減計數直到零而溢出來週期產生中斷的Module

TIMER


圖片

 

核心:爲16位可編程計數器,其時鐘源來自一個預分頻器,S12擁有8輸入捕捉/匹配輸出通道、一個脈衝累加器

什麼叫輸入捕捉呢---就是說,首先選擇相應的引腳作爲輸入引腳,當sense到有效的邊沿觸發後,將timer16位計數器的數值轉移到TCx寄存器中。(TCx就是相應引腳的一個裝數的東東)。當然,當事件發生後,通過相應設置可以觸發中斷。

什麼是比較輸出?---就是上面說的那個TCNT計數器跟TCx寄存器中的數值相比較,若果TCNT計數匹配到TCx,並且OCPDx置零,則可以根據TCTL12OMxOLx在相應引腳輸出東東。同理,當事件發生後,通過相應設置可以觸發中斷。

PA脈衝累加器?-------通過PAMOD來選擇兩種工作模式,一種是事件計數模式:PEDGE定義的

有效邊沿後則PACNT計數加一,並且通過PAVOFPAVOI標誌位來進行溢出中斷。另一種是門時間計數(不知道是不是這樣翻譯O(_)O~ Gated Time Accumulation Mode),就是在檢測到PEDGE定義的電平後,PACNT divided-by-64 clock進行不斷計數,直到隨之的下一邊沿。簡單的說就是搞到那個電平延長了多久。

TIMER的中斷:-----主要有三種,一種TFLG1中的CxF標誌任何輸入捕捉還是匹配輸出事件發生則相應位置高,配合TIE中的CxI進行中斷使能;一種TFLG2主要是一個TOF(即從FFFF0000時則置高),這個配合TSCR2中的TOI可以中斷。另一種PA通過PAVOFPAVOI標誌位來進行溢出中斷。

時鐘信號產生:TSCR2中有一個PR[2:0]來選擇預分頻,再加上PACTL中的CLK[1:0]進行時鐘的

選擇,最終確定timer所用時鐘信號

零散分析:

TSCR1存器是定時器模塊的總開關,它決定模塊是否啓動以及在等待模式,BDM模式下定時器的工作狀態。其中的TEN標誌位用來使能這個計數器

OCPD--使能匹配輸出引腳是否connect

TCTL1TCTL2決定了OCx(即匹配輸出的方式)、而TCTL3TCTL4則配置輸入捕捉的邊緣觸發方式

Timer模塊中的幾個計數器或者說數值寄存器TCNT--儲存Timer計數值;TCn--IC模式下,將Timer的計數值存下來,作爲OC模式下,用來儲存與Timer相比較的匹配值;PACNT--用來存放捕捉到的脈衝數量或者電平延續時間。

 

另外注意OC7匹配輸出的高高優先級):OC7匹配成功時可以改變、管理其他7個輸出引腳的狀態,即OC7MOC7D所決定的匹配狀態優先於OMxOLx決定的匹配動作。例如:當OC7匹配後,當某個

OC7Mn=1,則內部邏輯將C7Dn的值送到相應引腳,若OC7Mn=0,則按照OMxOLx決定

動作。

 

注意:有些標誌位是要軟件清零的,並且是寫一清零啲。

 

ATD

 

16通道,8- 10- 12-bits可選。S12ATD模塊爲逐次逼近型(us級別)

1、有5個那個ATDCTLx  (ATD控制寄存器)0-屏蔽通道;1-分辨率、外部觸發源;2-外觸發的方

(上升沿啊、電平啊 什麼的)3-單次轉換序列長度;4-採樣時間、時鐘;5-選通道

2、注意reset後,默認4個轉換長度(截圖)


圖片

3、外觸發就是說通過外部event來觸發轉換序列的開始:以ETRIGSELETRIGCH[0:3]來選擇是用ETRIG[0:3]呢或者用AN[0:15]來當做外部觸發的引腳

4、標誌位SCAN:連續轉換序列,即轉換一次呢還是多次緊接着來轉換;

 MULT:0-單個通道轉換(由SCCACBCCCD來決定是哪個) 1--多通道轉換(同樣SCCACBCCCD來決定是從哪一個開始)

5、內有一個Compare比較功能:把Channel x探測到的值 ATDDRx中預存的值 通過ATDCMPHT(符合寄存器,即大於還是小於)來對比,若正確True則以CCFx來標誌。

6ATDDRx中結果的FormatDJM決定,DJM=0時則爲左對齊,爲 1 時則爲右對齊。

這點在read這個寄存器的值或者在寫入compare值時要分外注意。

 

 圖片

 

PWM

 

8個通道,可編程週期、佔空比、4個可選時鐘(ABSASB),可選左對齊或中心對齊

 


圖片

1、選擇時鐘:

PWMCLK分配每個通道的時鐘

PWMPRCLK 時鐘預分頻:其實是對總線時鐘進行預分頻來得到Clock AB

PWMSCLAPWMSCLB則是用來分頻產生更精確時鐘。如Clock SA=Clock A/2*PWMSCLA

2、選擇極性

PWMPOL:對通道進行極性控制,如 PWMPOL_PPOL0=1 則通道0在週期開始時先輸出爲高電平,當計數器等於佔空比的值時,則輸出爲低電平。

Polarity=0: Duty Cycle=[(PWMPERx-PWMDTYx)/PWMPERx]*100%

Polarity=1: Duty Cycle=[PWMDTYx/PWMPERx]*100%

3、選擇對齊方式、級聯方式

PWMCAE 數據格式對齊配置,0-左對齊,1-中心對齊

截圖(如圖告訴你什麼是左對齊,什麼是中心對齊)

圖片圖片

 

 

PWMCTL 可使兩個8位連接爲16位,其中變爲16位後,以低位(Low Order)通道做輸出或決定輸出,比如CON67置位後,注意是以7爲低位。

4、設置週期、佔空比

PWMPERxPWMDTYxPWMCNTx分別爲週期、佔空比、計數寄存器。

5、使能PWM  PWMEx寄存

 

 

 

SCI


圖片

 

復位後,波特率發生器是不工作的 SBR012=0 ;並且在寫入SCIBDH後,必須補寫SCIBDL 否則不工作。公式爲:

圖片

 

數據位若果爲9bits,(即SCICR1控制寄存器中M位爲1),應先高位寫入,再低位。

SCISR1中的TDREtransmit date regester empty)置高指示寫入新的發送數據,復位爲1,當其爲1時讀取SCISR1,再寫SCIDRL便可清零。

RDRF(receive data register full flag)置高指示可以讀取接收完的數據,順次讀取SCISR1SCIDR後會自動清零

主要應用都是像以前那個串口通信一樣,發送---》等空---》再發送;或者是 等置高》接收---》等置高。

另外附有一個紅外調制子模塊

並且有LOOPS 模式(跟平時測試時一樣,自己輸出,再自己接收處理)    single-wire 模式(以TXDIR決定是TXD pin 做輸入定輸出,應該可以用來弄那個DS18B20,下次試一試)

圖片

圖片

 

圖片

 

PLL的作用:

 

圖片 

公式:fvcofpllfbus 調節每一個參數時,都有想應該一個寄存器,而寄存器中有一個頻率鎖相範圍(參數的調節後不能超過這個範圍,否則不穩定)通常調好後,要檢查CRGFLG中的LOCK標誌位(如圖)

0-VCOCLK is not within the desired tolerance of the target freguency

1-opposite

 

CLKSEL時鐘選擇寄存器:決定或配置各模式下的時鐘工作或stop情況。使用時要置高PLLSEL

 


圖片

另外
PLLCTL寄存器中的PLLON位置高來開啓PLL工作電路

引用龍丘的程序說明

void SetBusCLK_16M(void)

{  

    CLKSEL=0X00;                              // disengage PLL to system

    PLLCTL_PLLON=1;                      // turn on PLL

    SYNR=0x00 | 0x01;          // VCOFRQ[7:6];SYNDIV[5:0]

                        // fVCO= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1)

                        // fPLL= fVCO/(2 × POSTDIV)

                        // fBUS= fPLL/2

                        // VCOCLK Frequency Ranges  VCOFRQ[7:6]

                        // 32MHz <= fVCO <= 48MHz    00

                        // 48MHz <  fVCO <= 80MHz    01

                        // Reserved                  10

                        // 80MHz <  fVCO <= 120MHz   11                                

    REFDV=0x80 | 0x01;  // REFFRQ[7:6];REFDIV[5:0]

                        // fREF=fOSC/(REFDIV + 1)

                        // REFCLK Frequency Ranges  REFFRQ[7:6]

                        // 1MHz <= fREF <=  2MHz       00

                        // 2MHz <  fREF <=  6MHz       01

                        // 6MHz <  fREF <= 12MHz       10

                        // fREF >  12MHz               11                        

                        // pllclock=2*osc*(1+SYNR)/(1+REFDV)=32MHz;

    POSTDIV=0x00;       // 4:0, fPLL= fVCO/(2xPOSTDIV)

                        // If POSTDIV = $00 then fPLL is identical to fVCO (divide by one).

    _asm(nop);          // BUS CLOCK=16M

    _asm(nop);

    while(!(CRGFLG_LOCK==1));     //when pll is steady ,then use it;

    CLKSEL_PLLSEL =1;                   //engage PLL to system;

}

 

 

 

中斷的編寫:

在頭文件中可以查找到:

/**************** interrupt vector numbers ****************/

#define VectorNumber_Vsi                119

#define VectorNumber_Vsyscall           118

 

#define VectorNumber_Vatd0compare       96

 

#define VectorNumber_Vpit3              69

#define VectorNumber_Vpit2              68

#define VectorNumber_Vpit1              67

#define VectorNumber_Vpit0              66

#define VectorNumber_Vhti               65

#define VectorNumber_Vapi               64

#define VectorNumber_Vlvi               63

 

#define VectorNumber_Vpwmesdn           57

#define VectorNumber_Vportp             56

 

#define VectorNumber_Vcan0tx            39

#define VectorNumber_Vcan0rx            38

#define VectorNumber_Vcan0err           37

#define VectorNumber_Vcan0wkup          36

#define VectorNumber_Vflash             35

#define VectorNumber_Vflashfd           34

 

#define VectorNumber_Vcrgscm            29

#define VectorNumber_Vcrgplllck         28

 

#define VectorNumber_Vporth             25

#define VectorNumber_Vportj             24

 

#define VectorNumber_Vatd0              22

#define VectorNumber_Vsci1              21

#define VectorNumber_Vsci0              20

#define VectorNumber_Vspi0              19

#define VectorNumber_Vtimpaie           18

#define VectorNumber_Vtimpaaovf         17

#define VectorNumber_Vtimovf            16

#define VectorNumber_Vtimch7            15        

#define VectorNumber_Vtimch6            14        

#define VectorNumber_Vtimch5            13        

#define VectorNumber_Vtimch4            12        

#define VectorNumber_Vtimch3            11        

#define VectorNumber_Vtimch2            10        

#define VectorNumber_Vtimch1            9 

#define VectorNumber_Vtimch0            8

#define VectorNumber_Vrti               7   

#define VectorNumber_Virq               6  

#define VectorNumber_Vxirq              5   

#define VectorNumber_Vswi               4 

#define VectorNumber_Vtrap              3  

#define VectorNumber_Vcop               2 

#define VectorNumber_Vclkmon            1 

#define VectorNumber_Vreset             0  

其他的爲保留中斷位。。。。。。。。。。。。。

 

 

要點一:

因爲中斷矢量只有16位,所以無法在分頁地址中尋址。因此,中斷函數必須放入非分頁地址。在程序文件中要將中斷函數放入非分頁地址,用這樣的格式:

#pragma CODE_SEG NON_BANKED

。。。中斷函數。。。

#pragma CODE_SEG __NEAR_SEG NON_BANKED

所以說我們的中斷服務例程必須被“#pragma CODE_SEG NON_BANKED”和“#pragma CODE_SEG DEFAULT”包圍起來。

 

要點二:

中斷的服務程序名的寫法一般有以下幾種

1.interrupt關鍵字+中斷向量號+自己的isr函數

2.interrupt關鍵字+isr函數(isrprmVECTOR ADDRESS 映射)

3.#pragma TRAP_PROC聲明(isrprmVECTOR ADDRESS 映射)

 

#pragma TRAP_PROC 僅對緊跟着它的函數有效,通知編譯器位於它下面的函數是中斷函數,其返回指令是RTI,而不是RET,因此每個中斷函數前面都必需有這個預處理。在PRM文件中定義中斷矢量地址:

 

VECTOR ADDRESS 0xFFXX My_ISR  加在PRM文件的最後就可以了。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章