找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4590|回复: 0
打印 上一主题 下一主题
收起左侧

MC9S12中文版培训教材下载(WORD格式)

[复制链接]
跳转到指定楼层
楼主
ID:379731 发表于 2018-7-27 09:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
目录
第一章 PWM模块
第一节  PWM模块介绍
第二节  PWM寄存器简介
2.1   PWME寄存器
2.2   PWMPOL寄存器
2.3   PWMCLK寄存器
2.4   PWMPRCLK寄存器
2.5   PWMCAE寄存器
2.6   PWMCTL寄存器
2.7   PWMSCLA寄存器
2.8   PWMCNTx寄存器
2.9   PWMPERx寄存器
2.10  PWMDTYx寄存器
第三节  PWM应用实例
3.1  周期和占空比计算举例
3.2  PWM初始化步骤总结
3.3  PWM应用实例
第二章 ECT模块
第一节  ECT模块介绍
1.1 简述
1.2 特征
1.3 运行模式
1.4 ECT的组成与工作模式
1.5 ECT的工作过程与设置
第二节  ECT寄存器简介
2.1   IC/OC选择寄存器(TIOS)
2.2   输出比较通道7屏蔽寄存器(OC7M)
2.3   输出比较通道7数据寄存器(OC7D)
2.4   定时器核心寄存器(TCNT)
2.5   计时器系统控制寄存器1(TSCR1)
2.6   计时器溢出绑定寄存器1(TTOV)
2.7   控制寄存器(TCTLl-TCTL4)
2.8   计时器中断使能寄存器(TIE)
2.9   计时器系统控制寄存器2(TSCR2)
2.10  主定时器中断标志寄存器(TFLG1、TFLG2)
2.11  IC/OC寄存器(TC0-TC7)
2.12  脉冲累加器A控制寄存器(PACTL)
2.13  脉冲累加器A标志寄存器(PAFLG)
2.14  脉冲累加寄存器(PACN3、PACN2、PACN1、PACN0)
2.15  模数递减计数器控制寄存器(MCCTL)
2.16  输入脉冲累加器控制寄存器(ICPAR)
2.17  输入覆盖控制寄存器(ICOVW)
2.18  输入系统控制寄存器(ICSYS)
2.19  脉冲累加器B控制寄存器(PBCTL)
2.20  脉冲累加器B标志寄存器(PBFLG)
2.21  脉冲累加器保持寄存器(PA3H-PA0H)
2.22  模数递减计数器工作寄存器(MCCNT)
2.23  IC保持寄存器(TC0H-TC3H)
第三节  ECT应用实例
3.1  定时器编程步骤
3.2  输入捕捉IC:
3.3  通道6输出比较
3.4  通道7输出比较
3.5  模数递减计数器
第三章 SCI模块
第一节  SCI寄存器简介
1.1  波特率控制寄存器(SCIBDH、SCIBDL)
1.2  控制寄存器1(SCICR1)
1.3  控制寄存器2(SCICR2)
1.4  状态寄存器1(SCISR1)
1.5  状态寄存器2(SCISR2)
1.6  数据寄存器(SCIDRH、SCIDRL)
第二节  SCI应用示例
第四章 SPI模块
第一节  SPI模块介绍
1.1  SPI的功能特点
1.2  SPl的组成与工作设置
第二节  SPI寄存器简介
2.1  SPI控制寄存器1(SPICR1)
2.2  SPI控制寄存器2(SPICR2)
2.3  SPI波特率选择寄存器
2.4  SPI状态寄存器
2.5  SPI数据寄存器
第三节  SPI应用实例
第五章 A/D转换模块
第一节  A/D模块介绍
1.1  A/D转换原理
1.2  A/D转换原理的应用前景
1.3  A/D转换模块
1.4  功能结构图
1.5  HCS12A/D特点
第二节  A/D寄存器简介
2.1  控制寄存器2(ATDCTL2)
2.2  控制寄存器3(ATDCTL3)
2.3  控制寄存器4(ATDCTL4)
2.4  控制寄存器5(ATDCTL5)
第三节  A/D应用示例
3.1  编程步骤
3.2  A/D程序示例—单通道查询
3.3  A/D程序示例—滤波
3.4  A/D程序示例—定时采样
第六章 EEPROM模块
第一节  EEPROM模块介绍
1.1  EEPROM功能
1.2  EEPROM结构
1.3  EEPROM特点
第二节  EEPROM寄存器简介
2.1  时钟分频寄存器ECLKDIV
2.2  配置寄存器ECNFG
2.3  保护寄存器EPROT
2.4  状态寄存器ESTAT
2.5  命令寄存器ECMD
第三节  EEPROM应用实例
3.1  EEPROM的写入操作
3.2  EEPROM的擦除操作
3.3  EEPROM示例程序
第七章 FLASH模块
第一节  FLASH模块介绍
1.1  FLASH功能
1.2  FLASH结构
1.3  FLASH特点
第二节  FLASH寄存器简介
2.1 时钟分频寄存器FCLKDIV
2.2 配置寄存器 FCNFG
2.3 安全寄存器 FSEC
2.4 保护寄存器 FPROT
2.5 状态寄存器 FSTAT 状态寄存器
2.6 命令寄存器 FCMD
第三节  FLASH应用实例
3.1  FLASH的写入操作
3.2  FLASH的擦除操作
3.3  FLASH的擦写操作注意事项
3.4  FLASH示例程序
第八章 CodeWarrior IDE 12应用


第一章 PWM模块第一节  PWM模块介绍
PWM调制波有8个输出通道,每一个输出通道都可以独立的进行输出。每一个输出通道都有一个精确的计数器(计算脉冲的个数),一个周期控制寄存器和两个可供选择的时钟源。每一个PWM输出通道都能调制出占空比从0—100%变化的波形。
PWM的主要特点有:
1、它有8个独立的输出通道,并且通过编程可控制其输出波形的周期。
2、每一个输出通道都有一个精确的计数器。
3、每一个通道的PWM输出使能都可以由编程来控制。
4、PWM输出波形的翻转控制可以通过编程来实现。
5、周期和脉宽可以被双缓冲。当通道关闭或PWM计数器为0时,改变周期和脉宽才起作用。
6、8字节或16字节的通道协议。
7、有4个时钟源可供选择(A、SA、B、SB),他们提供了一个宽范围的时钟频率。
8、通过编程可以实现希望的时钟周期。
9、具有遇到紧急情况关闭程序的功能。
10、每一个通道都可以通过编程实现左对齐输出还是居中对齐输出。









第二节  PWM寄存器简介2.1   PWME寄存器
PWME寄存器每一位如图2所示:
图2  PWME寄存器
每一个PWM的输出通道都有一个使能位PWMEx。它是用来启动和关闭波形输出的。当任意的PWMEx位置1,则相关的PWM输出通道就立刻可用。然而实际的PWM波形的输出还取决于时钟源。
此寄存器在任何时间都是可读、可写的,复位时全置0。
用法: PWME7=1;    7通道可对外输出波形。
       PWME7=0;    7通道不能对外输出波形。
注意:在通道使能后所输出的第一个波形可能是不规则的。当输出通道工作在串联模式时(PWMCTL寄存器中的CONxx位被设置),那么使能相应的16位PWM输出通道是由PWMEx的低电平位控制的(详情见PWMCTL寄存器)。
2.2   PWMPOL寄存器
PWMPOL寄存器每一位如图3所示:
图3  PWMPOL寄存器
每一个PWM输出通道的波形都可以选择是在高电平时翻转,还是在低电平时翻转。此功能就是由PWMPOL寄存器实现的。
此寄存器在任何时间都是可读、可写的,复位时全置0。
用法: PWMPOL0=1;  0通道对外输出波形先是高电平然后再变为低电平。
       PWMPOL0=0; 0通道对外输出波形先是低电平然后再变为高电平。
2.3   PWMCLK寄存器
PWMCLK寄存器每一位如图4所示:
图4  PWMCLK寄存器
每一个PWM输出通道都有两个时钟可供选择(A、SA或B、SB)。0、1、4、5通道可选用A、SA时钟,2、3、6、7通道可选用B、SB通道。此寄存器在任何时间都是可读、可写的,复位时全置0。应当注意的是,如果当一个PWM输出波形正在产生时,时钟改变,这时就会产生一个平头的或线形脉冲。
此寄存器在任何时间都是可读、可写的,复位时全置0。
用法:               PCLK1=1;    1通道的时钟源设为SA。
          PCLK1=0;    1通道的时钟源设为A。此为默认时钟
PWMCLK_PCLK=1;
2.4   PWMPRCLK寄存器
PWMPRCLK寄存器每一位如图5所示:
图5  PWMPRCLK寄存器
PWMPRCLK寄存器是单独用来给时钟源A、B进行预分频的。
PCKB2—PCKB0是对B时钟源进行预分频。PCKA2 —PCKA0是对A时钟源进行预分频。这6位可以随时被读、被写。复位时置0。
其A时钟设置分频值如图6所示:
其B时钟设置分频值如图7所示:

图6  时钟A预分频选择值         图7  时钟B预分频选择值
2.5   PWMCAE寄存器
PWMCAE寄存器每一位如图8所示:
图8 PWMCAE寄存器
PWMCAE寄存器包含8个控制位来对每个PWM通道设置左对齐输出或居中对齐输出。如果CAEx置为1,则为居中对齐输出。如果置为0,则为左对齐输出。应当注意的是,只有输出通道被关闭后才能对其进行设置,即通道被激活后不能对其进行设置。
2.6   PWMCTL寄存器
PWMCTL寄存器每一位如图9所示:
图9  PWMCTL寄存器
此寄存器的2—7位为可读、可写位。只有当相应的通道关闭后,才能改变这些控制字。
控制字介绍:
PWMCTL_CON67=1;这时通道6、7就串联为同一个输出通道。此时只有7通道的控制字有用。例如:7通道的PWME寄存器决定了他们的输出情况,7通道的PWMPOL寄存器决定了他们是高电平翻转还是低电平翻转,7通道的PWMCLK寄存器决定了他们两个的时钟源,7通道的PWMCAE寄存器决定了他们是左对齐输出还是居中对齐输出等。
CON67=0 ;这时6,7通道分别作为独立输出通道对外输出。
CON45、CON23、CON01的用法同CON67相似。设置此控制字的意义在于扩大了PWM对外输出脉冲的频率范围。
PSWAI=1;则MCU一旦处于等待状态,就会停止时钟的输入。这样就不会因时钟在空操作而费电。当它置为0,则MCU就是处于等待状态,也允许时钟的输入。
2.7   PWMSCLA寄存器
PWMSCLA寄存器每一位如图10所示:
图10  PWMSCLA寄存器
时钟SA是通过对PWMSCLA寄存器的设置来对A时钟进行分频而产生的。
           Clock SA=Clock A /(2*PWMSCLA)
PWMSCLB寄存器同PWMSCLA寄存器相似,时钟SB就是通过对PWMSCLB寄存器的设置来对B时钟进行分频而产生的。
其计算公式为:
             Clock SB=Clock B /(2*PWMSCLB)
2.8   PWMCNTx寄存器
PWMCNTx寄存器共有8个,每一个通道都有一个。下面以PWMCNT0为例对PWMCNTx寄存器进行介绍。
PWMCNT0寄存器每一位如图11所示:
图11  PWMCNT0寄存器
计数器以所选时钟源的频率运行。计数器在任何时候都可以被读,而不影响计数,也不影响对PWM通道的操作。
任何值写入PWMCNT0寄存器都会导致计数器复位置0,且其计数方向会被设置为向上计数,并且会立刻从缓冲器载入任务和周期值,并会根据翻转极性的设置来改变输出。当计数器达到计数值后,会自动清零。只有当通道使能后,计数器才开始计数。此寄存器随时都可以对其进行读、写操作。
2.9   PWMPERx寄存器            
PWMPERx寄存器共有8个,每一个通道都有一个这样的周期寄存器。这个寄存器的值就决定了相关PWM通道的周期。每一个通道的周期寄存器都是双缓冲的,因此如果当通道使能后,改变他们的值,将不会发生任何作用,除非当下列情况之一发生:
*有效的周期结束。
*对计数器进行写操作(计数器复位成0)。
*通道不可用(PWMEx=0)。
这样就会使PWM输出波形要么是新波形要么是旧波形,并不会在两者之间进行交替变换。如果通道不可用,那么对周期寄存器进行写操作,将会直接导致周期寄存器同缓冲器一起闭锁。图12所示的是PWMPER0寄存器。
图12  PWMPER0寄存器。
周期的计算方法:
1) 当CAEx=0时,即进行左线性输出时:
PWMx周期=通道时钟周期*PWMPERx
2) 当CAEx=1时,即进行居中对齐输出时:
PWMx周期=通道时钟周期*(2*PWMPERx)
2.10  PWMDTYx寄存器
PWMDTYx寄存器也有8个,每一个通道都有一个这样的占空比常数寄存器。这个寄存器的值就决定了相关PWM通道输出波形的占空比。每一个通道的占空比寄存器都是双缓冲的,因此如果当通道被激活后,改变他们的值,将不会发生任何作用,除非当下列情况之一发生:
*有写操作(计数器复位成0)。
*通道没有被激活(P效的周期结束。
*对计数器进行WMEx=0)。

应当注意的是,在对PWMDTYx和PWMPERx进行设置时,PWMPERx寄存器的值应当大于PWMDTYx寄存器的值。

这样就会使PWM输出波形要么是新波形要么是旧波形,并不会在两者之间进行交替变换。如果通道没有被激活,那么对占空比常数寄存器进行写操作,将会直接导致周期寄存器同缓冲器一起闭锁。
当计数值与占空比常数PWMDTY相等时,则比较输出器有效,这时就会将触发器置位,然后PWMCNT继续计数,当计数值与周期常数PWMPER相等时,比较器输出有效,将触发器复位,同时也使PWMCNT复位,结束一个输出周期。
占空比的计算方法:
当PPOL=0时:
             占空比=[(PWMPERx—PWMDTYx)/ PWMPERx]*100%
当PPOL=1时:
占空比=(PWMDTYx/ PWMPERx)*100%







第三节  PWM应用实例3.1  周期和占空比计算举例
1   设CAEx=0;即为左线形输出。此时,设E=10 MHz(100 ns),PPOLx=0,PWMPERx=4  周期寄存器是4,PWMDTYx=1  。
则    PWMx输出频率=10 MHz/4=2.5 MHz  
      PWMx输出周期=1/(2.5  M)=400ns
      PWMx 占空比= 3/4=25%
公式总结:
     当为左线性输出时:
         PWMx输出频率=时钟频率/ PWMPERx
           当PPOLx=0时
           占空比=[(PWMPERx—PWMDTYx)/ PWMPERx]*100%
           当PPOLx=1时
占空比=[PWMDTYx/ PWMPERx]*100%
2   设CAEx=1;即为剧中线性输出。此时,设E=10 MHz(100 ns),PPOLx=0,PWMPERx=4,PWMDTYx=1。
则    PWMx输出频率=10 MHz/(4*2)=1.25 MHz
      PWMx输出周期=1/(1.25 M)=800ns
      PWMx 占空比= 3/4=25%
公式总结:
     当为居中线性输出时:
         PWMx输出频率=时钟频率/(2* PWMPERx)
           当PPOLx=0时
           占空比=[(PWMPERx—PWMDTYx)/ PWMPERx]*100%
          当PPOLx=1时
占空比=[PWMDTYx/ PWMPERx]*100%
应当注意的是,在对PWMDTYx和PWMPERx进行设置时,PWMPERx寄存器的值应当大于PWMDTYx寄存器的值。
3.2  PWM初始化步骤总结
1、禁止PWM  Disable PWM
PWME=0;
2、选择时钟 Select clock (prescaler and scale) for the PWM
PWMPRCLK,PWMSCLA,PWMSCLB,PWMCLK
3、选择极性  Select polarity
PWMPOL
4、选择对齐模式 Select center or left aligned mode
PWMCAE
5、对占空比和周期编程Program duty cycle and period
PWMDTYx, PWMPERx
6、使能PWM通道  Enable used PWM channels
PWME=1
3.3  PWM应用实例
例1:输出占空比为25%的波形
(1)实验设备:HCS12编程器、开发板、示波器
(2)软件程序设计:本例子是输出占空比为25%,周期为500Hz的波形。JPb8的0通道,开发板的地线和示波器相连。
(3)源程序如下:
#include <hidef.h>      /* common defines and macros */
#include <mc9s12dp256.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
void main(void)
{
  PWME_PWME0=0;   //关闭0通道
  PWMPRCLK=0X05;  //对总线时钟进行预分频,总线时钟为8M,分频后为250K
  PWMCLK_PCLK0=0; //设A为其时钟源
  PWMSCLA=0X7D;   //A时钟为2000Hz
  PWMPOL_PPOL0=1;//上升沿翻转
  PWMCAE_CAE0=0;//左对齐输出
  PWMDTY0=0X01; //占空比为25%的波形
  PWMPER0=0X04;  //输出为500Hz的波
  PWMCNT0=0X00;//0通道计数器清0
  PWME_PWME0=1;//0通道使能,0通道为输出通道
}
例2:步进电机的控制
(1)实验设备:HCS12编程器、开发板、步进电机、5804芯片、稳压电源
(2)功能实现:控制步进电机转动90度,按下中断后电机连续转动。
(3)源程序如下:
  1. #include <mc9s12dp256.h>     /* derivative information */

  2. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"

  3. int i=0;

  4. void main(void)

  5. {

  6.   DDRJ=0x00;

  7.   PIEJ=0X03;

  8.   EnableInterrupts; //中断设置

  9.   PWME=0;   //关闭所有通道

  10.   PWMCTL_CON01=1;//对PWM控制寄存器进行设置,0,1合为一个通道

  11.   PWMCNT1=0X00;//0,1通道计数器清0

  12.   PWMPOL_PPOL1=1;//上升沿翻转

  13.   PWMCLK_PCLK1=0; //设A为其时钟源

  14.   PWMPRCLK=0X00;  //不对A时钟进行分频

  15.   PWMCAE_CAE1=1;//中心对齐输出

  16.   PWMPER1=0X20;         

  17.   PWMPER0=0x4e;//per等于40000,即100赫兹

  18.   PWMDTY1=0X10;

  19.   PWMDTY0=0X27;//dty等于20000

  20.   PWME_PWME1=1;//0,1通道使能

  21. for(;i<=1854;)

  22. {

  23.   if(PWMCNT0==0X4e)

  24.   i++;

  25. }               //步进电机转90度

  26.   PWME=0;//0,1通道关闭

  27.   while(1){;}

  28. }

  29. #pragma CODE_SEG __NEAR_SEG NON_BANKED

  30. interrupt void man(void)

  31. {

  32.    if(PIFJ_PIFJ0==1)

  33.   {

  34.       PWMPER1=0X2a;         

  35.       PWMPER0=0x68;//per等于26666,即150赫兹

  36.       PWMDTY1=0X15;

  37.       PWMDTY0=0X34;//dty等于13333

  38.       PWME_PWME1=0xff;//0,1通道使能

  39.    }

  40. }

复制代码


第二章 ECT模块

第一节  ECT模块介绍1.1 简述
HC12增强型捕捉计时器模块在HC12标准定时器的基础上增加了一些特点,用以扩展它的应用范围,特别是在汽车ABS方面。
基准计时器的核心仍然是一个16位的可编程计数器,其时钟源来自一个预分频器。该计时器可以被应用于多个方面,包括在对输入波形进行测量的同时产生一个输出波形。波形的脉宽可以在几微秒到数秒的范围内变化。
对计数寄存器或者输入捕捉/输出比较寄存器的访问可以发生在一个时钟周期内。对这些寄存器分别访问其高字节和低字节与将它们作为一个字进行访问所获得的结果肯定不同。
1.2 特征
(1) 四个IC通道设置了16位保持寄存器,用于缓冲捕捉结果。
(2) 四个8位脉冲累加器、四个与缓冲IC通道关联的8位保持寄存器。四个8位脉冲累加器通道可以级联,形成两个16位的脉冲累加器。
(3) 具有4位定标器的16位递减模数计数器。
(4) 四个可选的延迟计数器用于增强输入抗干扰能力。
(5) 仅支持IP总线上的16位访问。
1.3 运行模式
停止:由于时钟停止,计时器和计数器均关闭。
冻结:计时器和计数器均保持运行,直到TSCR($06)的TSFRZ位被置1。
等待:计数器保持运行,直到TSCR($06)的TSWAI位被置1。
正常:计时器和计数器均保持运行,直到TSCR($06)的TEN位和MCCTL($26)的MCEN位被分别清0。
ECT增强模块的存储器图谱见表55。每一个列出的寄存器地是其地址的偏移量。总地址是ECT模块的基地址与偏移地址之和。
1.4 ECT的组成与工作模式
ECT具有8个IC/OC通道、4个8位或者2个16位的脉冲累加器(PAD通道,其OC部分与第6章的TIM模块相同,但IC及PAI部分与TIM模块有一定区别,其中4个IC通道与TIM模块相近,当相关引脚出现预定动作时,通过各自的捕捉寄存器TCn记录定时器的值;另外四个IC通道,除了捕捉寄存器TCn,还各有一个缓冲器TCnH,称为保持寄存器,可以在不产生中断的前提下,连续两次捕捉定时器的值。4个8位的PAl通道0-3与4个缓冲IC通道IC0-3相关联,并共享输入引脚PORTT0-3。每一个脉冲累加器通道都拥有一个缓冲器PACnH,也称为保持寄存器,可以在外部引脚出现预定动作时,保存它的累加值。两对8位的脉冲累加器还可以通过级联形成16位的脉冲累加器PACA、PACB。
16位递减模数计数器(MDC)是ECT增设的,它既是一个功能完善的定时器,具有独立的可程控定标器、自动重装载和中断能力,又可为IC、PAI寄存器向保持寄存器的传送提供定时控制信号。每当MDC回0时,将在给定的时间段内控制IC和PAI寄存器的内容向各自的缓冲寄存器传输。当然,MDC也可作为具有定时中断功能的独立时钟基准。
1.4.1  IC通道组
IC通道组由四个标准的缓冲通道IC0-IC3和四个非缓冲通道IC4-IC7组成,两部分的基本功能都是捕捉外部事件发生的时刻,但是缓冲通道除了IC/OC寄存器TCn外,还设有保持寄存器TCnH,此外还在入口设置了延迟计数器,用来提高抗干扰能力。非缓冲通道没有保持寄存器,入口也没有延迟计数器,但每个通道入口设置了一个2输入端的多路器,事件触发信号可以是来自本通道的输入引脚PORTn,也可以是来自其关联 通道PORT(n-4)的延迟计数器输出,使用更加灵活。当延迟功能有效时,输入引脚检测到一个有效的边沿后,延迟计数器开始对P时钟(模块时钟)进行计数,当到达设定的计数值后,延迟计数器在其输出端有条件地产生一个脉冲,这个条件就是延迟前后的引脚电平相反。这样可以避免对窄输入脉冲做出反应。延迟计数结束后,计数器自动清除。输入信号两个有效边沿之间的持续时间必须大于设定的延迟时间。
  在ECT中,所有IC通道均设置了覆盖保护功能,可以通过寄存器ICOVW设置是否允许某个通道用新的捕捉结果覆盖上一个结果。
对于缓冲的IC通道PT0-PT3,还具有锁存与队列两种工作方式。在锁存方式下,每个有效的引脚事件只将自由定时器的值放入捕捉寄存器TCn,而TCn到保持寄存器TCnH的传送必须依赖递减模数计数器回0或者其他强制锁存命令才能实现,这时IC的工作情形与第6章的TIM模块相似。在队列方式下(图7-2),TCn与TCnH形成了一个类似先进先出的队列,每个捕捉结果从TCn进入,然后随着下一个捕捉结果的到来移入TCnH,程序可以从TCnH取得结果,然而这个队列是开放的,即程序也可以直接从TCn取得捕捉结果。队列方式为CPU提供了充分的响应时间。
由于PAC0-3与IC0-3共享相同的引脚,而且共享入口的逻辑,因此在两种方式下,PAI与IC都可以同时工作,对同一引脚进行记录,前者记录脉冲或者边沿的数量,后者记录具体的时刻。
1.4.2  脉冲累加器
脉冲累加器由4个8位的通道PAC0-PAC3组成,可以通过级联形成两个 16位通道PACA、PACB,它可以统计输入引脚上出现的有效边沿的数量,也可以统计有效电平出现的累计时间。各个通道的8位保持寄存器是与4个缓冲IC通道相关联的,它们共享边沿检测与延迟电路。当IC工作在两种不同的队列方式时, PAC保持寄存器也处于不同的工作状态,在锁存方式下,PCnH的加载依靠MDC计数器或者强制命令实现,而在队列方式下,则依靠IC通道的TCnH读命令。可见在ECT模块下, IC与PAI的工作联系更加紧密。
此外,脉冲累加器还有饱和记忆功能,当8位的脉冲累加器计数超过$FF后记忆保持,而不回滚到0,这时,计数值$FF意味着计数已经达到或超过255,如不需要,该功能可以关闭。这可以用来监视某个通道的计数值是否已经达到预定的目标值。
值得注意的是,PACl、PAC0级联后,输入引脚为PT0,而PAC3、PAC2级联后,输入引脚并不是PT2,而是PT7,这样可以与那些无ECT的MCU保持一致性。
1.4.3  模数递减计数器
16位递减模数计数器(MDC)可以用作时钟基准,产生周期性的中断请求,也可用于将IC寄存器和脉冲累加器的值锁存到各自的保持寄存器中。锁存动作可以通过程序设定为周期性的或一次性的。MDC的时钟频率可通过独立的定标器设定,内部设有定时常数寄存器,可以实现自动重装载,但MDC的常数寄存器与MDC计数器使用相同的地址,加载时通过特殊的时序实现。
每当MDC回0时,将在给定的时间段内控制贮和PAI寄存器的内容向各自的缓冲寄存器传输。反映了MDC在IC、PAI系统中的作用。
1.5 ECT的工作过程与设置1.5.1  自由定时器、模数递减计数器与时钟频率设置
ECT的自由定时器与TIM模块基本相同,惟一的区别是TMSK2中的 PR2-PR0提供了7个预分频系数选项,包括1、2、4、8、16、32、64、128,而原来的TIM只提供了前6个选项,这样定时器时钟频率可以更低,周期更长。
ECT特有的模数递减计数器(MDC)逻辑结构,其核心为一个16位的递减计数器MDC($37、$36),其外围配备了常数寄存器MCCNT和预分频器,分别为其提供定时常数和时钟信号。当寄存器MCCTL中的MCEN=0时,MDC被复位成$FFFF,以避免在计数器启动的初期置位中断标志。将MCEN置1,MDC启动并从当前值开始对预分频器输出的时钟进行递减计数,分频系数为1、4、8、16可选,具体由MCCTL中的MCPR1 、 MCPRO确定(参看后面关于MCCTL的说明)。
MDC有两种工作方式,由MODMC决定,当MODMC=0时,MDC为单此计数方式,回到$0000后停止,反之为循环工作方式。
无论在那种方式下,当MDC计数回0后,首先置位寄存器MCFLG($27)的MCZF标志,若MCCTL中的中断允许位MCZI=1,则向CPU发出中断请求,中断矢量为$FFCC、 $FFCD,向MCFLG的MCZF位写1将清除该标志。MDC回0的另一个动作是向IC、PAC发出数据保持命令(参看IC、PAC部分),这是MDC的重要任务之一。此外在连续方式即 MODMC=1时,MDC回0后还将自动从MCCNT加载定时常数,但在单次方式即MODMC=0时,MDC回0后停止。
MCCNT与MDC占用相同的I/O地址($37、$36),由控制位RDMCL决定每次读操作的具体访问对象。当RDMCL=0/1时,读操作分别返回MDC和MCCNT的当前值。对 MCCNT的写操作要求在MODMC=1时进行,但MDC并不立即更新,必须等到计数器回0后重新加载,但向寄存器MCCTL($26)中的FLMC位写1可以实现MDC的立即加载,同时还将复位预分频器。如果MODMC:0,对地址$37、$36进行写入操作也将复位预分频器,并用写入值立即更新MDC计数器,然后开始一次递减计数,回到$0000后停止。可见在单次方式下可以直接指定定时常数,而在连续方式下则必须通过常数寄存器 MCCNT。
当寄存器ICSYS($AB)中的LATQ、BUFEN均为1时,如果将$0000写入到MCCNT和模数计数器,输入捕捉和脉冲累加寄存器将被锁存。将$0000写入到MCCNT后,模数计数器将保持为0,且不会将MCFLG中的MCZF标志置位。
1.5.2  IC通道组
IC通道分为缓冲与非缓冲两类,缓冲类又具有锁存与队列两种工作方式,下面分别介绍其逻辑结构与寄存器的设置。
1.缓冲的IC通道
缓冲的IC通道共有四个,即PT0-3,其最大特点是在捕捉寄存器TCn的基础上,又增加了保持寄存器TCnH,这样可以连续两次捕捉而不需要CPU干预。
单个缓冲IC通道主要由有效输入边沿检测、延迟滤波、捕捉与保持寄存器子系统等组成。当TIOS的IOS0=0,即PT0设置为IC输入后,每当PT0引脚的逻辑电平发生变化时,内部边沿检测电路首先对其进行判别,判别的规则由寄存器TCLA中的EDGOB、EDGOA决定,判别的结果送到延迟计数器进行滤波处理。所谓滤波,即启动延迟计数器开始对P时钟(模块时钟)进行计数,当到达预先设定的计数值后,延迟计数器在其输出端有条件地产生一个脉冲,这个条件就是延迟前后的引脚电平相反。这样可以避免对窄输入脉冲做出反应。延迟时间由寄存器DLYCT中的DLY1、DLY0控制,四个选项分别为0(旁路)、256、512、1024个P时钟周期。延迟计数结束后,计数器自动清除,输入信号两个有效边沿之间的持续时间必须大于选定的延迟时间。
延迟后的有效信号送到捕捉逻辑,然后根据ICOVW、ICSYS等相关位的设置决定是否捕捉TCNT的当前值以及是否处理保持寄存器TCOH,此外还要决定是否设置中断请求标志——寄存器TFLGl中的COF。一旦COF置位,如果COI=1且CCR中的I=1,CPU将会收到中断请求并予以响应,中断矢量为$FFEE、$FFEF。通过寄存器TFLG1向C0F写1将清除该标志位。对于锁存方式和队列方式,缓冲IC通道的捕捉条件和标志位的设置条件有所不同,下面将分别介绍。
(1)锁存方式。当设定为该方式时(LATQ=1),有效的引脚事件将主定时器值复制到寄存器TC0。在下述情况下,TC0还将被锁存到各自的保持寄存器中,这些情况包括模数计数器自然回0、向模数计数器直接写$0000、向控制寄存器MCCTL中的ICLAT位直接写1等。若寄存器ICOVW中的NOVWx位被清0,而这时出现新的捕捉事件,IC寄存器的内容将被新值覆盖。如果发生锁存操作,那么保持寄存器的内容也会被覆盖。若寄存器ICOVW中的NOVWx位被置1,  那么捕捉寄存器和保持寄存器必须处于 清空状态才允许写入,否则不能写入。这样可以避免读取或者转移到保持寄存器前,TC0被覆盖。
(2)队列方式(参看图7-2)。当设定为该方式时(LATQ=0),有效的引脚事件将主定时器值复制到IC寄存器。寄存器ICOVW中的NOVWx位被清0,而这时出现新的捕捉事件,IC寄存器的内容将被转移到保持寄存器。空出来的IC寄存器存放新的捕获值。若寄存器ICOVW中的NOVWx位被置1,那么捕捉寄存器和保持寄存器必须处于清空状态才允许写入,否则不能写入。在该方式下读保持寄存器TC0H会将相关的脉冲累加器值转移到对应的保持寄存器。在上述两种方式下,C3F-C0F中断标志的建立条件如图7-6所示。
2.非缓冲IC通道
这类通道与TIM模块相似,但是增加了覆盖控制位、入口处的延迟计数器及引入了双引脚控制(例如PT0)。当PT4引脚出现有效事件时,主定时器的值可能被记录到IC寄存器TC4,但是受覆盖控制寄存器ICOVW的影响,具体如下:
(1)如果输入覆盖控制寄存器ICOVW中的对应位NOVWx为0,当发生新的捕捉事件时,IC寄存器将用新的时间值覆盖上次捕捉结果。
(2)如果上述控制位为1,那么IC寄存器将不被覆盖,除非此时它处于清空状态。这可以阻止捕捉值在读取之前被覆盖掉。
1.5.3  脉冲累加器
ECT的四个8位的脉冲累加器可以独立使用,也可级联使用,这样可以满足不同的分辨率和通道数量要求。具体取决于PAEN、PBEN以及PAEN3-PAEN0的设置。当PAEN=PBEN=0时,PAC3-PAC0独立工作,当PAENn=1时,对应的PACn通道使能。当PAEN=1时,PAC3、PAC2级联成16位通道A,这时PAEN3、PAEN2无效,当PBEN=1时,PAC1、PAC0级联成16位通道B,这时PAEN1、PAEN0无效。级联后形成的通道A与TIM模块兼容,而通道B则功能相对简单。下面分别介绍级联前的四个8位通道PAC3-0、级联后的16位通道A和通道B各自的逻辑结构与设置。
1、8位通道PAC3-PAC0
PAC3-PAC0与IC联系十分密切,二者共享引脚、边沿检测和延迟计数电路,因此使用PAC通道时对应引脚必须通过寄存器TIOS设置为IC方式。
当TIOS中的IOS0、IOSl等于0时,PT0/PTl引脚信号进入边沿检测电路,有效边沿将被送到延迟计数部分进行窄脉冲消除,然后分别送到PACN0/PACNl,如果寄存器ICPACR中的PAENl、PAEN0为1,则PACNl、PACN0对输入进行计数。各通道的有效边沿可以通过寄存器TCL4单独设置,可选项包括切断、上升沿、下降沿和双向边沿,延迟时间则通过寄存器DLYCT设置,可选项包括0、256、512、 1024个P时钟周期,但所有通道共用一个延迟时间,不能分别设置。PACN3具有溢出中断功能,但PACN2没有,当PACN3从$FF回滚到$oo时,寄存器PBFLG中的PBOVF标志置 1,如果寄存器PBCTL中的PBOVI=1,同时CPU全局中断屏蔽位I=1,将向CPU申请中断,中断矢量为$FFCA、$FFCB。通过程序向PBOVF写1将清除该标志。
PAC3-PAC0通道设置了饱和记忆功能,当ICSYS中的PACMX=1时,该功能启动,这时如果某个通道计数器PACNx计数达到$FF,那么PACNx将停止对后续事件的计数,而保持在$FF,因此发现某个PACNx=$FF说明其计数结果大于或者等与255。
当ICSYS中的BUFEN=1时,保持寄存器PAlH、PAOH有效,用来保存PACN1、PACN0的累计结果,传送控制信号由MCCTL中的ICLAT或递减计数器MDC发出,但是与ICSYS中的LATQ有关。当BUFEN=0时,保持寄存器无效。
(1)脉冲累加器的锁存方式;当LATQ=1(锁存方式)时,模数递减计数器回0、将$0000写入模数计数器或者强制锁存控制位ICLAT被置1三者之一发生时,脉冲累加器的值将被转移到与它对应的保持寄存器,其自身同时清0。
(2)脉冲累加器的队列方式。当LATQ=0(队列方式)时,只在读取对应的IC通道的保持寄存器(TClH、TCOH)时,才会产生传送动作,其他的传送控制信号无效。
此外,PAC设置了覆盖限制功能,当保持寄存器为空时,将允许进行结果传送,但当保持寄存器非空时则禁止覆盖。覆盖控制通过寄存器ICSYS实现。
对于PAC2、PAC3,其逻辑结构与设置与PAC0、PAC1相似,只是涉及的某些寄存器不同,有关的设置这里不再赘述。
2、16位通道A
当寄存器PACTL中的PAEN=1时,通道PAC3、PAC2不复存在,PACN3、 PACN2级联成通道A(PAl),但为了与TIM保持一致,PAl仍然使用引脚PT7,而不使用引脚PT2,当然也不能使用PT2的边沿检测和延迟电路。该部分的工作过程与TIM的PAI完全相同。
3、16位通道B
当寄存器PBCTL中的PBEN=1时,通道PACl、PAC0不复存在,PACN1、 PACN0级联成通道B,它使用引脚PT0,因此仍然可以使用FT0的边沿检测和延迟电路,但没有门控时间累加方式,此外该通道只有溢出中断,这与通道A均不同。通道B只有事件计数方式,其他与通道A类似,读者可参看第6章的有关部分,这里不再赘述。
第二节  ECT寄存器简介2.1   ICOC选择寄存器(TIOS)
寄存器偏移量:$0000
Bit7      6        5        4       3       2       1      Bit0
IOS7
IOS6
IOS5
IOS4
IOS3
IOS2
IOS1
IOS0
复位后:0      0        0       0        0       0      0       0
可在任何时候读或写。
TIOS寄存器用于指定各个通道的功能,即工作于IC还是OC方式。当某个位IOSn=0时,对应的通道n为输入捕捉(1C)通道,否则当IOSn=1时,通道n为输出比较(OC)通道。其中的各位可以在任何时候写入或读出。上电后该寄存器默认为$00,TSCR中的TEN默认也为0,这时所有通道处于通用I/O方式,将TEN置位后各个通道进入IC方式,要将某些通道设置成OC方式,必须对TIOS进行设置,即将有关位置1。设置成OC的通道其引脚具有降功率驱动功能,设置成IC的通道具有内部上拉功能,但上电后均处于关闭状态,可以根据需要启用。
2.2   输出比较通道7屏蔽寄存器(OC7M)
寄存器偏移量:$0002
Bit7     6       5       4        3        2      1      Bit0
OC7M7
OC7M6
OC7M5
OC7M4
OC7M3
OC7M2
OC7M1
OC7M0
复位后:0      0       0        0         0       0      0      0
可在任何时候读或写。
前面已经说明,OC7具有特殊地位,它匹配时可以直接改变其他7个输出引脚的状态,并覆盖各个引脚原来的匹配动作结果,寄存器OC7M决定哪些通道将处于OC7的管理之下。 OC7M中的各位与PORTT口寄存器的各位一一对应。当通过TIOS将某个通道设定为输出比较时,将OC7M中的相应位置1,对应的引脚就是输出状态,与DDR中的对应位的状态无关。但OC7Mn并不改变DDR相应位的状态。
OC7M具有更高的优先级,它优于通过TCTL1和TCTL2寄存器中的OMn和OLn设定的引脚动作,若OC7M中某个位置1,就会阻止相应引脚上由OM和OL设定的动作。
2.3   输出比较通道7数据寄存器(OC7D)
寄存器偏移量:$0003
Bit7     6       5       4        3        2       1     Bit0
OC7D7
OC7D6
OC7D5
OC7D4
OC7D3
OC7D2
OC7D1
OC7D0
复位后:0      0       0        0        0       0      0        0
可在任何时候读或写。
OC7M对于其他OC输出引脚的管理限于将某个二进制值送到对应引脚,这个值保存在寄存器OC7D中的对应位中。当OC7匹配成功后,若某个OC7Mn=1,则内部逻辑将OC7Dn送到对应引脚。
OC7D中的各位与PORTT口寄存器的各位一一对应。当通道7比较成功时,如果OC7M中的某个位为1,OC7D中的对应位将被输出到PORTT的对应引脚。
当OC7M中的某个位为1时,通道7匹配成功的动作如果与通道6-0的动作发生在同一个周期,前者将覆盖后者。因此各个通道的动作将依赖于OC7D中各个位的设置。
2.4   定时器核心寄存器(TCNT)
寄存器偏移量:$0004-$0005
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0      0       0        0         0       0       0      0
TCNT是递增计数器,它不停地对内部时钟信号计数、程序可随时读取,但在普通模式下禁止写入。TCNT应按字访问,分别访问高、低字节可能得到错误的结果。
在特殊模式下,TCNT可写,但因为写操作与预分频器时钟不同步,TCNT寄存器写入后,其第一个周期可能是一个不同的值。
2.5   计时器系统控制寄存器1TSCR1
寄存器偏移量:$0006
Bit7      6        5       4       3       2        1      Bit0
TEN
TSWAI
TSFRZ
TFFCA




复位后:0       0       0        0        0      0       0        0
可在任何时候读或写。
TSCR1寄存器是定时器模块的总开关,它决定模块是否启动以及在中断等待、BDM方式下的行为,还包括标志的管理方式。其各位的意义如下:
TEN:定时器使能位,此外它还控制定时器的时钟信号源。要使用定时器模块的IC/OC功能,必须将TEN置位。如果因为某种原因定时器没有使能,脉冲累加器也将得不到ECLK/64时钟,因为ECLK/64是由定时器的分频器产生的,这种情况下,脉冲累加器将不能进行引脚电平持续时间的累加。
0:主计时器、包括计数器均被禁止,有利于降低功耗。
1:定时器使能,正常工作。
TSWAI:等待模式下计时器关闭控制位。
注意定时器中断不能用于使MCU退出等待模式。
0:在中断等待模式下允许MCU继续运行。
1:当MCU进入中断等待模式时,禁止计时器。
TSFRZ:在冻结模式下计时器和计数器停止位。
0:在冻结模式下允许计时器和计数器继续运行。
1:在冻结模式下禁止计时器和计数器,用于仿真调试。
注意:TSFRZ不能停止脉冲累加。
TFFCA:定时器标志快速清除选择位。
0:定时器标志普通清除方式。
1:对于TFLGl($0E)中的各位,读输入捕捉寄存器或者写输出比较寄存器会自动清除相应的标志位CnF。
对于TFLG2($0F)中的各位,任何对TCNT寄存器($04、$05)的访问均会清除TOF标志;任何对PACN3和PACN2寄存器($22,$23)的访问都会清楚清除PAFLG寄存器($21)中的PAOVF和PAIF位。任何对PACN1和PACN0寄存器($24,$25)的访问都会清除PBFLG寄存器($21)中的PBOVF位。这种方式的好处是削减了另外清除标志位的软件开销。此外,必须特别注意避免对标志位的意外清除。
2.6   计时器溢出绑定寄存器1TTOV
寄存器偏移量:$0007
Bit7      6       5       4       3        2       1      Bit0
TOV7
TOV6
TOV5
TOV4
TOV3
TOV2
TOV1
TOV0
复位后:0       0       0      0        0        0        0       0
可在任何时候读或写。
TOVx:溢出绑定管脚标志位。
TOVx在输出比较时,如果发现溢出,则绑定该管脚。这一功能仅在输出比较模式下有效,它的优先级高出强制输出比较,而低于通道7的输出比较。
0:输出比较的管脚发生溢出时绑定功能不发生作用。
1:输出比较的管脚发生溢出时绑定功能使能。
2.7   控制寄存器(TCTLl-TCTL4
TCTL1    寄存器偏移量:$0008
Bit7      6       5       4       3        2      1      Bit0
OM7
OL7
OM6
OL6
OM5
OL5
OM4
OL4
复位后:0       0       0        0       0        0      0       0
TCTL2    寄存器偏移量:$0009
Bit7      6       5       4       3        2        1     Bit0
OM3
OL3
OM2
OL2
OM1
OL1
OM0
OL0
复位后:0       0      0        0       0       0       0       0
TCTL3    寄存器偏移量:$000A
Bit7      6       5       4       3        2      1       Bit0
EDG7B
EDG7A
EDG6B
EDG6A
EDG5B
EDG5A
EDG4B
EDG4A
复位后:0       0         0      0       0       0      0       0
TCTL4    寄存器偏移量:$000B
Bit7     6        5       4       3        2      1     Bit0
EDG3B
EDG3A
EDG2B
EDG2A
EDG1B
EDG1A
EDG0B
EDG0A
复位后:0      0       0        0        0       0       0       0
可在任何时候读或写。
TCTLl-TCTL4分为两组,分别对IC和OC电路进行设定,每组16个二进制位,每两个二进制位管理一个通道。其中TCTLl、TCTL2设定各个OC通道匹配时的动作,包括切断OC与输出引脚的联系,而TCTL3、TCTL4设定IC响应引脚的何种动作,包括禁止IC的响应。各个控制位的作用如下:
OMn、OLn 分别设定输出方式和输出电平,这8对控制位(OM7、OL7-OMO、OL0)编码后用于指定通道比较成功后的输出动作(参看表7-3)。如果每对当中至少有一个为1,对应引脚就固定为相应通道的输出,而与DDRT中的对应位无关。当二者同时为0时,OC与输出引脚断开。
表7-3  输出比较动作设置
OMn
OLn
动作
0
0
定时器与输出引脚断开
0
1
OCn输出翻转
1
0
OCn输出清0
1
1
OCn输出置1
EDGnB、EDGnA 输入捕捉边沿控制位,这8对控制位(EDG7B、EDG7A—EDGOB、EDGOA)对输入捕捉的边沿检测电路进行设置(参看表7-4)。当二者同时为0时,IC与输入引脚断开。
表7-4 输入捕捉边沿检测电路设置
EDGnB
EDGnA
边沿检测器电路设置
0
0
捕捉禁止
0
1
仅捕捉上升沿
1
0
仅捕捉下降沿
1
1
上升、下降沿均捕捉
    注意:为了使OMn、OLn指定的引脚动作有效,OC7M中的对应位必须清0。若要使用16位脉冲累加器A和B,并使它们分别独立于IC/OC7和IC/OC0,必须设置对应的IOSn:1、OMn=0、OLn=0,同时寄存器OC7M中的C7M7、OC7M0位必须清0。
2.8   计时器中断使能寄存器(TIE
寄存器偏移量:$000C
Bit7      6       5       4       3        2       1     Bit0
C7I
C6I
C6I
C4I
C3I
C2I
C1I
C0I
复位后:0       0       0        0       0       0       0       0
可在任何时候读或写。
TIE寄存器中的位与状态寄存器TFLG1中的标志位相对应。如果将TIE中的某位清0,相应的标志位就不能引起硬件中断。如果被置1,相应的标志位就可以引起中断。
C7I-C0I:输入捕捉/输出比较“x”中断使能。
2.9   计时器系统控制寄存器2(TSCR2)
寄存器偏移量:$000D
Bit7      6      5       4        3       2        1     Bit0
TOI
0
0
0
TCRE
PR2
PR1
PR0
复位后:0       0       0        0       0        0      0       0
可在任何时候读或写。
TOI:计时器溢出中断使能。
0:中断被禁止。
1:当TOF标志被置位时发出硬件中断请求。
TCRE:时钟计数器复位使能。
该位在通道7成功输出比较之后允许时钟计数器复位。该操作模式类似于递增型计数器。
0:计数器复位禁止,计数器自由计数。
1:通道7成功输出比较后计数器将被复位。
如果TC7=$0000并且TCRE=1,TCNT将继续保持$0000。
如果TC7=#FFFF并且TCRE=1,当TCNT从$FFFF到$0000之间被复位后TOF将永远不被置位。
PR2,PR1,PR0:计数器预分频选择。
这三位所决定的分频因子如下表所示。
表7-5  分频因子选择
PR2
PR1
PR0
Prescale Factor
0
0
0
1
0
0
1
2
0
1
0
4
0
1
1
8
1
0
0
16
1
0
1
32
1
1
0
64
1
1
1
128
新设定的分频因子不会立即起作用,直到下一个触发沿到来那里所有预分频计数器值均为零。
2.10  主定时器中断标志寄存器(TFLG1TFLG2)
TFLG1    寄存器偏移量:$000E
Bit7      6       5       4       3       2       1     Bit0
C7F
C6F
C5F
C4F
C3F
C2F
C1F
C0F
复位后:0       0       0        0       0       0       0       0
TFLG2    寄存器偏移量:$000F
Bit7      6         5       4       3       2      1     Bit0
TOF
0
0
0
0
0
0
0
复位后:0       0       0        0       0       0       0       0
所示的TFLG1、TFLG2为中断标志寄存器,其中TFLG1对应8个IC/OC通道,当某CnF=1时说明对应的IC/OC通道有动作。TFLG2只有一个标志位TOF,作为核心计数器的中断请求标志。当TOF=1时说明核心计数器溢出。要清除某个标志位,只需向该位写1,向某位写0不影响该位的状态。当TSCR中的TFFCA位置位时,读IC通道或写OC通道 ($10-$1F)将自动清除该通道标志CnF,对TCNT的任何访问将自动清除TFLG2。
CnF:IC/OC通道中断请求标志。
0:上次清除标志以来,IC/OC通道没有有效动作。
1:IC/OC通道已经出现动作。将寄存器ICSYS($2B)中的TFMOD位和ICOVW寄存器($2A)联合使用,可以使定时器在两次捕捉后才产生中断,而不是每次捕捉均产生动作。两次捕捉结果分别在捕捉和保持寄存器里面。
TOF:定时器溢出标志,当16位自由定时器从$FFFF回滚到$0000时,该位置位。将$80写入到TFLG2将自动清除该位。详见前面关于TMSK2中TCRE控制位的解释。
2.11  ICOC寄存器(TC0-TC7)
每个IC或OC通道都设置有一个16位的寄存器,对于IC(输入捕捉)通道,当通道的边沿探测器检测到由EDGnA、EDGnB指定的条件时,将自由定时器的值捕捉到寄存器TCn,随后程序可以读取和处理;对于OC(输出比较)通道,程序将预定的时刻写入到TCn,当自由定时器的值与其相等时,触发由OMn、OLn所指定的输出动作。定时器模块共有 TC7-TC0等8个16位IC/OC寄存器。
对于设定为IC的通道,相应通道写操作无意义。上述所有寄存器复位后为$0000。
TC0    寄存器偏移量:$0010-$0011
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0        0       0      0
TC1    寄存器偏移量:$0012-$0013
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0       0        0       0
TC2    寄存器偏移量:$0014-$0015
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0       0       0       0
TC3    寄存器偏移量:$0016-$0017
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0       0       0       0
TC4    寄存器偏移量:$0018-$0019
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0       0       0       0
TC5    寄存器偏移量:$001A-$001B
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0       0       0       0
TC6    寄存器偏移量:$001C-$001D
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0       0       0       0
TC7    寄存器偏移量:$001E-$001F
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0       0       0        0       0       0       0       0
2.12  脉冲累加器A控制寄存器(PACTL)
寄存器偏移量:$0020
Bit7     6      5       4       3         2        1     Bit0
0
PAEN
PAMOD
PEDGE
CLK1
CLK0
PAOVI
PAI
复位后:0       0       0        0       0      0        0       0
可在任何时候读或写。
寄存器PACTL决定了PAI的工作方式及其参数,还包括PAI的启动、确定定时器系统的时钟信号源、中断管理等。其各位作用如下:
PAEN:脉冲累加系统使能位,该位与TEN相互独立。PAEN=1时,PAl的输入部分才进行引脚信号检测,同时8位脉冲累加器PAC3、PAC2被禁止。
0:PAI系统禁止。
1:PAI系统使能。
PAMOD:脉冲累加器模式控制位。当TEN=0时,没有ECLK/64时钟,如果启动PAI,
它只能工作在事件计数方式。
0:事件计数模式。   
1:门控时间累加模式。这时TEN必须为1。
PEDGE:脉冲累加器有效边沿设定位,该位的作用效果与PAMOD的状态有关。
(1)PAMOD:0  (事件计数模式)时:
0:对脉冲输入引脚(PT7/PAI)的下降沿计数。
1:对脉冲输入引脚(PT7/PAI)的上升沿计数。
(2)PAMOD:1  (门控时间累加模式)时:
0:当脉冲输入引脚(PT7/PAI)为高电平时,允许ECLK/64时钟脉冲计入脉冲累加器,并在随后的输入引脚下降沿置位PAIF标志。
1:当脉冲输入引脚(PT7/PAI)为低电平时,允许ECLK/64时钟脉冲计入脉冲累加器,并在随后的输入引脚上升沿置位PAIF标志。
CLKI、CLK0:定时器模块时钟选择位,如果脉冲累加器被禁止(PAEN:0),来自定时器的预分频器时钟总是作为定时计数器的时钟源。时钟源的改变在这两位写入后立即生效。其作用见表7-6。
表7-6  时钟选择
CLK1
CLK0
定时计数器时钟源
0
0
预分频时钟
0
1
PACLK
1
0
PACLK/256
1
1
PACLK/65536

PAOVI:脉冲累加器溢出中断允许位。
  0:禁止溢出中断。
  1:当PAOVF置位时申请中断。
PAI:脉冲累加器输入中断允许位。
0:禁止输入中断
1:当PAIF置位时申请中断。
2.13  脉冲累加器A标志寄存器(PAFLG)
寄存器偏移量:$0021
Bit7     6       5       4        3        2       1     Bit0
0
0
0
0
0
0
PAOVF
PAIF
复位后:0      0       0        0        0       0       0       0
可在任何时候读或写。
PAI子系统可能产生两种中断,累加器溢出和事件中断。当PACNT溢出时,先置位PAOVF,当PAOVI=1时将发出中断请求。而PAIF则在PAI检测到有效事件时置位,当PAI=1时还将发出中断请求。当TSCR寄存器中的TFFCA=1时,  访问PACNT将清除 PAFLG中的所有标志位。PAOVF、PAIF位于寄存器PAFLG中,其意义如下:
PAOVF:脉冲累加器溢出标志位。
0:上次清除以来,PACNT没有回滚到$0000。
1:PACNT从$FFFF回滚到$0000。将$02写入到PAFLG将自动清除该位。PAIF:脉冲累加器输入边沿有效标志位。
0:上次清除以来,PAI引脚尚未检测到预期的有效边沿。
1:在输入引脚检测到有效边沿。在事件计数模式下,选定的有效边沿在计数的同时触发该位置1;在门控时间累加模式下,输入引脚门控信号的后沿触发该位置1,将$01写入到PAFLG将自动清除该位.
2.14  脉冲累加寄存器(PACN3PACN2PACN1PACN0)
PACN3     寄存器偏移量:$0022
Bit7
6
5
4
3
2
1
Bit0
复位后:0      0        0       0        0       0       0        0
PACN2     寄存器偏移量:$0023
Bit7
6
5
4
3
2
1
Bit0
复位后:0       0       0       0        0       0       0        0
PACN1     寄存器偏移量:$0024
Bit7
6
5
4
3
2
1
Bit0
复位后:0      0       0        0        0       0       0       0
PACN0     寄存器偏移量:$0025
Bit7
6
5
4
3
2
1
Bit0
复位后:0      0       0        0        0       0       0       0
可在任何时候读或写。
PACN3、PACN2、PACN1、PACN0是四个8位的寄存器,PAC3、PAC2级连后形成PACA, PAC1、PAC0级连后形成PACB,它们反映外部事件或者时间的累计结果,程序可以随时读取或通过写入设定初始值。当PACA/PACB允许  (PACTL:$20寄存器中的PAEN=1/PBCTL:$30寄存器中的PBEN=1)时,寄存器PACN3、PACN2/PACNl、PACN0分别是PACA、 PACB的高、低位字节,当PACNl从$FF回滚到$00,寄存器PBFLG($31)中的PBOVF中断标志置1。
正确的寄存器访问方式是在单个时钟周期内完成,即采用字读写指令。分开访问高/低位字节可能得到错误的结果。但如果只需要寄存器的高8位或低8位,则读操作不受限制,但写操作仍需要注意。
2.15  模数递减计数器控制寄存器(MCCTL)
寄存器偏移量:$0026
Bit7    6        5       4         3      2       1      Bit0
MCZI
MODMC
RDMCL
ICLAT
FLMC
MCEN
MCPR1
MCPR0
复位后:0      0       0        0        0       0      0        0
可在任何时候读或写。
该寄存器主要控制MDC及相关操作。各位意义及作用如下:
MCZI:  模数计数器下溢出中断允许位。当MDC回0标志MCZF置位时,是否申请中断取决于MCZI。
0:禁止中断。
1:允许中断。
MODMC:模数方式允许位。该位设定MDC的工作方式,即选择单次或模数循环方式。
0:  单次计数方式,计数器从设定值递减到0后停止。
1:  模数计数方式,当计数器递减回0后,加载最新设定值,并开始新一轮计数过程。
注意:为保证正确运行,修改MODMC位之前,必须清除MCEN位使模数计数器复位到$FFFF。
RDMCL:模数读取选择位。该位决定读模数寄存器返回的内容。
0: 返回模数计数器的当前值。
1: 返回重新加载所用的常数。
ICLAT:捕捉寄存器强制转移控制位。当输入捕捉工作在锁存方式时(ICSYS($2B)寄存器中的LATQ和BUFEN位置位),向该位写1立即强制将捕捉寄存器TC0-TC3以及对应的8位脉冲累加器的内容转移到保持寄存器,同时相关的脉冲累加器自动清0。向该位写0无效,读该位总是返回0。
FLMC:模数计数器强制加载控制位。该位只在模数递减计数器允许时(MCEN=1)有效,向该位写1将把模数常数寄存器的值加载到模数计数器,同时复位模数计数器的定标器。向该位写0无效。
当MODMC=0时,计数器开始计数,并在到达$0000后停止。读该位总是返回0。
MCEN:模数递减计数器允许位。当MCEN=0时,计数器被预置为$FFFF,这可以避免在计数器启动的初期出现中断标志。
0: 模数计数器禁止运行。
1: 模数计数器使能。
MCPR1、MCPR0:模数计数器定标器分频常数设定位。设定的分频常数不能立即起作用,必须等到模数计数器进行加载操作。当MCPR1、MCPR0=00、01、10、11时,对应的分频常数分别为1、4、8、16。
2.16  输入脉冲累加器控制寄存器(ICPAR)
寄存器偏移量:$0028
Bit7    6        5        4       3        2      1      Bit0
0
0
0
0
PA3EN
PA2EN
PA1EN
PA0EN
复位后:0     0        0        0        0       0       0       0
可在任何时候读或写。
8位脉冲累加器PAC3、PAC2只有在PACTL($20)中的PAEN=0时,才能被允许,若PAEN=1,PA3EN和PA2EN无效。同样,8位脉冲累加器PACl、PAC0只有在PBCTL($30)中的PBEN=0时,才能被允许,若PBEN=1,PAlEN和PAOEN无效。当PAxEN=1时,对应的8位脉冲累加器通道x使能,反之则禁止。
2.17  输入覆盖控制寄存器(ICOVW)
寄存器偏移量:$002A
Bit7     6       5        4       3        2      1      Bit0
NOVW7
NOVW6
NOVW5
NOVW4
NOVW3
NOVW2
NOVW1
NOVW0
复位后:0      0        0       0        0       0       0       0
可在任何时候读或写。
该寄存器共有8个覆盖禁止位,对应8个IC通道,用来选择上次捕捉结果是否允许被覆盖。如果某位NOVWx=0,新的捕捉事件或转移动作发生时,不论捕捉或保持寄存器是否为空,均直接保存新的结果:反之若NOVWx:1,对应的寄存器不允许被覆盖,但若处于空白状态则仍然允许覆盖。这样可以避免捕捉结果在被读取或者转移到保持寄存器前丢失。
2.18  输入系统控制寄存器(ICSYS)
寄存器偏移量:$002B
Bit7     6       5       4        3        2       1     Bit0
SH37
SH26
SH15
SH04
TFMOD
PACMX
BUFEN
LATQ
复位后:0      0       0        0        0       0       0       0
可在任何时候读。
可能一次可写(test mode=0时)但是当test mode=1时,写总是被允许的。
该寄存器用于对IC和PAC部分的工作进行设置与控制。其各位意义和作用如下:
SHxy:  x、y通道输入共享控制位。
0:  x、y通道正常工作,各自使用对应的引脚。
1:  通道x的边沿检测电路及延迟电路同时作用于x、y通道,即在y通道上也引发与x通道相同的动作。
TFMOD:  标志设置方式控制位,寄存器ICSYS($2B)中的TFMOD位与寄存器ICOVW($2A)一起使用可以使定时器的中断在捕捉到两个事件后才产生,而不是每次捕捉事件都产生中断,两次捕捉的结果分别存放在捕捉和保持寄存器中。如果在队列方式下将TFMOD置1,同时NOVW置位且某通道n的捕捉和保持寄存器均为空白状态,那么第一个捕捉事件将首先用主定时器值更新对应的输入捕捉寄存器 TCn,下一个事件发生时,TCn中的数值将首先被转移到保持寄存器TCnH,然 后  更新TCn。这时,CnF中断标志才被置位。
在所有其他的输入捕捉情况下,PTn引脚发生的有效外部事件将置位中断标志。
0:  当对应的输入引脚满足预定的捕捉条件时,寄存器TFLGl($0E)中的标志C3F-COF将被相应置位。
1:  如果在队列方式下  (BUFEN=1且LATQ=0),那么标志位C3F-COF只有在对应的保持寄存器被填充后才置位。如果没有启用队列方式,那么标志位C3F-COF的置位条件与TFMOD:0时相同。
PACMX:  8位脉冲累加器饱和控制位,即选择计数到$FF后是否保持不变。饱和功能允许时$FF就代表计数值已经达到255或更多。换言之,可记忆是否曾经达到$FF。
0:  正常工作,计数达到$FF后,下一计数使其回到$oo。
1:  计数达到$FF时,停止加1操作,即进入饱和状态。
BUFEN: IC缓冲允许位。
0:  禁止IC及PAC的保持寄存器。
1:  IC及PAC保持寄存器使能。锁存方式由控制位LATQ设定,当位LATQ=1时,向寄存器MCCTL($26)中的ICLAT位写1,将导致捕捉寄存器和脉冲累加器将其中数值转移到各自的保持寄存器。
LATQ:  输入锁存及队列方式允许位。当控制位BUFEN=1时,IC和PAC的保持寄存器使能,反之不能通过LATQ进入锁存方式。当LATQ、BUFFEN同时为1时,向MCCTL($26)中的ICLAT位写1,IC和PAC寄存器内容将转移到保持寄存器。
0:  IC工作在队列方式。当输入引脚满足预定的捕捉条件时,主定时器的值被记录到捕捉寄存器,当下一个捕捉事件出现时,捕捉寄存器将其内容转移到保持寄存器,以便存放新的捕获值。
1:  IC工作在锁存方式。当模数计数器自然回0,或者向计数器MCCNT直接写$0000时,将进行锁存操作,结果,捕捉寄存器和脉冲累加器将其内容转移到保持寄存器,同时8位的脉冲累加器清0。
2.19  脉冲累加器B控制寄存器(PBCTL)
寄存器偏移量:$0030
Bit7     6       5        4        3       2       1     Bit0
0
PBEN
0
0
0
0
PBOVI
0
复位后:0     0        0        0        0       0       0       0
可在任何时候读或写。
16位的脉冲累加器B(PACB)系两个8位的脉冲累加器PACl和PAC0级连后形成的。当PBEN置1时,PACB启动,它与IC0共享同一个输入引脚。
PBEN:  脉冲累加器B使能位,它与TEN相互独立。只要PBEN=1,脉冲累加器B即可工作,与定时器是否允许无关,这与脉冲累加器A不同。
0:  脉冲累加器B禁止。8位的PACl和PAC0可通过各自的允许位(在寄存器ICPACR中,地址$28)使能。
1: 脉冲累加器B使能。实际上PACB为PACl、PAC0级连形成,PACl为高位、而PAC0为低位字节,这时寄存器ICPACR中的控制位PAlEN、PAOEN无效。
PBOVI: 脉冲累加器B溢出中断允许位。
0:  禁止PBOVF申请中断。
1:  当PBOVF=1时,申请中断。
2.20  脉冲累加器B标志寄存器(PBFLG)
寄存器偏移量:$0031
Bit7     6       5        4       3        2       1     Bit0
0
0
0
0
0
0
PBOVF
0
复位后:0     0        0        0        0       0       0       0
可在任何时候读或写。
该寄存器只有一个标志位PBOVF,当16位的PACB从$FFFF回滚到$0000,或8位脉冲累加器3(PACl)从$FF回滚到$00时,该位置1。将$01写入PBFLG清除该位。当寄存器TSCR($06)中的TFFCA位置位时,访问PACNl和PACN0清除该标志。
2.21  脉冲累加器保持寄存器(PA3H-PA0H
PAC3H     寄存器偏移量:$0032
Bit7
6
5
4
3
2
1
Bit0
复位后:0     0        0        0        0       0       0       0
PA2H     寄存器偏移量:$0033
Bit7
6
5
4
3
2
1
Bit0
复位后:0      0       0        0        0       0       0       0
PA1H     寄存器偏移量:$0034
Bit7
6
5
4
3
2
1
Bit0
复位后:0     0        0        0        0       0       0        0
PA0H     寄存器偏移量:$0035
Bit7
6
5
4
3
2
1
Bit0
复位后:0     0        0        0        0       0       0      0
可在任何时候读。写不起作用。
当ICPACR($28)中PAnEN=1时,通道PAn使能,寄存器PA3H-PAOH用于为PAn提供锁存功能。
2.22  模数递减计数器工作寄存器(MCCNT)
寄存器偏移量:$0036-$0037
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:1      1       1        1        1       1       1       1
MDC启动后,MCCNT用来对定标器输出的时钟进行递减计数,也可作为定时基准。对该寄存器的访问应在一个时钟周期内完成,即按字访问。对高低位字节分别访问可能得到错误的结果。如果MCCTL中的RDMCL=0,读MCCNT寄存器返回计数器的当前值;反之如果RDMCL=1,返回每次重新加载所用的常数。
当寄存器ICSYS($2B)中的LATQ、BUFEN均为1时,如果将$0000写入到MCCNT和模数计数器,输入捕捉和脉冲累加寄存器将被锁存。将$0000写入到MCCNT后,模数计数器将保持为0,且不会将MCFLG中的MCZF标志置位。
如果模数方式允许(MODMC=1),对该地址进行写操作将更新常数寄存器,但计数器不会立即更新,必须等到计数器回0后重新加载;如果希望立即加载,通过寄存器MCCTL ($26)中的FLMC位可以将新值立即加载到计数器。如果模数方式未允许(MODMC=0),写该地址将清0定标器,并用写入值立即更新计数器,然后开始一次递减计数,到0后停止。
2.23  IC保持寄存器(TC0H-TC3H
TCOH    寄存器偏移量:$0038-$0039
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0     0        0        0        0       0       0       0
TC1H    寄存器偏移量:$003A-$003B
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0      0       0        0        0       0       0       0
TC2H    寄存器偏移量:$003C-$003D
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0      0       0        0        0       0       0       0
TC3H    寄存器偏移量:$003E-$003F
Bit15
Bit14
Bit13
Bit12
Bit11
Bit10
Bit9
Bit8
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
复位后:0      0       0        0       0        0       0       0
这些寄存器用于为相应的捕捉寄存器TC0-TC3提供锁存功能。
定时器与I/O共享引脚的说明
定时器与PORTT共享8个I/O引脚,复位后各个引脚默认为通用输儿输出,当定时器相关功能使能后,将取代通用I/O功能。引脚PT0-3由IC/OC、PAC及通用I/O共享,引脚 PT4-7由IC/OC及通用I/O共享,此外引脚PT0、PT7还供16位脉冲累加器A、B作为输入使用。其他请参看第6章TIM模块有关说明,不再赘述。
不同模式下的定时器及模数计数器的运行状况
    (1)停止(STOP):因为PCLK和ECLK均已停止,定时器和模数计数器关闭。
    (2)调试方式(BDM):只要不满足TSBCK=1,定时器保持运行。
    (3)中断等待(WAIT):只要不满足TSWAI=1,计数器保持运行。
    (4)正常(Normal):只要不满足TEN=0和MCEN(MCCTL中)=0,定时器保持运行。
    (5)禁止(TEN=0):定时器和MDC停止,但寄存器可访问。ECLK/64时钟被禁止。
    (6)禁止(PAEN=0):所有的脉冲累加器动作停止,但寄存器可以访问。
    (7)MCEN:0:模数计数器停止。
    (8)PAEN:1:16位脉冲累加器A激活。
    (9)PAEN:0:8位脉冲累加器3和2可以激活。
    (10)PBEN:1:16位脉冲累加器B激活。
    (11)PBEN:0:8位脉冲累加器1和0可以激活。
第三节  ECT应用实例3.1  定时器编程步骤
1、初始化:
设定预分频系数,设定工作方式,定时器溢出中断使能,定时器使能
2、中断函数
用户自己的代码,清标志位
void ECT_Init(void)
{
   TSCR2_PR   = 7;  //预分频系数为8
   …………………..
   TSCR2_TOI  = 1;  //定时器溢出中断使能
   TSCR1_TEN  = 1;  //定时器使能
}
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void TimerOverFlow(void)
{
     //用户自己的代码
TFLG2_TOF  = 1;  //清楚定时器溢出中断标志位
}
3.2  输入捕捉IC
本试验的辅助设备有:信号发生器、示波器。
试验目的:通过连续记录输入信号的两个上升沿,用该程序可以计算出输入信号的频率;同时,利用脉冲累加器可以记录输入脉冲数。
#include <hidef.h>      /* common defines and macros */
#include <mc9s12dp256.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
    int count=0;
    float f;
    double f1=2000000,first=0,second=0,n,N;
    void main(void)
    {      
       DisableInterrupts;      
       TSCR2=0X82;
       PACTL=0X20;      
       TIOS=0XFE;    //设定pt0输入捕捉口
       TCTL4=0X01;
       ICSYS=0X0A;
       PBCTL_PBEN=0X00;      
       ICPAR=0X01;      
       TIE=0X01;
       TSCR1=0X80;            
       EnableInterrupts;      
       for(;;)
       {; }
    }
      #pragma CODE_SEG __NEAR_SEG NON_BANKED
      interrupt void CH0IC(void)
      {
        first=TC0H;
        second=TC0;
        n=count*65535+second-first;
        f=f1/n;
        N=PA0H;
        TFLG1=0X01;
        count=0;
      }
        interrupt void TOI(void)
      {
         count++;         
         TFLG2_TOF=1;         
      }
3.3  通道6输出比较
本试验的辅助设备有:示波器。
试验目的:利用定时器溢出中断产生脉冲周期,利用通道6输出比较产生不同脉宽的波形,但此方法产生的波形其周期不能改变。
  1. double count,counter;

  2. void main(void) {

  3.        DisableInterrupts;

  4.        TSCR2=0X82;      

  5.        TIOS=0XFE;//设定pt6输出捕捉口

  6.        TCTL1=0X30;      

  7.        TC6=0X3333;

  8.        TTOV=0X40;     

  9.        TIE=0X00;

  10.        TSCR1=0X80;              

  11.        EnableInterrupts;  

  12.        for(;;)

  13.        {; }

  14. }

  15.        #pragma CODE_SEG __NEAR_SEG NON_BANKED

  16.       interrupt void CH6OC(void)

  17.       {

  18.         counter++;

  19.         if(counter==100)

  20.         TC6=0X8888;

  21.         if(counter==200)

  22.         TC6=0XCCCC;

  23.         if(counter==300)

  24.         TC6=0XDEEE;         

  25.         TFLG2_TOF=1;

  26.       }
复制代码


3.4  通道7输出比较
本试验的辅助设备有:示波器。
试验目的:利用通道7输出比较中断产生脉冲周期,利用通道6、4输出比较产生不同脉宽的波形,此方法产生的波形既可以改变周期同时也能够改变脉宽。
  1. #include <hidef.h>      /* common defines and macros */

  2. #include <mc9s12dp256.h>     /* derivative information */

  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"

  4. double count,counter;

  5. void main(void) {

  6.        DisableInterrupts;      

  7.        TIOS=0XF0;//设定pt6输出捕捉口

  8.        TSCR2=0X0a;

  9.        TFLG1=0X00;

  10.        TFLG2=0X00;      

  11.        TCTL1=0X62;

  12.        ICSYS=0X0a;      

  13.        OC7M=0X50;

  14.        OC7D=0X50;

  15.        TC7=0X00C0;

  16.        TC6=0X0060;

  17.        TC4=0X0099;

  18.        TIE=0X00;

  19.        TSCR1=0X80;              

  20.        EnableInterrupts;      

  21.        for(;;)

  22.        {; }

  23. }
复制代码


3.5  模数递减计数器
本试验的辅助设备有:连接导线若干。
试验目的:利用模数递减计数器回零中断,控制五个小灯依次点亮,同时点亮的时间间隔由慢到快。
  1. #include <hidef.h>      /* common defines and macros */

  2. #include <mc9s12dp256.h>     /* derivative information */

  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"

  4. long counter=0;

  5. void main(void)

  6. {     

  7.        DisableInterrupts;                 

  8.        DDRB=0XFF;

  9.        PORTB=0X00;

  10.        MCCTL_MCEN=0;

  11.        MCCTL_MCZI=1;

  12.        MCCTL_MODMC=1;

  13.        MCCTL_MCPR1=1;

  14.        MCCTL_MCPR0=1;

  15.        MCCNT=0XAAAA;  

  16.        TSCR1=0X80;

  17.        TSCR2=0X00;

  18.        MCCTL_MCEN=1;              

  19.        EnableInterrupts;            

  20.        for(;;)

  21.        {; }

  22. }

  23.       #pragma CODE_SEG __NEAR_SEG NON_BANKED

  24.       interrupt void MDC(void)

  25.       {

  26.         counter++;

  27.         if(counter<=10)

  28.         PORTB=0X01;      

  29.         if((counter>10)&&(counter<=20))

  30.         {

  31.           PORTB=0X02;

  32.           MCCNT=0X2222;

  33.         }

  34.         if((counter>20)&&(counter<=30))

  35.         {

  36.           PORTB=0X04;

  37.           MCCNT=0X4444;

  38.         }

  39.         if((counter>30)&&(counter<=40))

  40.         {

  41.           PORTB=0X08;

  42.           MCCNT=0X8888;

  43.         }

  44.         if((counter>40)&&(counter<=50))      

  45.         {

  46.           PORTB=0X10;

  47.           MCCNT=0XDDDD;

  48.         }

  49.         if(counter>50)

  50.         counter=0;

  51.         MCFLG_MCZF=1;

  52.       }

复制代码




第三章 SCI模块第一节  SCI寄存器简介
SCI是一种采用NRZ格式的异步串行通信接口,它内置独立的波特率产生电路和SCI收发器,可以选择发送8或9个数据位(其中一位可以指定为奇或偶校验位)。
SCI是全双工异步串行通信接口,主要用于MCU与其他计算机或设备之间的通信,几个独立的MCU也能通过SCI实现串行通信,形成网络。
MC12里有两个SCI(SCI0和SCI1)。设计SCI串口通信程序,主要是掌握八个寄存器,设置好初始化。
1.1  波特率控制寄存器(SCIBDHSCIBDL)
SCIBDH和SCIBDL一起构成了一个16位的波特率控制寄存器。SBR12~SBR0为波特率常数,见表9-1。
表9-1 波特率控制寄存器
寄存器名:SCIBDH、SCIBDL;地址:$00C0、$00C1;复位默认值:00000000B、00000100B
读操作:任意;写操作:SBR12~SBR0任意,低位字节写入后生效。SBR13~SBR15未定义
B7
B6
B5
B4
B3
B2
B1
B0
SCIBDH
读写
未定义
未定义
未定义
SBR12
SBR11
SBR10
SBR9
SBR8
SCIBDL
读写
SBR7
SBR6
SBR5
SBR4
SBR3
SBR2
SBR1
SBR0

SCI的波特率由下述公式决定:
波特率:MCLK/(16×BR)
或BR:MCLK/(16×波特率)
其中BR是波特率常数,设定时写入到SBRl2~SBR0。复位后,在SCICR2寄存器中的 TE、RE位第一次置1前,波特率发生器是关闭的,而且,当SBRl2~
表9-2常用波特率及波特率常数
波特率
110
300
600
1200
2400
4800
9600
14400
19200
38400
波特率因子
P=4MHz
2273
833
417
208
104
52
26
17
13
P=8MHz
4545
1667
833
417
208
104
52
35
26
13
SBR0=0时,波特率发生器也会被关闭。
通常选用波特率为9600。
BTST、BSPL和BRLD保留用于检测功能。
1.2  控制寄存器1(SCICR1)
SCI的工作方式主要由该寄存器设置,包括回送、单线等方式选择,帧格式、唤醒、空闲检测类型以及奇偶校验等,见表9-3。其各位意义如下:
表9-3 SCI控制寄存器1
寄存器名:SCICR1;地址:$00C2;复位默认值:00000000B;读操作:任意;写操作:任意
B7
B6
B5
B4
B3
B2
B1
B0
读写
LOOPS
SCISWAI
RSRC
M
WAKE
ILT
PE
PT
LOOPS  SCI回送模式/单线模式允许位,接收器的输入由RSRC位选择确定,发送器的输出受相应的DDRS位(S口I/O方向控制位)控制。要使用回送或者单线模式,发送、接收器必须同时允许工作。在LOOPS=1期间,如果与TxD引脚对应的方向控制位被置1,那么TxD引脚就输出SCI的信号;如果方向控制位被清0,那么这时若RSRC=0,TxD引脚就变成高电平(空闲状态),反之若RSRC=1,TxD引脚就变成高阻态。
0:SCI发送和接收部分正常工作。
1:SCI接收部分与RxD引脚断开,空出来的RxD引脚可以用作通用I/O。
SCISWAI等待模式下SCI停止位
0:在等待模式下允许SCI
1:在等待模式下禁止SCI
RSRC:接收器信号源选择位,当LOOPS=1时,RSRC决定接收器的内部反馈信号路径。
0:接收器的输入在内部连接到发送器输出(并非TxD引脚)。
1:接收器的输入连接到TxD引脚。
M:方式选择位(选择字符帧格式)。
0:1个起始位,8个数据位,1个停止位。
1:1个起始位,8个数据位,第9个数据位,1个停止位。
WAKE:唤醒选择位。
0:介质空闲唤醒。
I:地址标志(最后一个数据位为1)唤醒。
ILT空闲检测方式选择位,该位在SCI接收器可以使用的两种空闲检测方式中选择一种。
0:快速检测,SCI在一个帧的开始位后立即开始对“1”计数,因此,停止位以及停止位前面的任何“1”均被计算在内,这样可以提前检测到空闲状态。
1:保守检测,SCI在停止位后才开始对“1”计数,因此最后一个字节的停止位以及该位以前的各个为“广的位,对检测的时间长短无影响。
PE:奇偶校验允许位。
0:禁止奇偶校验。
1:允许奇偶校验。
PT奇/偶校验选择位,如果奇偶校验允许,该位决定收发器使用奇校验还是偶校验。如果选择偶校验,当数据中有偶数个“广时,校验位置0,否则校验位置1。
0:选择偶校验。
1:选择奇校验。
1.3  控制寄存器2(SCICR2)
   该寄存器主要控制收发器的使能、中断允许及其他辅助操作,见表9-4。其各位意义如下:
表9-4 SCI控制寄存器2
寄存器名:SCICR2;地址:$00C3;复位默认值:00000000B;读操作:任意值;写操作:任意
B7
B6
B5
B4
B3
B2
B1
B0
读写
TIE
TCIE
RIE
ILIE
TE
RE
RWU
SBK

TIE 发送中断允许位,清0时禁止TDRE产生中断,若置1则允许TDRE位置1时产生SCI中断请求。
TCIE发送结束中断允许位,清0时禁止TC产生中断,若置1则允许TC位置1时产生SCI中断请求。
RIE接收中断允许位,清0时禁止RDRF和OR产生中断,若置1则允许RDRF或OR置1时产生SCI中断请求。
ILIE空闲中断允许位,清0时禁止IDLE产生中断,若置1则允许IDLE位置1时产生SCI中断请求。
TE  发送允许位。该位由0置1时可用来发送空闲报头。
0:  发送器禁止。
1:  允许SCI发送部分工作,TxD引脚(PSl/PS3)用于发送。
RE  接收允许位。
0:  接收器禁止。
1;  允许SCI接收器工作。 RWU:  接收器唤醒控制位。
RWU接收器唤醒控制位
0:SCI接收器正常工作。
1:允许唤醒功能,禁止接收器中断。通常,硬件通过自动清除该位来唤醒接收器。
SBK中止符发送允许位。只要该位保持为1,发送器就不停地发出“0”;如果变为0,当前的全“0”帧发送结束后,TxD引脚将变成空闲状态。如果SBK开关一次,发送器将只发出10(11)个“0”,然后复原,处于空闲或发送数据状态。
0:  中止符产生器关闭。
1:  产生中止符,至少10或11个连续的“0”。
1.4  状态寄存器1SCISR1
该寄存器反映SCI运行过程中的各种状态,包括发送器和接收器的状态信息和接收器的出错信息,见表9-5。
表9-5 SCI状态寄存器
寄存器名:SCISR1;地址:$00C4;复位默认值:11000000B;读操作:任意;写操作:无意义
B7
B6
B5
B4
B3
B2
B1
B0
TDRE
TC
RDRF
IDLE
OR
NF
FE
PR
当SCI硬件处于某些状态时,SCISR1中的对应位置位,并通过特定的确认动作清除。先后对SCISR1和SCIDRL进行读操作将清除与接收有关的标志位(RDRF、IDLE、OR、 NF、FE和PF),读SCISR1然后写SCIDRL将清除与发送有关的标志位(TDRE和TC)。
TDRE  发送保持器空标志位。发送前必须读SCISR1,并确认TDRE=1,然后将新的数据写入发送保持器以开始发送过程。复位后该位为1。
0:SC0DR处于忙状态。
1:发送保持器的数据已被传送到发送移位器,这时可以向发送保持器写入新的数据
TC 发送结束标志。该位在发送器空闲(无发送动作)时置位。读SCISRl,然后写SCIDR将清除该位。   
0:发送器忙。
1:发送器空闲。
RDRF:接收数据就绪标志。当收到的字符已经在SCIDR中就绪时,RDRF置1,顺次读取SCISRl和SCIDR将会自动清除RDRF。该位被清除后,必须等到RxD线变为活动,然后重新变成空闲以后,IDLE位才会被再次置1。
0:SCIDR空。
1:SCIDR中数据已就绪。
IDLE  空闲标志。检测到接收器RxD端空闲(收到10或者11个以上连续的“1”)。当RWU位为1时,空闲状态不会使该位置1。该位被清除后,必须等到RDRF置位(RxD线变为活动,然后重新变成空闲),IDLE位才会被再次置1。
0:RxD线活动。
1:RxD线空闲。
OR:重叠错误标志。如果接收数据寄存器中的数据尚未读取(RDRF=1),接受移位寄存器又准备向其传送新的数据,则称为重叠错误,该位被置1。必须清除该位,才能使新的数据进入接收数据寄存器。
0:无重叠。
1:出现重叠错误。
NF噪声错误标志。噪声错误出现时,该位与RDRF在同一个周器内置位,但如果同时或已经出现重叠错误,该位不置位。
0:采样结果一致。
1:在起始位、数据位或停止位接收期间检测到噪声。
FE帧格式错误。如果在应该出现停止位的时刻,检测到0,则该位置位。顺次读取寄存器SCISRl和SCIDR将清除FE标志。
0:检测到停止位。
1:在预期的停止位处检测到0。
PF奇偶错误标志。指示收到数据的奇偶性与校验位是否一致。奇偶校验允许(PE=1)时,该标志才有意义。所要求的奇偶性由SC0CR1中的PT位决定。
0:奇偶校验正确。
1:奇偶校验错误。
1.5  状态寄存器2(SCISR2)
表9-6 SCI状态寄存器2
寄存器名:SCISR2;地址:$00C5;复位默认值:00000000B;读操作:任意;写操作:写RAF无意义
B7
B6
B5
B4
B3
B2
B1
B0
读写
未定义
未定义
未定义
未定义
未定义
BRK13
TXDIR
RAF
BRK13中止符长度控制位。
0:中止符长度为10或11位。
1:中止符长度为13或14位。
TXDIR单线模式下发送管脚数据方向控制位。
0:单线模式下TxD脚用于输入。
1:单线模式下TxD脚用于输出。
RAF接收器活动标志位。反映接收器是否处于活动状态。在搜索起始位的RT1期间该位置1,当接收器器检测到空闲状态或者出现一个伪起始位(通常由于噪声或波特率匹配错误引起)时,该位清0。该位由接收器前端控制,
1.6  数据寄存器(SCIDRHSCIDRL)
  SCI内部分别设有发送和接收两个数据寄存器,其低位都通过SCIDRL访问,读操作返回接收数据寄存器RDR的内容,写操作数据置入发送数据寄存器TDR。当M=1即运行在9位数据模式时,SCIDRL和SCIDRH形成9位的SCI数据字,这时必须先写入SCIDRH,以便与低位字节(SCIDRL)一起进入发送移位器。如果M=0即SCI只用于7位或8位的数据传送,可以只访问SCIDRL。当PE=1即奇偶校验允许时,奇偶校验位由硬件负责,无需软件干预,见表9-7。
表9-7 SCI数据寄存器
寄存器名:SCIDRH、SCIDRL;地址:$00C6、$00C7;复位默认值;00000000B、00000000B;
读操作:任意;写操作:任意但写R8无意义。
B7
B6
B5
B4
B3
B2
B1
B0
SCIBDH
R8
T8
0
0
0
0
0
0
未定义
未定义
未定义
未定义
未定义
未定义
未定义
SCIBDL
R7T7
R6T6
R5T5
R4T4
R3T3
R2T2
R1T1
R0T0
R8接收到的位8,该位写操作无效。当SCI设置成9位数据运行模式时,该位是从串行数据流中接收到的第9位。
T8发送位8,任何时候可写。当SCI设置成9位数据模式时,该位是送到串行数据流的第9位。该位不必为每个数据重新设置,每次发送可重复使用。 R7T7-ROT0:  收/发数据位7-0,读操作返回只读寄存器RDR的内容,写操作写入只写寄存器TDR。
第二节  SCI应用示例
下面看看实验:
1、本实验需软件程序“穿口调试助手V2.0”。
2、实验步骤:
1)保证单片机5V电源、串口通讯线与仿真板的连接无误;
2)上电后建立新建文件,在main.c中输入下面程序并写如flash;
3)点击图标运行后,打开“助手”,在下面的发送框中输入任意数字或字符,然后选择自动或手动发送。
3、试验结果
在“助手”下边的发送框中输入任意数字或字符,然后发送,接收到数据后,上面的显示区就会将其以ASCII码或十六进制的形式(可选)显示出来。
4、源程序
  1. #include <hidef.h>      /* common defines and macros */

  2. #include <mc9s12dp256.h>     /* derivative information */

  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"

  4. byte sci_data;

  5. //发送子函数

  6. void SCI_Transmit(byte data){

  7. while(!SCI0SR1_TDRE);//SC0DR处于忙状态,等待。

  8. SCI0DRL=data;

  9. }

  10. //接收子函数

  11. void SCI_Receive(byte *data)

  12. {

  13. *data=SCI0DRL;

  14. }

  15. void main(void)

  16. { SCI0BDL=0x34; //总线为8M,波特率为9600

  17.   SCI0CR2=0X2C; //允许中断,允许发送,允许接受

  18.   while(1)

  19.   {

  20.     while(!SCI0SR1_RDRF);  //SCIDRL为空,等待数据就绪。

  21.     SCI_Receive(&sci_data);

  22.     SCI_Transmit(sci_data);

  23.   }

  24. }
复制代码


下面的源程序是利用SCI做的一个足球答题系统,感兴趣的同学可以看一下:
  1. #include <hidef.h>      /* common defines and macros */
  2. #include <mc9s12dp256.h>     /* derivative information */
  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
  4. byte sci_data;
  5. //中断初始化
  6. void SCI_Init(void) {
  7. SCI0BDL=0x34;
  8. SCI0CR2=0X2C;
  9. }
  10. //发送子函数
  11. void SCI_Transmit(byte data){
  12. while(!SCI0SR1_TDRE) ;
  13. SCI0DRL=data;
  14. }
  15. //接收子函数
  16. void SCI_Receive(byte *data){
  17. *data=SCI0DRL;
  18. }
  19. //特定输出子函数
  20. void printf(char *str){
  21. while(*str!='\r'){
  22. SCI_Transmit(*str);
  23. *str++;
  24. }
  25. }
  26. N0Choose(byte data){
  27. switch(data){
  28.   case '1':
  29.   NO1();
  30.   break;
  31.   case '2':
  32.   NO2();
  33.   break ;
  34.   case '3':
  35.   NO3();
  36.   break;
  37.   case '4':
  38.   NO4();
  39.   break;
  40.   case '5':
  41.   NO5();
  42.   break;

  43.   dafault:
  44.   break;
  45. }
  46. }
  47. void main(void) {
  48. SCI_Init();
  49. printf("welcome to lipu's football-quiz system!\n\r");
  50. printf("choose the problem number(1to5)\n\r");
  51. while(1){
  52. while(!SCI0SR1_RDRF);
  53. SCI_Receive(&sci_data);
  54. SCI_Transmit(sci_data);
  55. N0Choose(sci_data);
  56. }
  57. }
  58. void Right(void){
  59. printf("\nyou are RIGHT.\nchoose the next question\n\r");}
  60. void Wrong(void){
  61. printf("\nyou are WRONG.\nchoose the next question\n\r");}
  62. int NO1(void){
  63. printf(".which country is the champion of World Cup at 2006?\n\r") ;
  64. printf("A:Brazil  B:Italy\n\r");
  65. while(!SCI0SR1_RDRF);
  66. SCI_Receive(&sci_data);
  67. SCI_Transmit(sci_data);
  68. switch(sci_data){
  69.   case 'A':
  70.   Wrong();
  71.   break;
  72.   case 'B':
  73.   Right();
  74.   break;
  75.   default:
  76.   break;
  77. }
  78. }
  79. int NO2(void){
  80. printf(".which country have the most champions of World Cup?\n\r") ;
  81. printf("A:Brazil  B:Italy\n\r");
  82. while(!SCI0SR1_RDRF);
  83. SCI_Receive(&sci_data);
  84. SCI_Transmit(sci_data);
  85. switch(sci_data){
  86.   case 'B':
  87.   Wrong();
  88.   break;
  89.   case 'A':
  90.   Right();
  91.   break;
  92.   default:
  93.   break;
  94. }
  95. }
  96. int NO3(void){
  97. printf(".which club is the champion of Spanish Prinera Divison at 06-07\n\r") ;
  98. printf("A:Barcelona  B:Real Madrid\n\r");
  99. while(!SCI0SR1_RDRF);
  100. SCI_Receive(&sci_data);
  101. SCI_Transmit(sci_data);
  102. switch(sci_data){
  103.   case 'A':
  104.   Wrong();
  105.   break;
  106.   case 'B':
  107.   Right();
  108.   break;
  109.   default:
  110.   break;
  111. }
  112. }
  113. int NO4(void){
  114. printf(".which club is the champion of Italian Serie A at 06-07\n\r") ;
  115. printf("A:Inter Milan  B:AC.Milan\n\r");
  116. while(!SCI0SR1_RDRF);
  117. SCI_Receive(&sci_data);
  118. SCI_Transmit(sci_data);
  119. switch(sci_data){
  120.   case 'B':
  121.   Wrong();
  122.   break;
  123.   case 'A':
  124.   Right();
  125.   break;
  126.   default:
  127.   break;
  128. }
  129. }
  130. int NO5(void){
  131. printf(".who is the FIFA World Player at 2006\n\r") ;
  132. printf("A:Henry  B:Ronaldiaho\n\r");
  133. while(!SCI0SR1_RDRF);
  134. SCI_Receive(&sci_data);
  135. SCI_Transmit(sci_data);
  136. switch(sci_data){
  137.   case 'B':
  138.   Wrong();
  139.   break;
  140.   case 'A':
  141.   Right();
  142.   break;
  143.   default:
  144.   break;
  145. }
  146. }
复制代码





第四章 SPI模块第一节  SPI模块介绍1.1  SPI的功能特点
串行设备接口SPI主要用于同步串行通信,它使MCU具备了与外围设备以及其他微处理器进行同步通信的能力,也能够在多主系统中实现处理器间的通信。可连接的设备包括简单的移位寄存器(例如74LSl65用作并行输入口,或74LSl64用作并行输出口等)、LCD显示驱动器或AID转换器的接口。MCU可选择8种不同的位传送频率、两种不同的时钟极性、相位和位传送顺序,因此可直接与各个厂家生产的多种标准的串行外围接口器件连接。在串行外围接口中,数据和时钟线是分开的,在SPI格式中,时钟不包括在数据流中,它必须是另一个独立的信号线。MC9S12DP256的SPI可定义为主机或从机方式,主要特性如下:(1)全双工、三线同步传送。
(2)单个数据引脚的双向传送方式。
(3)主机或从机工作方式。
(4)每一晶体频率下可通过程序选择八种不同的主机位传送频率。
(5)主机位传送频率最大4MHz,当MCU总线频率=8MHz时最小为31.25kHz。
(6)从机位传送频率最大4MHz,允许频率范围为0-4MHz。
(7)可程控设置位时钟极性、相位和数据位传送顺序,即可选高位在前或低位在前。
(8)发送完成中断标志。
(9)多主机系统控制冲突保护中断标志。
(10)写冲突标志保护。
(11)可方便地与各种简单扩展器件接口,如PLL、D/A、锁存器、LCD显示驱动器等。
SPI系统可在软件控制下构成各种不同复杂程度的系统,例如:
(1)一个主MCU和一个或者几个从MCU。
(2)几个MCU相互联接构成多主机的系统(全分布式系统)。
(3)一个主MCU和一个或者几个从I/O设备。
(4)一个其他主微机系统和一个或者几个从MCU。
1.2  SPl的组成与工作设置
(一)SPl的结构与工作过程
    1.SPI的结构组成
SPI系统主要由8位移位寄存器、时钟控制逻辑、引脚控制逻辑、SPI控制逻辑和分频器以及波特率寄存器SPIBR、状态寄存器SPISR、控制寄存器1SPICR1、控制寄存器2SPICR2、数据寄存器SPIDR等5个寄存器组成,如图1所示。
SPI的核心是一个8位移位寄存器。发送或接收时,引脚的数据流在时钟信号SCK的作用下移出或移入该寄存器。该寄存器对用户透明,CPU通过SPIDR与其联系。发送时将数据写入SPIDR将直接进入移位寄存器,即所谓单缓冲;而接受到的数据则通过读数据缓冲器到达SPIDR,因此称为双缓冲,这样可以保证移位寄存器正在接收时,CPU能正确读取上一个收到的字节。
时钟逻辑主要用于为移位寄存器提供工作时钟。在主模式下,内部波特率产生逻辑为其提供时钟源,同时还通过SCK引脚输出到外部从器件;在从模式下,外部主器件通过SCK引脚提供时钟源。分频器的时钟频率通过对SPIBD的设定来选择,因而可以得到各种位传送速率。时钟控制逻辑将产生各种极性和相位的位时钟(SCK)信号,还可以选择传送时数据高位在先还是低位在先,以适应各种不同的外围器件。
控制寄存器SPICR1、SPICR2和SPIBR用来设置SPI的工作方式,包括主/从模式、数据位顺序、时钟极性、相位、波特率以及引脚逻辑等参数。状态寄存器SPISR保存SPI的工作状态,包括传送结束、写冲突和模式错误等。
    SPI0与PS口共享PS7-PS4引脚,SPI1与PP口共享PP7-PP4引脚, SPI2与PP口共享PP3-PP0引脚。当SPI系统使能时,四个引脚一般由通用I/O变为SPI的有关引脚(、SCK、MISO、MOSI)。但当 SPI工作在双向模式时,个别引脚仍可用作通用I/O。
图1 SPI接口的逻辑结构与寄存器设置
2.SPI引脚
对于SPI0,当SPE=1即SPI系统使能时,SPI使用PS口的四个引脚:串行位时钟SCK、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低有效的从机选择线。在SPI系统关闭时,这四个引脚用作通用I/O线PS7-PS4。在通用I/O方式下,数据方向寄存器DDRS完全控制PS口引脚的数据方向,但SPI系统使能后,DDRS仍然参与对PS7-PS4引脚的控制,它与SPI控制寄存器共同决定相应引脚的功能。
从机选择信号:该信号总是由主机发给从机,低电平有效。
当 MSTR=0时,MCU的SPI被设置为从机方式,其引脚为自身工作允许端(输入状态), SCK由外部主器件提供。若引脚输入为逻辑1,SPI不理会外部的SCK时钟,并且MISO引脚为高阻抗状态。当输入为逻辑0时,SPI被允许,在外部SCK的作用下接收或发送数据。在该方式下,不受DDS7和SSOE的控制,固定为器件选择输入引脚。
若MSTR=1,SPI处于主机方式,其引脚可选三种功能。
当DDS7=SSOE=0时,引脚输出从机选择信号,SCK输出SPI工作时钟。若要选中外部从机,引脚必须输出逻辑 0,外部从机在SCK的作用下接收或发送数据。当输出逻辑1时,从器件被禁止。每一次传送时,输出自动变低以选中外部器件,在传送中间的空闲状态回到高电平以释放外部器件。
当DDS7=SSOE=1时,引脚为SPI系统的工作方式冲突错误检测输入,正常情况下保持高电平。在分布式多主机系统中,多个器件均可能作为主机,但是同一时刻只能有一个主机。当已有一个器件作为主机并正在选择从器件时,引脚被其拉低到逻辑0,这时若 MCU将自身SPI设为主机,即置MSTR=1,SPI将会发现已经为逻辑0,表示已经存在主机,于是发生了工作方式冲突错误,SPI自动置位MODF标志,并在SPIE=1时申请中断,通知CPU处理。
当DDS7=1、SSOE=0时,引脚为通用输出引脚,与SPI系统无关。
当DDS7=0、SSOE=1时,引脚为系统保留功能,用户不能使用。
(2)串行数据线(MISO、MOSI)。MISO为主入/从出线,MOSI为主出/从入线,它们用于串行接收和发送数据;数据高低位传送顺序由LSBF选择。每个MOSI、MISO引脚都是双向引脚,当SPICR寄存器的MSTR位由软件置1时,SPI设置为主机方式,其MISO、 MOSI分别是数据输入/输出线,这时主机从它的MOSI脚输出数据,从它的MISO引脚输入数据。当器件设置为从机方式时,其MISO变为数据输出线,而MOSI成为数据输入线。在多主机系统中,无论主从,所有SCK引脚、MISO引脚和MOSI分别联在一起。时钟信号由主SPI的SCK引脚输出,送到所有的从SPI的SCK引脚,主SPI的数据从其MOSI引脚输出,送到所有从SPI的MOSI引脚;被选中的从SPI的数据从其MISO输出,送到主SPI的MISO引脚。
(3)串行时钟(SCK)。在SPI设置为主机方式时,SCK信号来自内部MCU时钟,并从其SCK引脚输出。在主机起动一次传送时,自动在SCK端产生8个SCK时钟脉冲。对于从机,只有其引脚为逻辑低电平时,才接收SCK时钟信号,并与SCK同步发送或接收数据。无论是主SPI或从SPI,都是在SCK信号的一个跳变沿进行数据移位,在数据稳定后的另一个跳变沿进行采样。主机设备的SPIBR选择时钟频率,与从机无关。主机和从机的SPI数据与位时钟之间的传送定时关系必须相同(由SPICR1的CPOL和CPHA位控制)。
另外,数据方向寄存器的DDRS4-DDRS6分别影响MISO、MOSI和SCK。若某一引脚作为输出时,应使DDRS对应位置1,若作为输入,则不受DDRS位影响。
3.SPI的双向模式(MOMI或SISO)
当控制寄存器SPOCR2中的SPC0=1时,SPI进入一种双向模式,事实上SPI原来就是双向的,因此这里的双向模式确切地说是单线双向模式。在该模式下,SPI使用单一引脚与外部器件接口,具体引脚由MSTR控制位决定,在主模式下MOSI成为双向引脚 MOMI,而在从模式下MISO成为双向引脚SISO,引脚数据方向取决于相应的DDRS位。如表1所示。在使用双向模式的系统中,所有需要双向传输的器件均必须工作在双向模式下。在双向模式下,无论SPI作为主器件或从器件,均有一引脚重新获得通用I/O功能。
表1 普通模式与双向模式
4.SPI数据与位时钟的各种时序关系
两器件之间传送信息,它们的时序必须一致。为了能与各种标准外围设备接口,MCU提供了四种数据和位时钟的时序关系,由CPOL和CPHA控制位选择。将CPOL置1相当于在时钟信号中串入一个反相器。除此以外,SPI还可以选择数据位的传送顺序。时序相同时,将主机和从机的MISO、MOSI、SCK分别直接相联,即可构成一个主从系统。
图2、图3分别表示了CPHA为0、1时,单个字节数据传送的时序。由图可见,每个字节需要8个时钟周期,传送期间从器件选中信号必须有效。这里以CPOL=O、LSBF=O为例,主机发送数据为例,对两个时序图简单说明如下。
图2 CHPA=O时的数据位与时钟时间关系
图3 CHPA=1时的数据位与时钟时间关系
在图2中,主机的输出逻辑0,选中从器件,同时MOSI输出数据最高位,经过半个时钟周期后,在SCK的上升沿,从器件采样MOSI线,保存结果。在SCK的下降沿,主机输出下一个数据位,在下一个SCK的上升沿,从器件又采样MOSI线,保存结果,如此循环八次,数据传送结束,然后再延迟半个时钟周期后释放,回到高电平,等待半个周期后可以开始下一次传送过程。
在图3中,有效后,时钟信号没有立即输出,因此传送过程并没有真正开始,而是半个周期后,时钟和数据同时输出,然后在时钟的下降沿从器件采样MOSI线,保存结果,其他与图9-5类似。  
5.SPI的工作过程
系统工作时,主机发送数据的同时也接收从机来的数据,从机接收的同时也向主机发送数据,这个过程就好像分别位于主从器件的两个8位寄存器被“连接”在一起形成了一个分布式的16位寄存器。当进行数据传输时,该寄存器在主器件时钟SCK控制下,连续循环移动8位,于是数据在主从器件之间实现了数据的有效交换。对于主器件来讲,写入SPIDR寄存器的数据成为送往从器件的输出数据,经传输操作后,从SPIDR读出的数据则是来自从器件的输入数据。
当SPI控制寄存器SPICR1中的SPE=1时,SPI系统使能。SPICR1中的相位控制位CPHA和极性控制位CPOL用于决定当前的SPI系统使用的时钟格式。CPOL只选择正向还是反向时钟,而CPHA则通过选择是否将时钟移相180度,来协调两种不同的协议。
在主机方式中,CPU将数据写入SPIDR时(写入SPIDR的数据立即装入8位移位寄存器中),起动一个传送过程。SCK脚输出8个位传送时钟,MOSI脚串行移位输出数据到从机SPI。同时,数据也由从SPI通过MISO脚串行移位输入到这个8位移位寄存器中。在传送的第8次移位后,数据并行传送到SPIDR,此后,CPU可读出它的内容。每完成一次数据传送,SPRF状态位置位,读SPISR(SPRF为1时),访问SPIDR,将SPIF位清0。
在从机方式中,CPU可先向SPIDR写入需传送到主机的数据,该数据从内部总线并行装入8位移位寄存器中。与主机不同,该写入不起动传送,从机需等待主机的信号。当CPHA为0时,脚的逻辑低电平,使数据的最高位输出,在SCK的第一个跳变沿采样输入,在另一个跳变沿将数据的次高位输出,当CPHA=1且=0时,SCK引脚的第一个跳变沿启动从机移位,将数据的最高位输出,在下一个跳变沿采样输入,这使从机与主机同步。这时,来自主机的数据由从机的MOSI脚串行输入,并移入8位移位寄存器,同时原来8位移位寄存器的数据由从机的MISO脚串行输出至主机。在8次数据移位后,接收的数据并行传送到SPIDR中,等待CPU读出。同主机一样,每完成一次数据的传送,SPRF位置1,这时读 SPSR随后访问SPIDR将SPRF位清0。
主机可发可收,从机可收可发。主机从机之间的数据传送是双向的。对于主机发、从机收的情况,主机由写入SPIDR起动一次发送过程。对于主机收、从机发的场合,也由主机写入SPIDR起动一次传送过程,不过写入SPIDR的数据与传送无关。
正在传送时,若写入SPIDR,将引起写冲突错误。对于主机,将打断数据的传送,对从机若写入SPIDR,对数据的传送无影响。
(二)波特率设置
P时钟经过一组级联的分频器形成SPI时钟,分频系数由SPIBR寄存器中的SPPR2~SPPR0和SPR2~SPR0共六位控制。波特率分频因子的表达式为:
该波特率产生器必须满足两个条件才能激活:一是SPI为主器件,二是串行传输正在进行,否则处于关闭状态以降低功率消耗。详见波特率寄存器SPIBR的说明。
(三)中断管理
SPI设置了两种中断,一是数据传送结束中断,另一个是模式冲突中断,二者受同一个中断允许位SPIE的控制,每次SPIF或MODF状态标志置位时,若CCR中的全局中断允许位I=1,则向CPU发出硬件中断请求。读SPOSR寄存器、然后读或写SPI数据寄存器将清除标志位SPIF,读SPOSR寄存器、然后写SPI数据寄存器将清除标志位MODF。
第二节  SPI寄存器简介2.1  SPI控制寄存器1(SPICR1)
SPI的工作方式主要由该寄存器设置,包括主从方式、单线双向模式选择,时钟及位顺序等,甚至包括引脚工作特性的设置,见表2。其各位意义如下:

表2 SPI控制寄存器1
寄存器名:SPICR1;地址:$00D0;复位默认值:00000100B;读操作:任意; 写操作:任意。
B7
B6
B5
B4
B3
B2
B1
B0
读写
SPIE
SPE
SPTIE
MSTR
CPOL
CPHA
SSOE
LSBF
SPIESPI中断允许位。
0:  禁止SPI中断。
1:  每次SPRF或MODF状态标志置位时发出硬件中断请求。
SPESPI系统允许位。
当MODF=1时,SPE读取结果总是0,SPOCR1的写操作指令必须作为模式故障恢复序列的一部分嵌入其中。
0:SPI内部硬件完成初始化,但SPI系统处于低功耗的禁止状态。
1:SPI使能。
SPTIE
0:SPTEF中断不被允许。
1:SPTEF中断允许。
MSTR主、从模式选择位,用于设定本机SPI以主器件还是从器件身份出现。
0:从模式。
1:主模式。
CPOLCPHA  SPI时钟极性、相位选择位,这两位用来指定SPI的时钟格式。当无传输动作且CPOL=0时,主器件的SCK引脚处于低电平,而如果CPOL=1,SCK则闲置在高电平。参看图9-6、图9-7。
SSOE  从器件选中输出信号()允许位,输出功能只有在主模式下通过置位SSOE和DDRS7实现。
0:  禁止输出。
1:  允许输出,但同时DDRS7必须为1。
LSBF  SPI数据位传输顺序选择位,通常要求LSBF=0,即传输过程高位在先。该位只决定传输过程中各位的先后顺序,不影响数据位在寄存器中的顺序,因此读写操作正常进行,即高位(MSB)在第7位(BIT7)。对于仅由MC9S12DP256构成的互连系统,只要各个SPI的LSBF相同,对传输结果无影响,但在与外围设备或器件连接时,SPI必须根据该设备或器件所要求的位顺序正确设置LSBF。
0:  数据传输高位(MSB)在先。
1:  数据传输低位(LSB)在先。
2.2  SPI控制寄存器2(SPICR2)
表3 SPI控制寄存器2
寄存器名:SPICR2;地址:$00D1;复位默认值:00001000B;读操作:任意;写操作:任意。
B7
B6
B5
B4
B3
B2
B1
B0
读写
未定义
未定义
未定义
MODFEN
BIDIROE
未定义
SPISWAI
SPC0
MODFEN模式错误使能位
0:禁止模式错误标志位置位。
1:允许模式错误标志位置位。
BIDIROE双向模式下输出缓冲使能位
0:双向模式下禁止输出缓冲。
1:双向模式下允许输出缓冲。
SPISWAI等待模式下SPI工作方式
0:等待模式下停止SPI时钟。
1:等待模式下SPI时钟正常工作。
SPC0串行引脚控制,该位与MSTR位一起决定串行引脚功能设置。见表3
2.3  SPI波特率选择寄存器
该寄存器只有六个有效位SPPR2~SPPR0和SPR2~SPR0,用来确定SPI系统工作时钟SCK的频率,即波特率。复位默认值为0,。参看表9-11。
表4 SPI波特率选择寄存器
寄存器名:SPIBDR;地址:$00D2;复位默认值为:00000000$;读操作:任意;写操作:任意。
B7
B6
B5
B4
B3
B2
B1
B0
读写
未定义
SPPR2
SPPR1
SPPR0
未定义
SPR2
SPR1
SPR0
SPPR2-SPPR0:波特率预选位;
SPR2-SPR0:波特率选择位。
波特率分频因子表达式为:
2.4  SPI状态寄存器
该寄存器反映SPI的工作状态,其中包括传输结束、写冲突和模式故障三个标志位,程序可以检查各位的状态,也可以通过特定的寄存器访问序列将标志位清0,见表9—12。其各位意义如下:
表5 SPI状态寄存器
寄存器名:SPISR;地址:$00D2;复位默认值:00100000B;读操作:任意;写操作:无意义。
B7
B6
B5
B4
B3
B2
B1
B0
SPIF
未定义
SPTEF
MODF
未定义
未定义
未定义
未定义
SPIFSPI中断请求位,在数据传输过程中,SPRF在第8个SCK周期后置位,通过读SPISR寄存器并随后读或写数据寄存器SPIDR清0。
0:传输正在进行或者根本没有传输。
1:一次传输已经结束。
SPTEF 当SPIDR中的值送入移位寄存器中是,该位置1。同时如果SPTIE位为1,则向CPU发出中断请求。读SPISR然后写SPIDR将清除该位。
0:SPI数据寄存器非空。
1:SPI数据寄存器空。
MODFSPI模式错误中断状态位。当MSTR=1时,如果从选择引脚在外部被拉低成逻辑0,该位由SPI硬件自动置1。这时本机SPI已经不能成功设定为主机,显然这种情况在正常情况下是不允许的。当DDRS7=1时,PS7是通用输出或输出引脚,而不是专用于SPI系统的输入引脚,在这种特殊情况下,模式故障功能被禁止,MODF保持为0。读SPOSR随后写入SPOCR1将清0该位。
0:无异常。
1:系统中已经出现另一个主机,并正在选中从器件。
2.5  SPI数据寄存器
表6 SPI数据寄存器
寄存器名:SPIDR;地址:$00D5;复位默认值;读操作:任意,一般在读SPIF位后,写操作:任意,读SPTEF后
B7
B6
B5
B4
B3
B2
B1
B0
读写
D7
D6
D5
D4
D3
D2
D1
D0
该8位寄存器是SPI数据寄存器,具有输入、输出双重功能,见表6。对该寄存器进行读操作时所访问的输入部分是双缓冲的,但写操作则直接将数据送到串行移位器。注意:某些简单的从器件可能只有发送功能,只向主器件发送数据而不向主器件请求数据,例如并行输入串行输出的TTL逻辑电路:或者只有接收功能,只从主器件接收而不返回数据,例如串行输入并行输出的TTL逻辑电路。由于SPI的传输是一次交换过程,对于只发送数据的从器件,交换前主机可向SPODR写入任何数据;对于只接收数据的从器件,交换后主机 SPODR中的数据无意义。
第三节  SPI应用实例
利用单片机与显示驱动芯片MC14489的SPI通讯实现计时器功能
(1)实验设备:HCS12编程器、开发板、MC14489驱动芯片、数码管
(2)软件程序设计:串型外部通讯是单片机与外界设备联系的重要方式。本例子利用HCS12单片机与MC14489芯片构成的具有串型通讯功能的电路,实现单片机与外部设备的串口通讯。并且利用程序的相应算法实现计时器的功能。
(3)源程序
#include <hidef.h>      /* common defines and macros */
#include <mc9s12dp256.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
/*声明变量*/
int n1,n2,n3,n4,n5,j=0;
word t1,t2,time;
byte mode=0;
/*SPI初始化*/
void SPI (void) {
SPI0CR1=0b01010000;
DDRS=0x60; //S5,S6为输出,其余为输入
SPI0BR=0x12;
SPI0CR2=0x00;               
DDRT=0X01;//t0为输出,其余为输入
PTT=0X01;//T0=1
}
/*键盘中断初始化*/
  void PortInit(void){
   DDRJ=0x00;   //j脚数据方向寄存器为输入
   PIEJ=0X03;   //j脚中断允许寄存器
}
/*延时程序*/
  void delay(word time){
   for(t2=0;t2<time;t2++){
      for(t1=0;t1<100;t1++){   
      }
   }
}
/*将单字节数据写入14489的配置寄存器*/
  void DanZiJie(void) {
PTT=0X00;
delay(1);
SPI0DR=0b00000001;
while(!SPI0SR_SPTEF){;}
delay(3);
PTT=0X01;  
  }
/*发三字节数据*/
void SanZiJie (void) {
PTT=0X00;
delay(1);
SPI0DR=0x80+n1;               
while(!SPI0SR_SPTEF){;}
SPI0DR=0x00+n2*16+n3;
while(!SPI0SR_SPTEF){;}  
SPI0DR=0x00+n4*16+n5;
while(!SPI0SR_SPTEF){;}
delay(3);
PTT=0X01;
}
/*主程序*/
void main(void) {
  SPI();
  DanZiJie();        
  PortInit();
  EnableInterrupts;
  while(1){
  n1=j/10000;
  n2=j/1000%10;
  n3=j/100%10;
  n4=j/10%10;
  n5=j%10;
  j++;
  SanZiJie();
  delay(15600);
  }
}
/*键盘中断子程序*/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt void PortJISR(void){
   switch(PIFJ){   //J脚中断标志寄存器
      case 0x01: mode=0;  PIFJ_PIFJ0=1;
       for (;;){
       }
       break;
   }   
}
(4)调试结果
程序运行,计时器开始工作,本计时器的工作范围(1s—99999s)。按下Key1计时停止,记录时间,按下Reset键,计时重新开始。


第五章 A/D转换模块第一节  A/D模块介绍1.1  A/D转换原理
模拟信号依次通过抽样和保持(S/H)电路和模拟转换器(A/D)后转换为数字格式。
抽样和保持电路以均匀间隔对模拟信号进行抽样,并且在每个抽样运算后在足够的时间内保持抽样值恒定,以保证输出值可以被A/D转换器精确转换。
下一步是通过模数转换器将抽样和保持电路的输出转换为数字形式。模数转换器的输出通常表示为二进制编码的形式。
转换精度由分辨率来表示,它由离散级数量决定。比如,对一个以二进制形式编码的长度为N位的长的输出,有效地离散级数量是2的N次方,分辨率为离散数量级的倒数。
1.2  A/D转换原理的应用前景
A/D转换器是模拟信号源与计算机或其他数字系统之间联系的桥梁,它的任务是将连续变化的模拟信号转换为数字信号,以便计算机或数字系统进行处理、存储、控制和显示。在工业控制和数据采集及许多其他领域中,A/D转换器是不可缺少的重要组成部分。
1.3  A/D转换模块
12中A/D转换共有两个方块,每个方块各有8个输入通道,使用时应以标头ATD0或ATD1标识。
1.4  功能结构图
图 2.1 功能结构图
图中所示的是A/D模块的功能结构,这个功能模块被虚线划分成为图示所示的虚线所隔离的三个部分:IP总线接口、转换模式控制/寄存器列表,自定义模拟量。
IP总线接口负责该模块与总线的连接,实现A/D模块和通用I/O的目的,还起到分频的作用;
转换模式控制寄存器列表中有控制该模块的所有的寄存器,执行左右对齐运行和连续扫描。
自定义模拟量负责实现模拟量到数字量的转换。包括了执行一次简单转换所需的模拟量和数字量。
1.5  HCS12A/D特点
8/10 位精度;7 us, 10-位单次转换时间.;采样缓冲放大器;可编程采样时间;左/右对齐, 有符号/无符号结果数据;外部触发控制;转换完成中断;模拟输入8通道复用;模拟/数字输入引脚复用;1到8转换序列长度;连续转换模式;多通道扫描方式。
ATD模块有模拟量前端、模拟量转换、控制部分及结果存储等四部分组成。其中模拟前端包括多路转换开关、采样缓冲器、放大器等,结果存储部分主要有8个16位的存储器和反映工作状态的若干标志位。
第二节  A/D寄存器简介
要完成ATD转换的特定功能,必须对相关寄存器有所了解。在12ATD模块中,ATDCTL2,3,4,5为常用的控制寄存器,ATDSTAT0,1为常用的两个状态控制器,ATDDR0-7为八个结果寄存器。
ATD工作时,由CPU发出启动命令,然后经采样、模数转换,最后将结果保存到相应的寄存器。
ATD每次启动要进行若干个扫描循环,每个扫描循环称为一个转换序列,每个转换序列能包含1-8最多8次转换,由控制寄存器ATDCTL3中的S8C/S4C/S2C/S1C等位来决定。
这些转换序列可以针对某个单一通道,也可以针对几个相邻通道,每个通道可以使外部模拟输入,也可以是参考电压或其他保留信号,ATD可支持多种不同的通道信号组合。每次转换包括哪些通道由ATDCTL5中的CC、CB、CA决定的。
对单一通道连续进行多次转换有利于实现滤波,一次转换多个通道则可以通过一次启动命令快速浏览多个信号,中间无需CPU干涉,节约了CPU时间。
ATD的运行方式分为单次和连续运行两种。
在单次方式下,每个转换序列完成后,寄存器ATDSTAT中的SCF置位,然后ATD模块暂停。
在连续方式下,转换以转换序列为单位连续进行,当第一个转换序列完成后,SCF置位,同时ATD模块开始下一个转换序列。
在上述两种方式下,每个通道的转换结果进入到对应结果寄存器后,寄存器ATDSTAT1种对应的CCF位置1,对存放转换结果的寄存器进行读操作后,CCF位将自动清0。转换过程的启动是通过写入寄存器5ATDCTL5实现的。
ATD转换所需要的时钟周期数是固定不变的,但是采样时间和时钟频率可以通过ATDCTL4在一定范围内选择,因此转换时间也可以选择。
2.1  控制寄存器2ATDCTL2

ADPU - A/D 电源使能/禁止
  1 =  A/D模块上电
  0 =  禁止A/D,以减少功耗
AFFC - A/D 快速转换完成标志位清零
  1 = 快速标志位清零顺序   每次读取结果寄存器自动清零
  0 = 正常标志位清零顺序    需要手动对状态标志位清零
AWAI - A/D 等待模式
1 = 等待模式下,转换
0 = 等待模式下,禁止转换
ASCIE - A/D 顺序完成中断使能
ETRIGLE
ETRIGP
ETRIGE
SCAN
描述
x
x
0
0
忽略外部触发,执行一次转换后停止
x
x
0
1
忽略外部触发,执行连续转换后
0
0
1
X
下降沿触发,每次触发,执行一次转换
0
1
1
X
上升沿触发,每次触发,执行一次转换
1
0
1
X
低电平触发,每次触发,执行连续转换
1
1
1
X
高电平触发,每次触发,执行连续转换


2.2  控制寄存器3ATDCTL3
FIFO – 结果寄存器 FIFO
  1 = 结果寄存器映射到转换序列
  0 = 结果寄存器没有映射到转换序列

2.3  控制寄存器4ATDCTL4
SRES8 - A/D 精度选择
  1 = 8 位
  0 = 10位
5位 模数计数器预分频器
  - 由A/D控制寄存器中的PRS[4:0]控制
  - 分频系数从2到64
  - 如果 PRS[4:0] = 0, 预分频不起作用
注: 设置PRS[4:0]时,  A/D Clock 不能大于 2 MHz.

SMP [1:0]
采样时间
00
2 A/D时钟周期
01
4 A/D时钟周期
10
8 A/D时钟周期
11
16 A/D时钟周期

转换时间计算:


2.4  控制寄存器5ATDCTL5

2.5  状态寄存器

SCF – 转换序列完成标志
     - 在单次转换模式时,当转换完成后置位 (SCAN = 0)
      在连续转换模式时,当第一次转换完成后置位 (SCAN = 1).
当 (AFFC = 0) ,写1清零.
ETORF - 外部触发覆盖标志
  • 如果在转换过程中高/低电平出现,置位FIFOR
–当结果寄存器在读出之前已经被写入时,置位 ( CCF没有清零)
CC[2:0]转换计数器
3-位计数器指向下一个将要转换的通道
CCF7 -CCF0–独立通道转换完成标志位              
每个相应的通道转换结束后置位,  当相应的A/D结果寄存器被读出时,清零 ,注意当AFFC位不同时的情况
第三节  A/D应用示例3.1  编程步骤
要让ATD开始转换工作,必须经过以下三个步骤:
1.将ADPU置1,使ATD启动;
2.按照要求对转换为数、扫描方式、采样时间、时钟频率及标志检查等方式进行设置;
3.发出启动命令;
如果上电默认状态即能满足工作要求,那么只要将ADPU置1,然后通过控制寄存器发出转换命令,即可实现转换。
3.2  A/D程序示例单通道查询
  1. #include <hidef.h>      /* common defines and macros */

  2. #include <mc9s12dp256.h>     /* derivative information */

  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"

  4. int ADValue;

  5. void AD_Init(void) //初始化

  6. {

  7. ATD0CTL2=0xc0; //定义寄存器2

  8. ATD0CTL3=0x20; //定义寄存器3

  9. ATD0CTL4=0xc3; //定义寄存器4

  10. ATD0CTL5=0xa6; //定义寄存器5

  11. ATD0DIEN=0x00; // 禁止数字输入

  12. }

  13. int AD_GetValue(void) //读取AD转换结果

  14. {

  15. ADValue = ATD0DR0;  //读结果寄存器

  16. }

  17. void main(void)

  18. {

  19.   AD_Init();   //AD初始化

  20. DDRB = 0xFF;//portB均为输出通道

  21.   PORTB  = 0x00;

  22.   for(;;)

  23.   {

  24.    while(!(ATD0STAT1&0x01)){;}   //等待转换结束

  25.    AD_GetValue();  //读取转换结果

  26.    PORTB = (int)ADValue;  //在B口显示转换值

  27.   }

  28. }
复制代码


3.3  A/D程序示例滤波
12中A/D系统启动一次A/D转换,能对同一模拟量输入连续执行多次转换。利用此功能,使用下面的程序,可在一次采样中执行四取二数字滤波,从而可滤除干扰,得到精度较高的A/D转换结果。
  1. #include <hidef.h>      /* common defines and macros */

  2. #include <mc9s12dp256.h>     /* derivative information */

  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"

  4. static long ADValue0, ADValue1,ADValue2,ADValue3;

  5. long a,b,c,d;

  6. long m,n,sum;

  7. long max();

  8. long min();

  9. void AD_Init(void) //初始化

  10. {

  11. ATD0CTL2=0xc0; //定义寄存器2

  12. ATD0CTL3=0x20; //定义寄存器3

  13. ATD0CTL4=0xc3; //定义寄存器4

  14. ATD0CTL5=0x86; //定义寄存器5

  15. ATD0DIEN=0x00; // 禁止数字输入

  16. }

  17. void AD_GetValue0(void) //读取AD转换结果

  18. {

  19. ADValue0 = ATD0DR0;  //读结果寄存器0

  20. a=ADValue0;

  21. }

  22. void AD_GetValue1(void) //读取AD转换结果

  23. {

  24. ADValue1 = ATD0DR1;  //读结果寄存器1

  25. b=ADValue1;

  26. }

  27. void AD_GetValue2(void) //读取AD转换结果

  28. {

  29. ADValue2 = ATD0DR2;  //读结果寄存器2

  30. c=ADValue2;

  31. }

  32. void AD_GetValue3(void) //读取AD转换结果

  33. {

  34. ADValue3 = ATD0DR3;  //读结果寄存器3

  35. d=ADValue3;

  36. }

  37. void main(void)

  38. {

  39.   AD_Init();   //AD初始化

  40.   DDRB = 0xFF;

  41.   PORTB  = 0x00;

  42.   for(;;)

  43.   {

  44.    while(!(ATD0STAT1&0x01)){;}     //等待转换结束

  45.    AD_GetValue0();                  //读取转换结果

  46.    while(!(ATD0STAT1&0x02)){;}     //等待转换结束

  47.    AD_GetValue1();                  //读取转换结果

  48.    while(!(ATD0STAT1&0x04)){;}     //等待转换结束

  49.    AD_GetValue2();                  //读取转换结果

  50.    while(!(ATD0STAT1&0x08)){;}     //等待转换结束

  51.    AD_GetValue3();                  //读取转换结果

  52.    m=max(a,b,c,d);

  53.    n=min(a,b,c,d);

  54.    sum=(a+b+c+d-m-n)/2;

  55.   }

  56. }
复制代码


3.4  A/D程序示例定时采样
在实际应用中,经常需每隔一段时间对某个模拟量进行一次采样。为实现定时A/D采样,可使用12中的输出比较功能来控制定时,其定时时间间隔可设定。在发生定时器输出比较中断时,进行启动A/D转换。然后等待A/D转换完成,读入数据。为了不浪费CPU时间去等待转换的完成,可使用中断方式。
本程序有两部分组成:一为初始化和启动程序,另一位定时器输出比较中断处理程序。CCF为标志字节,它的最高位为1,表示完成一次A/D转换,由程序可读入的值,并应清零该位。TOF为定时器控制标志位,=0表示为处于启动A/D状态;=1表示为等待定时时间到,以便下次采样。
  1. #include <hidef.h>      /* common defines and macros */

  2. #include <mc9s12dp256.h>     /* derivative information */

  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"

  4. int ADValue0;

  5. unsigned int i=0;

  6. int  counter=0;

  7. void AD_Init(void) //初始化

  8. {

  9. ATD0CTL2=0xc0; //定义寄存器2

  10. ATD0CTL3=0x08; //定义寄存器3

  11. ATD0CTL4=0xc3; //定义寄存器4

  12. ATD0CTL5=0xa0; //定义寄存器5

  13. ATD0DIEN=0x00; // 禁止数字输入

  14. }

  15. void AD_GetValue0(void) //读取AD转换结果

  16. {

  17. ADValue0 = ATD0DR0;  //读结果寄存器0

  18. }

  19. void main(void)

  20. {

  21.   TSCR2_PR   = 7;  //prescale factor is 8, bus clock/128=8Mhz/8

  22.   TSCR2_TOI  = 1;  //timer overflow interrupt enable

  23.   TSCR1_TEN  = 1;  //timer enable

  24.   AD_Init();   //AD初始化

  25.   DDRB = 0xFF;

  26.   PORTB  = 0x00;

  27.   EnableInterrupts;

  28.   for(;;) {

  29.   }

  30. }

  31. #pragma CODE_SEG NON_BANKED

  32. #pragma TRAP_PROC

  33. void Int_TimerOverFlow(void)

  34. {

  35. {

  36.    counter++;

  37.    if(counter==10)

  38.    {

  39.     while(!(ATD0STAT1&0x01)){;}     //等待转换结束

  40.     AD_GetValue0();                  //读取转换结果

  41.     PORTB = (int)ADValue0;         //在B口显示转换值

  42.     for(i=0;i<=1000;i++);   //delay

  43.      counter=0;

  44.    }

  45. }

  46. TFLG2_TOF  = 1;  //clear timer overflow flag

  47. }

  48. #pragma CODE_SEG DEFAULT
复制代码





第六章 EEPROM模块
    MC9S12DP256B内部同时集成了两种非易失存储器:FLASH和EEPROM,前者用于存储程序,后者可用来保存组态、设置等关键数据,它们均为防止误操作而设置了各种保护措施。本章主要介绍EEPROM的功能、特点及使用,包括擦除与写入步骤。
第一节  EEPROM模块介绍1.1  EEPROM功能
MC9S12DP256内部集成了4KB的EEPROM存储器,具有单块和整块擦除、编程、灵活保护和安全功能、快速区域擦除和字编程模式特点,规范字访问可在单总线周期内完成。EEPROM是一种非易失性存储介质,具有稳定、保密性好的特点,在系统掉电后,EEPROM中的内容仍能可靠保持不变,可以用来保存一些短时间不变的内容(如环境参数、产品序列等)。EEPROM可以同RAM一样地读,但要向EEPROM写入需要一定的时序和花费比RAM多的时间,即需要一段特定的程序来写EEPROM。
1.2  EEPROM结构
$0000~$0FFF是4KB为EEPROM的存储空间,复位时默认的EEPROM地址是从0开始的,而单片机各I/O寄存器的地址已经占用了从0地址开始的1KB空间,故EEPROM中开始的1KB空间($0000---$03FF)看不到了,所以实际上用户可以访问的是$0400---$0FFF的3KB的存储空间。
EEPROM设有保护机制,用户可以通过编程$0FFD,在普通模式下设定需要的保护空间,保护空间可在64B、128B、192B、256B、320B、384B、448B、512B中进行选择,相应的保护区在$0XXX---$0FFFF。由于设定保护地址所访问的地址也在所保护的区域中,所以一旦用户在普通模式下对$0FFD的内容进行了编程,就无法再在此模式下修改保护区的内容,从而也就达到了写保护或禁止局部擦除的效果。要改变保护区的设定,需要单片机工作在“特殊模式”下,访问EPROT寄存器,而一旦在特殊模式下取消了保密属性,该区的内容也就被擦除了。
1.3  EEPROM特点
①单电源供电擦写
②自动编程和擦除算法
③命令执行完可产生中断
④快速扇区擦除和字编程操作
⑤灵活的保护机制,避免意外编程和擦除
第二节  EEPROM寄存器简介2.1  时钟分频寄存器ECLKDIV
   
EDIVLD:EEPROM时钟分频加载。ECLKDIV寄存器被写入时此位置“1”;若此位置“0”,FCLKDIV寄存器从最后复位后没有写入。在没有写入此寄存器之前,擦写和编程eeprom将引起进入错误和命令不被执行。
1:最后复位后寄存器写入。
0:寄存器没有写入。
PRDIV8:8分频控制。
0 - 晶振时钟为EEPROM时钟分配器的时钟源
1 - 晶振时钟除以8后,为EEPROM时钟分配器的时钟源
EDIV[5:0] 时钟分配器位
PRDIV8和EDIV[5:0]联合用于将外部晶振频率分频为150~200KHZ。
注意:在对EEPROM进行操作之前,必须对时钟进行初始化
这个频率用于驱动EEPROM擦写和编程。外部晶振频率大于12.8MHZ,PRDIV8置1位,CLK=OSCCLK/8。反之,PRDIV8 置零,CLK=OSCCLK。
ECK=CLK/(EDIV[5:0]+1)。
2.2  配置寄存器ECNFG
   
CBEIE:命令缓冲区空中断允许位,
0:命令缓冲区空中断关闭。
1:命令缓冲区空中断允许。
CCIE — 指令完成中断使能,当所有指令被完成该位产生中断
0:命令完成中断关闭。
2.3  保护寄存器EPROT
   
EPOPEN:开启EEPROM编程/擦写
1:全部EEPROM或是部分EEPROM可以擦写;
0:所有EEPROM块保护。
EPDIS:EEPROM部分保护位
1:不作部分保护EEPROM。
0:EEPROM部分保护。
EP[2:0]——EEPROM保护地址范围
2.4  状态寄存器ESTAT
CBEIF:命令缓冲区空中断标志,表示地址、数据命令缓冲去空,新的命令序列开始,标志写“1”清零,通过标志清零,发出命令序列。写“0”将取消没有发出的命令序列,并ACCERR标志置“1”。
1:缓冲准备好接受新的命令。
0:缓冲器满
CCIF— 命令完成中断标志,表明不再有未决的指令。该标志通过硬件写入来清除,写操作不起作用。
1:所有命令完成。
0:命令正在进行。
PVIOL:保护冲突标志。表示在保护地址空间内进行了擦写或编程操作,在此标志置位同时,后续的擦写或编程操作无法进行。标志写“1”清零,写“0” 无影响。在CBEIF清零后或者当CCIF清零时,写入新的有效命令可以使保护错误标志清零。
1:保护冲突已发生。
0:无故障。
BLANK — 空白校验标志
表明在响应一条擦除校验指令后EEPROM块已被完全地擦除
该标志位通过写“1”被清除.
1 = EEPROM 被完全擦除.
0 = EEPROM未被完全擦除
ACCERR— 存取错误标志
表明在编程或擦除时序中有错误。该标志位通过写“1”来清除。
1 = 存取错误已出现
0 = 指令时序或执行被成功完成
ACCERR:进入错误标志。表示非法进入EEPROM块或者与定义命令序列冲突。以下命令序列会引起ACCERR置位:
1在初始化ECLKDIV之前,向EEPROM地址写值;
2向EEPROM地址写入错误的字或字节;
3在CBEIF未置1时,向EEPROM地址写值;
4在执行前一个编程或擦除命令之前,向EEPROM地址写入第二个字
5在向EEPROM地址空间写入字后,接着写其它EEPROM寄存器,没有写ECMD寄存器;
6在执行前一个写好的命令之前,向ECMD寄存器写入第二个命令;
7在对有保护的EEPROM空间,向ECMD寄存器写入整块擦除命令;
8在对有保护的EEPROM空间,向ECMD寄存器写入部分擦除命令;
9在写完命令寄存器后,接着写其它EEPROM寄存器,而没有写ESTAT寄存器;
10在命令行列已开始或擦/写命令已执行的同时,从EEPROM块读取。这样读到无效数据。
2.5  命令寄存器ECMD
ERASE:EEPROM擦除
0:  无意义
1:  在MASS=0时,区域擦除;在MASS=1时,区域擦除;
PROG:EEPROM编程
0:  无意义。
1: EEPROM 编程。
ERVER:擦除校验:
0:  无意义。
1:  区域擦除后擦除校验。
MASS: 全局铲除
0: 部分擦除
1: 全部擦除
注意:只有在ERASE和MASS同时置1时,才能实现全部擦除。
有关寄存器ECMD的命令字的设置:
第三节  EEPROM应用实例3.1  EEPROM的写入操作
EEPROM的写入操作可以按照以下步骤进行:
1. ECLKDIV寄存器初始化,确定分频因子
2. 检查EEPROM时钟分频寄存器(ECLKDIV_EDIVLD)是否已  经设置
3. 检查命令缓冲区(ESTAT_CBEIF)是否为空
4. 对读写错误(ESTAT_ACCER)标志位清零(写1清零)
5. 对保护区编程错误(ESTAT_PVIOL)标志位清零(写1清零)
6.检查保护寄存器(EPROT_EPOPEN)是否允许编程/写
7. 将编程的数据赋值给要编程的EEPROM地址
8. 对EEPROM命令寄存器(ECMD)写入编程命令(0x20)
9. 对命令缓冲区空标志位(ESTAT_CBEIF)清零(写1清零)
10. 等待,直到命令完成标志位(ESTAT_CCIF)置位
3.2  EEPROM的擦除操作
1. ECLKDIV寄存器初始化,确定分频因子
2. 检查EEPROM时钟分频寄存器(ECLKDIV_EDIVLD)是否已经设置
3.检查命令缓冲区(ESTAT_CBEIF)是否为空
4.对读写错误(ESTAT_ACCER)标志位清零(写1清零)
5.对保护区编程错误(ESTAT_PVIOL)标志位清零(写1清零)
6.检查保护寄存器(EPROT_EPOPEN)是否允许编程/写
7. 在要擦除的EEPROM的段地址内写入任意数据
8. 对EEPROM命令寄存器(ECMD)写入段擦除命令(0x40)
9. 对命令缓冲区空标志位(ESTAT_CBEIF)清零(写1清零)
10. 等待,直到命令完成标志位(ESTAT_CCIF)置位
3.3  EEPROM示例程序(见附件)


第七章 FLASH模块
    MC9S12DP256B内部同时集成了两种非易失存储器:FLASH和EEPROM,前者用于存储程序,后者可用来保存组态、设置等关键数据,它们均为防止误操作而设置了各种保护措施。本章主要介绍flash的功能、特点及使用,包括擦除与写入步骤。
第一节  FLASH模块介绍1.1  FLASH功能
MC9S12DP256内部集成了256KB的FLASH存储器,具有单块和整块擦除、编程、灵活保护和安全功能、快速区域擦除和字编程模式特点,规范字访问可在单总线周期内完成。可以存放整个程序或者需要高速访问或经常运行的程序代码,如操作系统核心或标准子程序库、数据表格等。FLASH模块对于单芯片应用系统是理想的程序存放处,它允许在现场进行代码更新。
Flash是一种非易失性存储介质,读取它的内容同RAM的读取一样方便,而对它的写操作却比EPROM还要快。同时,在系统掉电后,Flash中的内容仍能可靠保持不变。Flash的主要优点是结构简单、集成密度大、成本低。由于Flash可以局部擦除,且写入、擦除次数可达数万次以上,从而使开发微控制器不再需要昂贵的仿真器。
1.2  FLASH结构
$4000~4FFFF是48KB为FLASH的存储空间,分成3个16KB空间如图1-1所示。最后16KB空间的最后256B,即$FF00~$FFFF是中断向量表空间。由于FLASH模块的地址范围超过STAR12(16位)最大地址64KB空间,因此模块采用从一个$8000~$BFFF 16KB地址窗口分配地址,其余的地址位分配在分页寄存器PPAGE。256KB的FLASH由4个64KB块组成,如表3-1所示,每块64KBFLASH按照16位二进制方式组织,支持按字节或字方式访问。字节和规则字的访问可在单总线周期内完成,非规则字访问需两个总线256KB的FLASH被分成4个64KB块,每一块又可以继续细分为16KB一页,共16页。每一页再细分为4KB、2KB、1KB、或者512B一段。
              图1-1 MC9S12DP256B置位后的内存
1.3  FLASH特点
• 自动编程和擦除算法
• 快速扇区擦除和字编程操作
• 指令完成时中断
• 2段命令流水线,快速实现多个字的编程
• 灵活的保护机制,避免意外编程和擦除
• 预防非法访问的加密特征
第二节  FLASH寄存器简介
FLASH寄存器如表2-1所示
2.1 时钟分频寄存器FCLKDIV
FDIVLD:FLASH时钟分频加载。FCLKDIV寄存器被写入时此位置“1”;若此位置“0”,FCLKDIV寄存器从最后复位后没有写入。在没有写入此寄存器之前,擦写和编程FLASH将引起进入错误和命令不被执行
0 - FCLKDIV 寄存器没有被写过
1 - FCLKDIV 寄存器从最近一次复位起已经被写过
PRDIV8 使能时钟8分频
0 - 晶振时钟为FLASH时钟分配器的时钟源
1 - 晶振时钟除以8后,为FLASH时钟分配器的时钟源
FDIV[5:0] 时钟分配器位
—PRDIV8 和FDIV[5:0]的设置,必须满足FLASH时钟在150 kHz – 200 kHz范围内。最大的分频系数为512。在对FLASH进行操作之前,必须对时钟进行初始化,否则接下来的任何操作将是无效的。
2.2 配置寄存器 FCNFG
CBEIE — 指令缓冲区空中断使能
该位在空地址,数据和指令缓冲区的情况下使能中断。
1 = CBEIF标志被置位产生中断请求
0 = 指令缓冲区空中断禁止
CCIE — 指令完成中断使能
当所有指令被完成该位产生中断
1 = CCIF 标志被置位产生中断请求
0 = 指令完成中断禁止
KEYACC — 使能安全密匙写入
1 = 写入flash模块被解释成打开后门的密匙.
0 = Flash 写入后编程或擦除过程的开始
2.3 安全寄存器 FSEC
KEYEN:安全门码控制。
1:允许通过BDM或外部总线接口开启安全门。
0:禁止通过BDM或外部总线接口开启安全门。
当KEYEN置1时,用户可以通过以下步骤避开安全检查
FCNFG寄存器中KEYACC置1。
通过安全门比较码地址向FLASH 写四个正确16位字。
将FCNFG寄存器中KEYACC置0。
如果全部四个字与FALSH内容相符,强制通过SEC[1:0]处于非安全状态,使MCU处于非安全状态。
6.如果全部四个字与FALSH内容不相符,MCU处于安全状态,向CPU发回安全冲突信号。
NV[6:2]:非冲突标志位。这5位是用户可以用做非冲突标志。
SEC0[1:0] 存储安全位。这2位决定设备的安全状态。如表2-2所示
表2-3  SEC0[1:0] 与安全状态关系
SEC0[10]
00
01
10
11
描述
安全
安全
非安全
安全

2.4 保护寄存器 FPROT
FPOPEN—FLASH编程或擦除保护
1 = FPHDIS和FPLDIS定义的FLASH地址区域不被保护
0 =
FPHDIS—Flash 保护高地址范围禁止
该位用来决定在Flash块地址映射的较高末端是否存在一个被保护的区域
1 = 保护禁止
0 = 保护使能
FPHS[1:0]—Flash 保护高地址范围
这两位用来决定保护区域的范围。
FPLDIS—Flash 保护较低的地址范围禁止
该位用来决定在Flash块地址映射的较低末端是否存在一个被保护的区域
1 = 保护禁止
0 = 保护使能
FPLS[1:0]—Flash保护低地址范围
这两位用来决定保护区域的范围
2.5 状态寄存器 FSTAT 状态寄存器
CBEIF— 指令缓冲区空中断标志
表明地址,数据和指令缓冲区为空因此一个新的指令序列可以开始。
该标志通过写人“1”清除。指令序列通过清除该位来开始。
写入“0” 可异常中止一个尚未开始的指令序列且置ACCERR标志
1 = 缓冲区准备接收一个新指令
0 = 缓冲区满
CCIF— 指令完成中断标志
表明不再有未决的指令。该标志通过硬件写入来清除
写操作不起作用。
1 = 所有指令都被完成
0 = 指令进行中
PVIOL— 保护错误标志
表明试图对被保护的存储器区域中的一个地址编程或擦除。
若该位被置1则并行的编程或擦除指令不能被执行。该标志通过写入“1”被
清除,也可通过在CBEIF被清零后或当CCIF 被清除时写一条新的,有效
的指令来清除
1 = 保护系统侵犯已出项
0 = 无故障
ACCERR— 存取错误标志
表明在编程或擦除时序中有一个错误。该标志位通过写
“1”来清除。
1 = 存取错误已出现
0 = 指令时序或执行被成功完成
ACCERR:进入错误标志。表示非法进入FLASH块或者与定义命令序列冲突。以下命令序列会引起ACCERR置位:
1.在初始化FCLDIV之前,向FLASH地址写值;
2.当分页寄存器没有选择16KBFLASH块,向$8000~$BFFF地址空间的FLASH写值;
3.向$4000~$7FFF地址空间的FLASH写值或在BKSEL[1:0]没选FALSH 0下,向$C000~$FFFF地址空间的FLASH写值;
向FLASH地址空间写入错误的字或字节;
4.CBEIF未置1时,向FLASH地址写值;
5.在执行前一个编程或擦除命令之前,向FLASH地址空间写入第二个字;
6.在向FLASH地址空间写入字之后,接着写其他FLASH寄存器,没有写FCMD寄存器;
7.在执行完前一个写好的命令之前,向FCMD寄存器写入第二个命令;
8.在对有保护FLASH空间,向FCMD寄存器写入整块擦除命令;
9.在对有保护FLASH空间,向FCMD寄存器写入部分擦除命令;
10.在写完命令寄存器后,接着写其他FLASH寄存器,没有写FSTAT寄存器;
11.在命令序列已开始或擦除/编程命令以执行的同时,从FLASH块读取。这样读到无效数据,但能读其他没有编程的FLASH块。
BLANK:FLASH块校验标志,表示响应的擦除—校验命令时FLASH块全部擦除,标志写“1”清零,写“0” 无影响。
1:FLASH块全部擦除
0:FLASH块没有全部擦除
BITS[1:0] 这两位用于工厂测试预留,用户无法使用。
2.6 命令寄存器 FCMD
ERASE:FLASH 擦除
0:  无意义
1:  在MASS=0时,区域擦除;在MASS=1时,区域擦除;
PROG:FLASH 编程
0:  无意义。
1: FLASH 编程。
ERVER:擦除校验:
0:  无意义。
1:  区域擦除后擦除校验。
MASS: 全局铲除
0: 部分擦除
1: 全部擦除。
第三节  FLASH应用实例3.1  FLASH的写入操作
FLASH的写入操作可以按照以下步骤进行:
1. FCLKDIV寄存器初始化,确定分频因子
2.设置FCNFG寄存器和PPAGE寄存器,用于管理命令序列。写FCNFG寄存器中的BKSEL[1;0]位,选择要擦除或编程的FALKSH块状的相应寄存器。如果编程在8000~BFFF地址范围内,向(内核)寄存器(X030)写入值选择要编程的某一16KB页。当编程在4000~7FFF或C000~FFFF地址范围,没有必要写分页寄存器。
3. 检查FLASH时钟分频寄存器(FCLKDIV_FDIVLD)是否已经设置
4. 检查命令缓冲区(FSTAT_CBEIF)是否为空
5. 对读写错误(FSTAT_ACCER)标志位清零(写1清零)
6. 对保护区编程错误(FSTAT_PVIOL)标志位清零(写1清零)
7. 将编程的数据赋值给要编程的FLASH地址
8. 对FLASH命令寄存器(FCMD)写入编程命令(0x20)
9. 对命令缓冲区空标志位(FSTAT_CBEIF)清零(写1清零)
10. 等待,直到命令缓冲区标志位(FSTAT_CBEIF)置位
11. 检查是否还有新的数据需要写入到FLASH,如有转到第7步
12. 等待,直到命令完成标志位(FSTAT_CCIF)置位
3.2  FLASH的擦除操作
1. FCLKDIV寄存器初始化,确定分频因子
2.设置FCNFG寄存器和PPAGE寄存器,用于管理命令序列。写FCNFG寄存器中的BKSEL[1;0]位,选择要擦除或编程的FALKSH块状的相应寄存器。如果编程在8000~BFFF地址范围内,向(内核)寄存器(X030)写入值选择要编程的某一16KB页。当编程在4000~7FFF或C000~FFFF地址范围,没有必要写分页寄存器。
3. 检查FLASH时钟分频寄存器(FCLKDIV_FDIVLD)是否已经设置
4. 检查命令缓冲区(FSTAT_CBEIF)是否为空
5. 对读写错误(FSTAT_ACCER)标志位清零
6. 对保护区编程错误(FSTAT_PVIOL)标志位清零
7. 在要擦除的FLASH的段地址内写入任意数据
8. 对FLASH命令寄存器(FCMD)写入段擦除命令(0x40)
9. 对命令缓冲区空标志位(FSTAT_CBEIF)清零
10. 等待,直到命令完成标志位(FSTAT_CCIF)置位
3.3  FLASH的擦写操作注意事项
a、由于在FLASH的擦除和写入过程中,FLASH是不能读的,故擦除和写入FLASH的程序要放在RAM中,换言之,在FLASH的擦除或写入之前,要把擦除或写入的可执行代码复制到RAM中去,并让程序在RAM中执行。这段程序的编译是在FLASH中的程序段复制到RAM中的数据段,不论这段程序复制到RAM中的哪一段,即无论程序的起始地址在哪里,程序都能正确执行。这就要求生成的程序和装载地址无关,程序可以重载。
b、系统初始化后一定要严格按照上述步骤规范设置,这样避免出现逻辑错误也便于检查错误。此外,在编程选择写入或者擦除的范围时,一定要明确所选区域是否需要设置分页寄存器。
3.4  FLASH示例程序
  1. #include <hidef.h>      /* common defines and macros */
  2. #include <mc9s12dp256.h>     /* derivative information */
  3. #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
  4. #define portb (*((volatile unsigned char*)(0x0001)))
  5. #define ddrb  (*((volatile unsigned char*)(0x0003)))
  6. #define ppage  (*((volatile unsigned char*)(0x0030)))
  7. #define fclkdiv  (*((volatile unsigned char*)(0x0100)))
  8. #define fcnfg (*((volatile unsigned char*)(0x0103)))
  9. #define fprot (*((volatile unsigned char*)(0x0104)))
  10. #define fstat  (*((volatile unsigned char*)(0x0105)))         
  11. #define fcmd  (*((volatile unsigned char*)(0x0106)))
  12. #define any  (*((volatile unsigned char*)(erase)))
  13. #define a  (*((volatile unsigned char*)(0x2000)))
  14. #define EraseInSector 0x40;
  15. #define ProgramInAlignedWord 0x20;
  16. unsigned  char *flashaddr;
  17. unsigned  char *progaddr;
  18. unsigned  char *erase,*base,*end1,*end2;
  19. unsigned  int i;
  20.         /*flash擦除函数*/        
  21.         void eraseflash ()
  22.     {
  23.       while(erase<=(volatile unsigned char*)(end1))
  24.      {
  25.         while(!(fclkdiv&0x80))    //时钟是否加载
  26.                {}
  27.         while(!(fstat&0x80))     //命令缓冲区是否为空
  28.                {}
  29.         while(!(fprot&0x80))      //flash是否允许写入或者擦除
  30.                {}
  31.          any=0xff;
  32.         fcmd=EraseInSector;       //扇区擦除命令,每次擦除512B
  33.       fstat|=0x80;               //准备接收新的命令                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  34.       while(!(fstat&0x40))       //判断命令是否完成,没有则等待
  35.              {}
  36.       erase+=512;                 //擦除地址递加
  37.      }
  38.    }
  39.         /*flash写入函数*/
  40.        void  writeflash ()
  41.     {
  42.       while(flashaddr<=(volatile unsigned char*)(end2))
  43.       {
  44.          while(!(fclkdiv&0x80))
  45.                  {}
  46.          while(!(fstat&0x80))
  47.                  {}
  48.          while(!(fprot&0x80))
  49.                  {}
  50.          while(!SCI0SR1_RDRF) ;      //等待接收数据
  51.               SCI_Receive(&a) ;
  52.          *flashaddr=*progaddr ;
  53.             if(SCI0SR1_TDRE)
  54.       SCI_Transmit(*flashaddr);
  55.              flashaddr++;
  56.               progaddr++;
  57.      FCMD=ProgramInAlignedWord;
  58.              FSTAT|=0x80;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
  59.       while(!(FSTAT&0x40))
  60.                 {}
  61.       }
  62.    }
  63.       /*flash初始化函数*/
  64.         void  flash_init ()
  65.        {
  66.          fclkdiv=0x4a;   //时钟分频
  67.            FCNFG=0x00;    /*选择flash模块0*/
  68.            FSTAT=0X30;    //清除上次的错误标示位
  69.         // PPAGE=0x30;    /*分页寄存器设置,选择30页
  70.        }
  71.        // 串口初始化函数
  72.      int SCI_Init(void) {
  73.           SCI0BDL=0x34;
  74.           SCI0CR2=0X2C;
  75.         }
  76.         //发送子函数
  77.        int SCI_Transmit(byte data){
  78.         while(!SCI0SR1_TDRE) ;
  79.               SCI0DRL=data;
  80.             }
  81.         //接收子函数
  82.    int SCI_Receive(byte *data){
  83.       *data=SCI0DRL;
  84.        }
  85.      void main(void)
  86.     {
  87.       ddrb=0xff;
  88.       erase=(volatile unsigned char*)(0x4000);
  89.       end1= (volatile unsigned char*)(0xbfff);
  90.       end2= (volatile unsigned char*)(0x5000);
  91.       flashaddr=(volatile unsigned char*)(0x4000);
  92.       progaddr=(volatile unsigned char*)(0x2000);
  93.        flash_init () ;//flash初始化函数调用
  94.         portb=0xf0;
  95.         SCI_Init();     // 串口初始化函数调用
  96.         eraseflash () ;     //flash擦除函数
  97.         for(i=0;i<=10000;i++)
  98.         portb=0x0f;            //演示擦除完毕
  99.         writeflash ();        // flash写入函数
  100.          while(1) {}
  101.      }
复制代码

各位智能车同仁,加油哦!当然记得支持本店哦!我们一定会竭诚为你服务


第八章 CodeWarrior IDE 12应用
第一步:双击桌面CodeWarrior IDE 12图标,进入CodeWarrior IDE 12运用界面。在打开的界面中点击菜单File,在其下拉菜单中点击New,新建数据库文件。
第二步:新建一个数据库,如图选择第一行(HC(s)12New Project Wizard),然后再右面命名123(任意命名均可),确定。
第三步:进入欢迎界面,点击下一步。然后选择芯片型号MC9S12DP256B,点击下一步。程序一定要与单片机型号一直,否则在硬件调试中会出现错误。
第四步:选择使用的语言,在此选择C语言,点击“下一步”。
第五步:选择调试专家,在此选择“NO”,点击“下一步”。
第六步:界面如下图所示,选择“NO”,点击“下一步”。
第七步:界面如下图所示,选择” ANSI startup code” ,点击“下一步”。
第八步:选择有无浮点格式,根据自己情况而定,本程序在此选择“None”,点击“下一步”。
第九步:界面出现“选择存储模式?”,选择Banked,点击下一步。
第十步:界面出现“选择硬件连接电缆型号?”,前两项全选中,点击“完成”。
第十一步:进入如下界面,点击左侧Sources文件前面的加号,选择主程序中的Main.c,双击左键进入。
第十二步:显示界面如下,其中右侧为Main.c的编辑环境,可以在此输入你的单片机程序,也可以删除、修改或拷贝你前面编辑完成的程序。
例如当输入以下源程序:
#include <hidef.h>      /* common defines and macros */
#include <mc9s12dp256.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
void main(void)
{
  PWME_PWME0=0;   //关闭0通道
  PWMPRCLK=0X05;  //对总线时钟进行预分频,总线时钟为8M,分频后为250K
  PWMCLK_PCLK0=0; //设A为其时钟源
  PWMSCLA=0X7D;   //A时钟为2000Hz
  PWMPOL_PPOL0=1;//上升沿翻转
  PWMCAE_CAE0=0;//左对齐输出
  PWMDTY0=0X01; //占空比为25%的波形
  PWMPER0=0X04;  //输出为500Hz的波
  PWMCNT0=0X00;//0通道计数器清0
  PWME_PWME0=1;//0通道使能,0通道为输出通道
}
第十三步:程序输入以后,点击工具栏的图标(make)检查程序是否有错,如果有错,会在编辑框上方提示错误警告,以为标志,程序中会随之用红色箭头在程序中标出出错位置。例如下图中的程序有两个错误(第12行少了一个分号,导致无法编译通过)。检查程序并修改,直到没有错误为止。
前面介绍的属于程序在计算机中的编译运行,不需要开发工具,适用于初试开发和检查程序有无语法错误。下面介绍采用开发板的实际调试过程:
第一步:在上述单片机程序编译的基础上,将编程器与仿真试验板连接好,编程器下载口用数据线同计算机相连,试验板与5V直流电源相连。点击图标开始调试(debug),进入调试仿真状态后会出现如下界面。
第二步:在上面的界面中点击“确定”以后。会出现下面界面“连接失败”,仍点击“确定”。
第三步:在上面的界面单击“确定”以后,会出现如下界面单击“取消”


第四步:在单击“取消”以后,出现“硬件连接”失败界面如下图所示,单击确定。


第五步:在上面的界面单击“确定”以后,会发现光标在COMMAND窗口in>后闪动,输入字母set gdi(注意set和gdi之间有一个空格)后单击“回车键”。
第六步:单击Browse按钮,在安装的软件文件夹mc12中找到指定文件tbdml_gdi12.dll,然后单击“确定”。




第七步:在上面的界面单击“确定”以后,在图示窗口输入晶振频率数值16:00后单击“OK”。
第八步:在上面的界面单击“确定”以后,在如下界面中单击“OK”。
第九步:在TBDML HCS12中单击Load,然后在自己建立的文件夹里找到bin文件夹,单击bin文件夹然后再双击其中的第一个文件即可将源程序下载到flash中。
第十步:单击图示按钮即可执行所编程序功能。



完整的Word格式文档51黑下载地址:
MC9S12中文版培训教材1.doc (2.17 MB, 下载次数: 26)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表