把学习笔记整理一下,懒得忘了。看了很多网上的资料,但是终觉得记不住,水过鸭背,糊里糊涂,决定尝试把它从自己嘴里吐出来。另外由于暂时缺乏硬件,只能停留在知识点层面,应用程序以后再说了。
;>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文件的最后就可以了。