把學習筆記整理一下,懶得忘了。看了很多網上的資料,但是終覺得記不住,水過鴨背,糊里糊塗,決定嘗試把它從自己嘴裏吐出來。另外由於暫時缺乏硬件,只能停留在知識點層面,應用程序以後再說了。
;>P.S.(任何資料都是google所得,如有雷同,純粹抄襲)
PIT (Periodic Inerrupt Timer):
如圖,實際上就是一個8位計數器產生一個時鐘信號,提供給下一個16位計數器計數,當溢出後就產生中斷。公式:time-out period=(PITMTLD+1)*(PITLD+1)/fBUS
各個寄存器中,
PITMUX用來爲4個16位計數器選擇各自的時鐘(接上哪一個8位計數器)。PITMLDn是8位計數器的預存值,同理,PITDL則爲16位計數器的預存值,而PITCNn爲當前計數值。
PITTF、PITINTE分別爲溢出標誌位以及溢出中斷使能位。
PITCE是使能各個16位計數器通道。
PITFLT是用來強迫16位計數器進行reload。
PITCFLMT用來強迫8位計數器進行reload,並且其中有一個PITE這個總使能標誌位。
總的來說,PIT就是像它英文所描述那樣,通過自減計數直到零而溢出來週期產生中斷的Module。
TIMER:
核心:爲16位可編程計數器,其時鐘源來自一個預分頻器,S12擁有8輸入捕捉/匹配輸出通道、一個脈衝累加器
什麼叫輸入捕捉呢?---就是說,首先選擇相應的引腳作爲輸入引腳,當sense到有效的邊沿觸發後,將timer的16位計數器的數值轉移到TCx寄存器中。(TCx就是相應引腳的一個裝數的東東)。當然,當事件發生後,通過相應設置可以觸發中斷。
什麼是比較輸出?---就是上面說的那個TCNT計數器跟TCx寄存器中的數值相比較,若果TCNT計數匹配到TCx,並且OCPDx置零,則可以根據TCTL1、2的OMx、OLx在相應引腳輸出東東。同理,當事件發生後,通過相應設置可以觸發中斷。
PA脈衝累加器?-------通過PAMOD來選擇兩種工作模式,一種是事件計數模式:PEDGE定義的
有效邊沿後則PACNT計數加一,並且通過PAVOF和PAVOI標誌位來進行溢出中斷。另一種是門時間計數(不知道是不是這樣翻譯O(∩_∩)O~ Gated Time Accumulation Mode),就是在檢測到PEDGE定義的電平後,PACNT以 divided-by-64 clock進行不斷計數,直到隨之的下一邊沿。簡單的說就是搞到那個電平延長了多久。
TIMER的中斷:-----主要有三種,一種是TFLG1中的CxF標誌任何輸入捕捉還是匹配輸出事件發生則相應位置高,配合TIE中的CxI進行中斷使能;一種是TFLG2主要是一個TOF(即從FFFF到0000時則置高),這個配合TSCR2中的TOI可以中斷。另一種是PA通過PAVOF和PAVOI標誌位來進行溢出中斷。
時鐘信號產生:TSCR2中有一個PR[2:0]來選擇預分頻,再加上PACTL中的CLK[1:0]進行時鐘的
選擇,最終確定timer所用時鐘信號
零散分析:
TSCR1寄存器是定時器模塊的總開關,它決定模塊是否啓動以及在等待模式,BDM模式下定時器的工作狀態。其中的TEN標誌位用來使能這個計數器
OCPD--使能匹配輸出引腳是否connect
TCTL1與TCTL2決定了OCx(即匹配輸出的方式)、而TCTL3與TCTL4則配置輸入捕捉的邊緣觸發方式
Timer模塊中的幾個計數器或者說數值寄存器:TCNT--儲存Timer計數值;TCn--IC模式下,將Timer的計數值存下來,作爲OC模式下,用來儲存與Timer相比較的匹配值;PACNT--用來存放捕捉到的脈衝數量或者電平延續時間。
另外注意(OC7匹配輸出的高高優先級):OC7匹配成功時可以改變、管理其他7個輸出引腳的狀態,即OC7M、OC7D所決定的匹配狀態優先於OMx和OLx決定的匹配動作。例如:當OC7匹配後,當某個
OC7Mn=1,則內部邏輯將C7Dn的值送到相應引腳,若OC7Mn=0,則按照OMx,OLx決定
動作。
注意:有些標誌位是要軟件清零的,並且是寫一清零啲。
ATD:
16通道,8- 10- 12-bits可選。S12的ATD模塊爲逐次逼近型(us級別)
1、有5個那個ATDCTLx (ATD控制寄存器):0-屏蔽通道;1-分辨率、外部觸發源;2-外觸發的方
式(上升沿啊、電平啊 什麼的);3-單次轉換序列長度;4-採樣時間、時鐘;5-選通道
2、注意reset後,默認4個轉換長度(截圖)
3、外觸發就是說通過外部event來觸發轉換序列的開始:以ETRIGSEL和ETRIGCH[0:3]來選擇是用ETRIG[0:3]呢或者用AN[0:15]來當做外部觸發的引腳
4、標誌位SCAN:連續轉換序列,即轉換一次呢還是多次緊接着來轉換;
MULT:0-單個通道轉換(由SC、CA、CB、CC、CD來決定是哪個) 爲1--多通道轉換(同樣SC、CA、CB、CC、CD來決定是從哪一個開始)
5、內有一個Compare比較功能:把Channel x探測到的值 與 ATDDRx中預存的值 通過ATDCMPHT(符合寄存器,即大於還是小於)來對比,若正確True則以CCFx來標誌。
6、ATDDRx中結果的Format由DJM決定,DJM=0時則爲左對齊,爲 1 時則爲右對齊。
這點在read這個寄存器的值或者在寫入compare值時要分外注意。
PWM:
8個通道,可編程週期、佔空比、4個可選時鐘(A、B、SA、SB),可選左對齊或中心對齊
1、選擇時鐘:
PWMCLK分配每個通道的時鐘
PWMPRCLK 時鐘預分頻:其實是對總線時鐘進行預分頻來得到Clock A、B
PWMSCLA、PWMSCLB則是用來分頻產生更精確時鐘。如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、設置週期、佔空比
PWMPERx、PWMDTYx、PWMCNTx分別爲週期、佔空比、計數寄存器。
5、使能PWM :PWMEx寄存
器
SCI:
復位後,波特率發生器是不工作的 SBR【0:12】=0 ;並且在寫入SCIBDH後,必須補寫SCIBDL 否則不工作。公式爲:
數據位若果爲9bits,(即SCICR1控制寄存器中M位爲1),應先高位寫入,再低位。
SCISR1中的TDRE(transmit date regester empty)置高指示寫入新的發送數據,復位爲1,當其爲1時讀取SCISR1,再寫SCIDRL便可清零。
RDRF(receive data register full flag)置高指示可以讀取接收完的數據,順次讀取SCISR1和SCIDR後會自動清零
主要應用都是像以前那個串口通信一樣,發送---》等空---》再發送;或者是 等置高—》接收---》等置高。
另外附有一個紅外調制子模塊
並且有LOOPS 模式(跟平時測試時一樣,自己輸出,再自己接收處理) 和 single-wire 模式(以TXDIR決定是TXD pin 做輸入定輸出,應該可以用來弄那個DS18B20,下次試一試)
PLL的作用:
公式:fvco、fpll、fbus 調節每一個參數時,都有想應該一個寄存器,而寄存器中有一個頻率鎖相範圍(參數的調節後不能超過這個範圍,否則不穩定)通常調好後,要檢查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函數(isr在prm中VECTOR ADDRESS 映射)
3.#pragma TRAP_PROC聲明(isr在prm中VECTOR ADDRESS 映射)
#pragma TRAP_PROC 僅對緊跟着它的函數有效,通知編譯器位於它下面的函數是中斷函數,其返回指令是RTI,而不是RET,因此每個中斷函數前面都必需有這個預處理。在PRM文件中定義中斷矢量地址:
VECTOR ADDRESS 0xFFXX My_ISR 加在PRM文件的最後就可以了。