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文件的最后就可以了。

 

 

 

 

 

 

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