嵌入式编程学习笔记(一)

      本文利用 MC9S12XEP100 单片机来学习A/D采集功能。

      首先开发板上有两个电位计作为A/D采集的输入信号,拉下图所示:


  将采集到的信号作比较,利用判断结果来控制开发板上的二极管的开和灭,二极管的电路连接如下:


然后将AD0的转换后的结果采用扫描的方式输出在数码管上,数码管的电路原理图如下:

    数码管的每个阳极连接一个限流电阻,8个阳极和单片机的PP0~PP7引脚相连。数码管的四个阴极采用4个三极管作为开关。三极管的基极经过电阻之后与单片机的PK3~PK0引脚相连。按照这个电路,扫描的具体方法是:P口输出第一位数码的码段,  K口控制第一位导通而其他三位不导通,延时5ms后,P口输出第二位数码的码段,  K口控制第二位导通而其他三位不导通,如此直到扫描完第四位后,继续扫描第一位。

     在code warrior中程序源代码如下所示:

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

#define  BUS_CLOCK		   40000000	     //总线频率,改变总线频率直接在此处修改
#define  OSC_CLOCK		   16000000	     //晶振频率
#define LEDCPU PORTK_PK4
#define LEDCPU_dir DDRK_DDRK4


#define CONT1 PORTK_PK3
#define CONT2 PORTK_PK2
#define CONT3 PORTK_PK1
#define CONT4 PORTK_PK0
#define CONT1_dir DDRK_DDRK3
#define CONT2_dir DDRK_DDRK2
#define CONT3_dir DDRK_DDRK1
#define CONT4_dir DDRK_DDRK0 
#define DATA PTP
#define DATA_dir DDRP

unsigned char AD_in0,AD_in1;


byte data1 = 0;
byte data2 = 0;
byte data3 = 0;
byte data4 = 0;
byte single = 1;

byte shuma[20]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,       //0~9对应的段码
                0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};      //0~9后加小数点对应的段码
                
    
                

/* ------------------------------------------------------------------------------------
// ATD 的运行方式分为单次和连续运行两种:
//     在单次方式下,每个转换序列完成后,寄存器 ATDSTAT 中的 SCF 置位,然后 ATD 模块暂停。
//     在连续方式下,转换以转换序列为单位连续进行,当第一个转换序列完成后,SCF 置位,
//     同时 ATD 模块开始下一个转换序列。
//  在上述两种方式下,每个通道的转换结果进入到对应结果寄存器后,寄存器ATDSTAT1中对应的 CCF 位置 1,
//  对存放转换结果的寄存器进行读操作后,CCF 位将自动清0.
//  转换过程的启动是通过写入寄存器 ATDCTL5 实现的。
//  ATD 转换所需要的时钟周期数是固定不变的,但是采样时间和时钟频率可以通过 ATDCTL4 在一定范围内选择.
//  因此转换时间也可以选择。
// ---------------------------------------------------------------------------------- */

/*--------------------------------------------------------------------------------------
// MCU上电后, ATD模块各个寄存器处于默认关闭状态, 至少需要经过下面几个步骤, 才可以使ATD完成
// 所需要的转换工作:
//  (1) 设置ATD 控制寄存器 ATDCTL1-4: 根据对转换位数、扫描方式、采样时间、时钟频率的要求及
//  标志检查方式进行相应寄存器的设置; 
//  (2) 通过写ATD 控制寄存器 ATDCTL5 启动新的ATD转换.
//  (3) 通过查询ATD 状态寄存器 ATDSTAT0 或响应A/D转换完成标志做中断处理.
// ------------------------------------------------------------------------------------*/





/*************************************************************/
/*                      初始化锁相环                         */
/*************************************************************/
void INIT_PLL(void) 
{
    CLKSEL &= 0x7f;       //设置OSCCLK作为系统时钟
    PLLCTL &= 0x8F;       //禁止锁相环
 
    //PLLCLK=2×OSCCLK×(SYNR+1)/(REFDV+1), fbus=PLLCLK/2
    #if(BUS_CLOCK == 120000000) 
        SYNR = 0xcd;
    #elif(BUS_CLOCK == 104000000) 
      SYNR = 0xcc;
    #elif(BUS_CLOCK == 96000000)                      
      SYNR = 0xcb;
    #elif(BUS_CLOCK == 88000000) 
      SYNR = 0xca;
    #elif(BUS_CLOCK == 80000000) 
      SYNR = 0xc9;
    #elif(BUS_CLOCK == 72000000) 
      SYNR = 0xc8;
    #elif(BUS_CLOCK == 64000000) 
      SYNR = 0xc7;
    #elif(BUS_CLOCK == 56000000) 
      SYNR = 0xc6;
    #elif(BUS_CLOCK == 48000000) 
      SYNR = 0xc5;
    #elif(BUS_CLOCK == 40000000) 
      SYNR = 0x44;
    #elif(BUS_CLOCK == 32000000)
      SYNR = 0x43;     
    #elif(BUS_CLOCK == 24000000)
      SYNR = 0x42;
    #elif(BUS_CLOCK == 16000000)
      SYNR = 0x01;
   #endif 

    REFDV = 0x81;
    PLLCTL |=0x70;  //使能锁相环
    asm NOP;
    asm NOP;
    while(!(CRGFLG&0x08)); //PLLCLK锁定
    CLKSEL |= 0x80;        //设置PLLCLK为系统时钟
}






/*************************************************************/
/*                      初始化AD模块                         */
/*************************************************************/  
     
void INIT_AD(void)

{

  ATD0DIEN_IEN0 = 0;
  ATD0DIEN_IEN1 = 0;
  
 // 相应AD通道禁止为I/O口 
 // ATD0DIEN 是ATD 数字信号输入使能寄存器,
 //     0: 禁止数字信号输入
 //     1: 允许数字信号输入
 
  
  ATD0CTL2 = 0x40;   
       
  // 启动A/D转换,快速清零,禁止中断
  // ATD0CTL2 的定义如下:
  /*
    // ATD0CTL2 - ATD 0 Control Register 2; 0x000002C2 
    union {
      byte Byte;
      struct {
        byte ACMPIE      :1;             // ATD Compare Interrupt Enable  
        byte ASCIE       :1;             // ATD Sequence Complete Interrupt Enable  
        byte ETRIGE      :1;             // External Trigger Mode enable  
        byte ETRIGP      :1;             // External Trigger Polarity  
        byte ETRIGLE     :1;             // External Trigger Level/Edge control  
        byte ICLKSTP     :1;             // Internal Clock in Stop Mode Bit  
        byte AFFC        :1;             // ATD Fast Conversion Complete Flag Clear  
        byte             :1; 
      } Bits;
    } ATD0CTL2STR;
    #define ATD0CTL2                    _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Byte
    #define ATD0CTL2_ACMPIE             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ACMPIE
    #define ATD0CTL2_ASCIE              _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ASCIE
    #define ATD0CTL2_ETRIGE             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGE
    #define ATD0CTL2_ETRIGP             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGP
    #define ATD0CTL2_ETRIGLE            _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGLE
    #define ATD0CTL2_ICLKSTP            _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ICLKSTP
    #define ATD0CTL2_AFFC               _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.AFFC
  */ 
 
   // ATD0CTL2寄存器如下:
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // |      |  AFFC |ICLKSTP|ETRIGLE| ETRIGP| ETRIGE | ASCIE | ACMPIE |
   // |______|_______|_______|_______|_______|________|_______|________|
   
   // AFFC ------ A/D快速转换完成标志位清零
   //      1: 快速标志位清零顺序, 每次读取结果寄存器自动清零
   //      0: 正常标志位清零顺序, 需要手动对状态标志位清零
   // 
   
 
 
  ATD0CTL1_SRES = 0b00; 
      
  // ATD转换精度设置为8位
  // 我们进入头文件查看 ATD0CTL1_SRES 的定义:                          
   /*
       // ATD0CTL1 - ATD 0 Control Register 1; 0x000002C1
       struct {
       union {
          byte Byte;
          struct {
            byte ETRIGCH0    :1;            // External Trigger Channel Select Bit 0 
            byte ETRIGCH1    :1;            // External Trigger Channel Select Bit 1  
            byte ETRIGCH2    :1;            // External Trigger Channel Select Bit 2  
            byte ETRIGCH3    :1;            // External Trigger Channel Select Bit 3  
            byte SMP_DIS     :1;            // Discharge Before Sampling Bit  
            byte SRES0       :1;            // A/D Resolution Select Bit 0  
            byte SRES1       :1;            // A/D Resolution Select Bit 1  
            byte ETRIGSEL    :1;            // External Trigger Source Select  
                 } Bits;
          struct {
            byte grpETRIGCH :4;
            byte     :1;
            byte grpSRES :2;
            byte     :1;
                  } MergedBits;
               } ATD0CTL1STR;    
             } Overlap_STR;
           } ATD0CTL01STR;
   
        extern volatile ATD0CTL01STR _ATD0CTL01 @(REG_BASE + 0x000002C0UL);
        #define ATD0CTL1                    _ATD0CTL01.Overlap_STR.ATD0CTL1STR.Byte
        #define ATD0CTL1_SRES               _ATD0CTL01.Overlap_STR.ATD0CTL1STR.MergedBits.grpSRES   
    */
  // 因此ATD0CTL1_SRES 有两个 位 的空间, 
  
 
   
  
  
  ATD0CTL3 = 0x90;        
  
  // 转换序列长度为2,右对齐模式
  /*
    // ATD0CTL3 - ATD 0 Control Register 3; 0x000002C3  
    union {
      byte Byte;
      struct {
        byte FRZ0        :1;           // Background Debug Freeze Enable Bit 0  
        byte FRZ1        :1;           // Background Debug Freeze Enable Bit 1  
        byte FIFO        :1;           // Result Register FIFO Mode  
        byte S1C         :1;           // Conversion Sequence Length 1 
        byte S2C         :1;           // Conversion Sequence Length 2  
        byte S4C         :1;           // Conversion Sequence Length 4  
        byte S8C         :1;           // Conversion Sequence Length 8  
        byte DJM         :1;           // Result Register Data Justification  
      } Bits;
      struct {
        byte grpFRZ :2;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
      } MergedBits;
    } ATD0CTL3STR;
    #define ATD0CTL3                    _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Byte
    #define ATD0CTL3_FRZ0               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FRZ0
    #define ATD0CTL3_FRZ1               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FRZ1
    #define ATD0CTL3_FIFO               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FIFO
    #define ATD0CTL3_S1C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S1C
    #define ATD0CTL3_S2C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S2C
    #define ATD0CTL3_S4C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S4C
    #define ATD0CTL3_S8C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S8C
    #define ATD0CTL3_DJM                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.DJM
    #define ATD0CTL3_FRZ                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.MergedBits.grpFRZ
  */                 
   // ATD0CTL3(ATD控制寄存器3)如下所示:
  
   //bit  7      6        5      4       3       2        1       0
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // | DJM  |  S8C  |  S4C  |  S2C  |  S1C  | FIFO   |  FRZ1 | FRZ0   |
   // |______|_______|_______|_______|_______|________|_______|________|
   //
   // (1) DJM  ----- 结果寄存器数据对齐方式
   //    这一位决定结果寄存器的数据如何向IP数据总线的位上映射.映射关系取决于A/D转换的分辨率。
   //    对于10位的分辨率, 左对齐模式下,结果寄存器数据将映射到数据总线的6~15位, 第15位为高位; 
   //                      右对齐模式下,结果寄存器数据将映射到数据总线的0~9位,第9位为高位.
   //    对于8位的分辨率,  左对齐模式下,结果寄存器数据将映射到数据总线的8~15位, 第15位为高位; 
   //                      右对齐模式下,结果寄存器数据将映射到数据总线的0~7位,第7位为高位.
   //    0: 左对齐模式
   //    1: 右对齐模式
   //
   // (2) S8C/S4C/S2C/S1C ----- 选择转换序列的长度
  
  
  
  
 
  ATD0CTL4 = 0x84;
         
  // 采样时间为12个ATD转换时钟周期数, 
  // fatdclk = fbus/(2*(prs+1))=40/2/5, 
  // 因此 AD模块时钟频率为4MHz         
  
  // 首先ATD0CTL4 在头文件中的定义为:  
  /*  
   struct {
    // ATD0CTL4 - ATD 0 Control Register 4; 0x000002C4  
    union {
      byte Byte;
      struct {
        byte PRS0        :1;       // ATD Clock Prescaler 0 
        byte PRS1        :1;       // ATD Clock Prescaler 1 
        byte PRS2        :1;       // ATD Clock Prescaler 2 
        byte PRS3        :1;       // ATD Clock Prescaler 3 
        byte PRS4        :1;       // ATD Clock Prescaler 4 
        byte SMP0        :1;       // Sample Time Select 0 
        byte SMP1        :1;       // Sample Time Select 1 
        byte SMP2        :1;       // Sample Time Select 2 
      } Bits;
      struct {
        byte grpPRS :5;
        byte grpSMP :3;
      } MergedBits;
    } ATD0CTL4STR;
    #define ATD0CTL4                    _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Byte
    #define ATD0CTL4_PRS0               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS0
    #define ATD0CTL4_PRS1               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS1
    #define ATD0CTL4_PRS2               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS2
    #define ATD0CTL4_PRS3               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS3
    #define ATD0CTL4_PRS4               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS4
    #define ATD0CTL4_SMP0               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.SMP0
    #define ATD0CTL4_SMP1               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.SMP1
    #define ATD0CTL4_SMP2               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.SMP2
    #define ATD0CTL4_PRS                _ATD0CTL45.Overlap_STR.ATD0CTL4STR.MergedBits.grpPRS
    #define ATD0CTL4_SMP                _ATD0CTL45.Overlap_STR.ATD0CTL4STR.MergedBits.grpSMP
   */
   // ATD0CTL4(ATD控制寄存器4)如下所示:
  
   //bit  7      6        5      4       3       2        1       0
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // | SMP2 |  SMP1 |  SMP0 |  MULT |  PRS4 | PRS3   |  PRS1 | PRS0   |
   // |______|_______|_______|_______|_______|________|_______|________|
   //
   // (1) SMP[2:0] ----- 采样时间选择
   //    这三位选择采样时间长度, 单位是ATD转换时钟周期数, SMP[2:0]取不同值对应的采样时间可以查表.
   //
   // (2) PRS[4:0] ----- ATD模块时钟的预分频系数PRS
  
   // -----------------------------------------------------------------------------    
   //  ATD时钟的计算方法如下:
   //                              fbus(总线时钟)
   //     fatdclk(ATD模块时钟) = ----------------------- 
   //                                2 * (PRS+1)
   // ---------------------------------------------------------------------------                       
}   



 

/*************************************************************/
/*                      启动AD模块                           */
/*************************************************************/ 
  
 void Start_ATD(void)
 
 {
 
   ATD0CTL5 = 0x30;    
   
   // 连续执行转换序列AN0,AN1,多通道采样模式, 从AN0通道开始采样
   // 向这个寄存器写入将中止正在执行的转换序列, 并启动一个新的转换序列. 
   
   /*
    // ATD0CTL5 - ATD 0 Control Register 5; 0x000002C5 
    union {
      byte Byte;
      struct {
        byte CA          :1;           // Analog Input Channel Select Code A 
        byte CB          :1;           // Analog Input Channel Select Code B 
        byte CC          :1;           // Analog Input Channel Select Code C 
        byte CD          :1;           // Analog Input Channel Select Code D 
        byte MULT        :1;           // Multi-Channel Sample Mode 
        byte SCAN        :1;           // Continuous Conversion Sequence Mode 
        byte SC          :1;           // Special Channel Conversion Bit 
        byte             :1; 
      } Bits;
      struct {
        byte grpCx :4;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
      } MergedBits;
    } ATD0CTL5STR;
    #define ATD0CTL5                    _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Byte
    #define ATD0CTL5_CA                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CA
    #define ATD0CTL5_CB                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CB
    #define ATD0CTL5_CC                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CC
    #define ATD0CTL5_CD                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CD
    #define ATD0CTL5_MULT               _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.MULT
    #define ATD0CTL5_SCAN               _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.SCAN
    #define ATD0CTL5_SC                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.SC
    #define ATD0CTL5_Cx                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.MergedBits.grpCx 
   */
   
   // ATD0CTL5(控制寄存器5)如下所示:
  
   //bit  7      6        5      4       3       2        1       0
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // |      |  SC   |  SCAN |  MULT |   CD  |   CC   |   CB  |   CA   |
   // |______|_______|_______|_______|_______|________|_______|________|
   //
   // (1)  SC ----- 特殊通道转换使能位
   //        0: 禁止特殊通道转换
   //        1: 使能特殊通道转换
   // (2)  SCAN ---- 连续转换模式
   //        1: 连续转换模式
   //        0: 单次转换模式
   //        如果这一位为0,则一次向ATD0CTL5的写入将启动一个转换序列,转换序列被执行,
   //         执行后转换序列结束标志位(SCF)置1,之后模块返回空闲模式. 
   // (3)  MULT ----- 多通道采样模式
   //        0: 只对指定通道采样
   //        1: 对多通道采样
   // (4)  CD/CC/CB/CA ----- 模拟输入通道选择位
   //        这几位是选择哪个(或哪些)模拟输入通道的信号被采样并转换为数字信号.
   //        在通道转换模式下, 这几位表示被采样的通道
   //        在多通道转换模式下, 这几位表示转换序列的第一个通道.
   
}










/*************************************************************/
/*                      初始化周期性定时器                   */
/*************************************************************/ 
       
 void Init_PIT(void)
 
 {
  // --------------------------------------------------------------------------
  // 微处理器常常内置定时器(硬件定时器) , 比如MS9S12XS内置ECT、PWM 、以及四个24位PIT定时器
  // 想要使能某一路定时器, 需要写通道使能寄存器和 PIT 控制寄存器来使能PIT模块
  // 4个16位定时器, 共享两个8位微计数器, 通过写PIT复用寄存器来配置
  // 当某一路定时器使能时, 16位和8位计数器对应的加载寄存器的值自动加载
  // 按照MCU内部总线时钟, 24位计数器减1, 直至为零时,自动重加载,同时, 将超时标志置位, 
  // 若对应的定时中断被使能, 则产生定时中断.
  //                 (16位计数器值+1) * (8位计数器值+1)
  // 定时周期 =   ----------------------------------------- 
  //                            BusCLK
  // -------------------------------------------------------------------------------------
  
 
   PITMTLD0=249;    
   
   // 为0通道8位计数器赋值
   // PIT Micro Timer Load Register 0 to 1 (PITMTLD0-1)                 
   // 该寄存器用于设置PIT模块中的8位计数器初值,以实现24位的计数。设定值为0到255范围
   /*
   // PITMTLD0 - PIT Micro Timer Load Register 0; 0x00000346 
      typedef union {
        byte Byte;
        struct {
          byte PMTLD0      :1;                        // PIT Micro Timer Load Bit 0  
          byte PMTLD1      :1;                        // PIT Micro Timer Load Bit 1  
          byte PMTLD2      :1;                        // PIT Micro Timer Load Bit 2  
          byte PMTLD3      :1;                        // PIT Micro Timer Load Bit 3  
          byte PMTLD4      :1;                        // PIT Micro Timer Load Bit 4  
          byte PMTLD5      :1;                        // PIT Micro Timer Load Bit 5  
          byte PMTLD6      :1;                        // PIT Micro Timer Load Bit 6  
          byte PMTLD7      :1;                        // PIT Micro Timer Load Bit 7  
        } Bits;
      } PITMTLD0STR;
      extern volatile PITMTLD0STR _PITMTLD0 @(REG_BASE + 0x00000346UL);
      #define PITMTLD0                        _PITMTLD0.Byte
      #define PITMTLD0_PMTLD0                 _PITMTLD0.Bits.PMTLD0
      #define PITMTLD0_PMTLD1                 _PITMTLD0.Bits.PMTLD1
      #define PITMTLD0_PMTLD2                 _PITMTLD0.Bits.PMTLD2
      #define PITMTLD0_PMTLD3                 _PITMTLD0.Bits.PMTLD3
      #define PITMTLD0_PMTLD4                 _PITMTLD0.Bits.PMTLD4
      #define PITMTLD0_PMTLD5                 _PITMTLD0.Bits.PMTLD5
      #define PITMTLD0_PMTLD6                 _PITMTLD0.Bits.PMTLD6
      #define PITMTLD0_PMTLD7                 _PITMTLD0.Bits.PMTLD7
   */
   
   PITLD0 = 799; 
         
   //为0通道16位计数器赋值   
   // PIT Load Register 0 to 3(PITLD0-3) 
   // 该寄存器用于设置PIT模块中的16位计数器初值,和8位计数器配合而成24位计数器。设定值范围0-655352
   // PITLD0的定义如下:
   /*
   // PITLD0 - PIT Load Register 0; 0x00000348  
        typedef union {
          word Word;
        } PITLD0STR;
        extern volatile PITLD0STR _PITLD0 @(REG_BASE + 0x00000348UL);
        #define PITLD0                   _PITLD0.Word
   */

      
    // 因位Fbus(总线时钟)= 40MHZ 
    // 故0通道的定时周期可以如下计算:
    // (249+1)*(799+1)/40M = 0.005s = 5ms.
    
   
  
     
                     

   PITMUX_PMUX0=0;   
   
   // 设置第0通道使用微计数器0
   // 
   /* // PITMUX - PIT Multiplex Register; 0x00000343  
      typedef union {
        byte Byte;
        struct {
          byte PMUX0       :1;                    // PIT Multiplex Bits for Timer Channel 0  
          byte PMUX1       :1;                    // PIT Multiplex Bits for Timer Channel 1  
          byte PMUX2       :1;                    // PIT Multiplex Bits for Timer Channel 2  
          byte PMUX3       :1;                    // PIT Multiplex Bits for Timer Channel 3  
          byte PMUX4       :1;                    // PIT Multiplex Bits for Timer Channel 4 
          byte PMUX5       :1;                    // PIT Multiplex Bits for Timer Channel 5  
          byte PMUX6       :1;                    // PIT Multiplex Bits for Timer Channel 6  
          byte PMUX7       :1;                    // PIT Multiplex Bits for Timer Channel 7  
        } Bits;
      } PITMUXSTR;
      extern volatile PITMUXSTR _PITMUX @(REG_BASE + 0x00000343UL);
      #define PITMUX                          _PITMUX.Byte
      #define PITMUX_PMUX0                    _PITMUX.Bits.PMUX0
      #define PITMUX_PMUX1                    _PITMUX.Bits.PMUX1
      #define PITMUX_PMUX2                    _PITMUX.Bits.PMUX2
      #define PITMUX_PMUX3                    _PITMUX.Bits.PMUX3
      #define PITMUX_PMUX4                    _PITMUX.Bits.PMUX4
      #define PITMUX_PMUX5                    _PITMUX.Bits.PMUX5
      #define PITMUX_PMUX6                    _PITMUX.Bits.PMUX6
      #define PITMUX_PMUX7                    _PITMUX.Bits.PMUX7
    */
  
   //  PIT定时器复合寄存器 PITMUX 如下:
   
   // bit   7        6        5        4       3      2        1         0
   //    ______________________________________________________________________
   // R |        |       |         |       |      |       |         |          |
   //   |  PMUX7 | PMUX6 |  PMUX5  | PMUX4 | PMUX3| PMUX2 | PMUX1   |   PMUX0  |
   // W |        |       |         |       |      |       |         |          |
   //   |________|_______|_________|_______|______|_______|_________|__________|
   //复位:  0       0         0        0      0       0         0         0
   
   // PMUX[7:0]: PIT定时器复合寄存器控制位. 
   //     该寄存器控制16位定时器与8位微定时器时基0或者时基1连接复合
   //     0: 相应16位定时器与微定时器时基0连接
   //     1: 相应16位定时器与微定时器时基1连接
   
   
   
   PITCE_PCE0=1;
        
   // 设置第0通道计数器工作
   // 
   /* // PITCE - PIT Channel Enable Register; 0x00000342  
      typedef union {
        byte Byte;
        struct {
          byte PCE0        :1;               // PIT Enable Bits for Timer Channel 0  
          byte PCE1        :1;               // PIT Enable Bits for Timer Channel 1  
          byte PCE2        :1;               // PIT Enable Bits for Timer Channel 2  
          byte PCE3        :1;               // PIT Enable Bits for Timer Channel 3  
          byte PCE4        :1;               // PIT Enable Bits for Timer Channel 4  
          byte PCE5        :1;               // PIT Enable Bits for Timer Channel 5  
          byte PCE6        :1;               // PIT Enable Bits for Timer Channel 6  
          byte PCE7        :1;               // PIT Enable Bits for Timer Channel 7  
        } Bits;
      } PITCESTR;
      extern volatile PITCESTR _PITCE @(REG_BASE + 0x00000342UL);
      #define PITCE                           _PITCE.Byte
      #define PITCE_PCE0                      _PITCE.Bits.PCE0
      #define PITCE_PCE1                      _PITCE.Bits.PCE1
      #define PITCE_PCE2                      _PITCE.Bits.PCE2
      #define PITCE_PCE3                      _PITCE.Bits.PCE3
      #define PITCE_PCE4                      _PITCE.Bits.PCE4
      #define PITCE_PCE5                      _PITCE.Bits.PCE5
      #define PITCE_PCE6                      _PITCE.Bits.PCE6
      #define PITCE_PCE7                      _PITCE.Bits.PCE7
    */      
   //  PIT通道使能寄存器 PITCE 如下:
   
   // bit   7        6        5        4       3      2        1         0
   //    ____________________________________________________________________
   // R |        |       |         |       |      |       |         |        |
   //   |  PCE7  | PCE6  |  PCE5   |  PCE4 |  PCE3|  PCE2 |  PCE1   |  PCE0  |
   // W |        |       |         |       |      |       |         |        |
   //   |________|_______|_________|_______|______|_______|_________|________|
   //复位:  0       0         0        0      0       0         0         0
  
   // PCE[7:0]:  PIT使能控制位.
   //     该寄存器使能PIT四个通道, 如果PCE写0, PIT通道将被禁止, PITTF(PIT溢出标志寄存器)中 
   //     相应的标志位也将被清除; 如果PCE写1, PIT通道将被使能, 16位定时器计数器被载入初始值
   //     并开始计数.
   //    0: 相应通道使能
   //    1: 相应通道禁止
   
   


   
   
   PITCFLMT=0x80;
       
   // 使能PIT模块
   // 我们进入头文件查询  PITCFLMT 的定义:
   /* 
   // PITCFLMT - PIT Control and Force Load Micro Timer Register; 0x00000340  
        typedef union {
          byte Byte;
          struct {
            byte PFLMT0      :1;             // PIT Force Load Bits for Micro Timer 0  
            byte PFLMT1      :1;             // PIT Force Load Bits for Micro Timer 1  
            byte             :1; 
            byte             :1; 
            byte             :1; 
            byte PITFRZ      :1;            // PIT Counter Freeze while in Freeze Mode Bit  
            byte PITSWAI     :1;            // PIT Stop in Wait Mode Bit  
            byte PITE        :1;            // PIT Module Enable Bit  
          } Bits;
          struct {
            byte grpPFLMT :2;
            byte         :1;
            byte         :1;
            byte         :1;
            byte         :1;
            byte         :1;
            byte         :1;
          } MergedBits;
        } PITCFLMTSTR;
        extern volatile PITCFLMTSTR _PITCFLMT @(REG_BASE + 0x00000340UL);
        #define PITCFLMT                        _PITCFLMT.Byte
        #define PITCFLMT_PFLMT0                 _PITCFLMT.Bits.PFLMT0
        #define PITCFLMT_PFLMT1                 _PITCFLMT.Bits.PFLMT1
        #define PITCFLMT_PITFRZ                 _PITCFLMT.Bits.PITFRZ
        #define PITCFLMT_PITSWAI                _PITCFLMT.Bits.PITSWAI
        #define PITCFLMT_PITE                   _PITCFLMT.Bits.PITE
        #define PITCFLMT_PFLMT                  _PITCFLMT.MergedBits.grpPFLMT
   */
   
  // PIT控制寄存器及强制载入微定时器寄存器 PITCFLMT 如下所示:  
      
   // bit   7        6        5        4       3      2        1         0
   //    ____________________________________________________________________
   // R |        |       |         |   0   |  0   |  0    |    0    |    0   |
   //   | PITE   |PITSWAI| PITFRZ  |_______|______|_______|_________|________|
   // W |        |       |         |       |      |       | PFLMT1  | PFLMT0 |
   //   |________|_______|_________|_______|______|_______|_________|________|
   //复位:  0       0         0        0      0       0         0         0
  
   //  PITE: PIT模块使能位. 
   //     0: 禁止PIT模块
   //     1: 使能PIT模块
   
   
   
   PITINTE_PINTE0=1; //0通道定时器定时中断被使能
   
   // 我们进入头文件查询 PITINTE 的定义:
   /* // PITINTE - PIT Interrupt Enable Register; 0x00000344 
      typedef union {
        byte Byte;
        struct {
          byte PINTE0      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 0 
          byte PINTE1      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 1 
          byte PINTE2      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 2 
          byte PINTE3      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 3 
          byte PINTE4      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 4 
          byte PINTE5      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 5 
          byte PINTE6      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 6 
          byte PINTE7      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 7 
        } Bits;
      } PITINTESTR;
      extern volatile PITINTESTR _PITINTE @(REG_BASE + 0x00000344UL);
      #define PITINTE                         _PITINTE.Byte
      #define PITINTE_PINTE0                  _PITINTE.Bits.PINTE0
      #define PITINTE_PINTE1                  _PITINTE.Bits.PINTE1
      #define PITINTE_PINTE2                  _PITINTE.Bits.PINTE2
      #define PITINTE_PINTE3                  _PITINTE.Bits.PINTE3
      #define PITINTE_PINTE4                  _PITINTE.Bits.PINTE4
      #define PITINTE_PINTE5                  _PITINTE.Bits.PINTE5
      #define PITINTE_PINTE6                  _PITINTE.Bits.PINTE6
      #define PITINTE_PINTE7                  _PITINTE.Bits.PINTE7
  */
   
   //  PIT 中断使能寄存器 PITINTE 如下所示:
     
   // bit   7        6        5        4       3      2        1         0
   //    ____________________________________________________________________
   // R |        |       |         |       |      |       |         |        |
   //   | PINTE7 | PINTE6| PINTE5  |PINTE4 |PINTE3| PINTE2|  PINTE1 | PINTE0 |
   // W |        |       |         |       |      |       |         |        |
   //   |________|_______|_________|_______|______|_______|_________|________|
   //复位:  0       0         0        0      0       0         0         0
   
   // PINTE[7:0] : PIT定时器溢出中断使能控制位.
   //    0: PIT相应通道溢出中断禁止
   //    1: PIT相应通道溢出中断使能 
                   
 }
 
 






/*************************************************************/
/*                      初始化端口                           */
/*************************************************************/
void INIT_port(void) 
{
  CONT1_dir = 1;
  CONT2_dir = 1;
  CONT3_dir = 1;
  CONT4_dir = 1;
  CONT1 = 0;
  CONT2 = 0;
  CONT3 = 0;
  CONT4 = 0;
  DATA_dir = 0xff;
  DATA = 0x00;
}



/*************************************************************/
/*                        延时函数                           */
/*************************************************************/
void delay(void) 
{
 unsigned int i,j;
 for(j=0;j<200;j++)
 for(i=0;i<60000;i++);
}





 //----------------------PIT模块-----------------------------------------------
 
/*************************************************************/
/*                  周期定时器0中断函数                      */
/*************************************************************/ 

#pragma CODE_SEG __NEAR_SEG NON_BANKED

// NON_BANKED一般位于0xc000-0xffff区域(非分页区), 而这个区域是16位单片机可以直接寻址的区域,
// 由于飞思卡尔16位单片机的中断向量是16位,所以中断函数只有被置于非分页区内才能被寻址到,
// 而__NEAR_SEG告诉编译器函数放在固定页中,只有固定页中的函数才能访问其他页的数据,
// 同时CODE_SEG定义了一个代码段.
// 如果不写这一句, 默认的是将函数存放在分页的flash里面,此时函数为far函数,
// 访问far函数是相当耗费时间的一件事, 中断函数毫无实时性可言.
// 一般只有中断函数时才用__NEAR_SEG, 对于一般函数来说__NEAR_SEG毫无作用



// 接下来是PIT模块的溢出中断响应函数, 
// 首先我们在"MC9S12XEP100.h" 找出PIT中通道0所对应的溢出中断源的地址, 如下:
// #define Vpit0           0xFF7AU
// 将 该地址 和 中断函数名 一起写入 "project.prm"中.
interrupt void PIT_INTER0(void)  

{   
    EnableInterrupts; 
    
    if(1 == PITTF_PTF0)     // PIT模块的0通道发生溢出中断.
    
    {
      
   
      PITTF_PTF0=1;     
      // 先写1清除
     
  switch(single)
  {
    case 1:
      CONT1 = 1;
      CONT2 = 0;
      CONT3 = 0;
      CONT4 = 0;
      DATA=shuma[data1];
      break;

    case 2:
      CONT1 = 0;
      CONT2 = 1;
      CONT3 = 0;
      CONT4 = 0;
      DATA=shuma[data2];
      break;

    case 3:
      CONT1 = 0;
      CONT2 = 0;
      CONT3 = 1;
      CONT4 = 0;
      DATA=shuma[data3];
      break;

    case 4:
      CONT1 = 0;
      CONT2 = 0;
      CONT3 = 0;
      CONT4 = 1;
      DATA=shuma[data4];
      break;
    
    default:
      break;
  }
  
  single +=1;
  if(single == 5) single = 1;

 }
}
#pragma CODE_SEG DEFAULT







/*************************************************************/
/*                           主函数                          */
/*************************************************************/
void main(void)

 {
 
	DisableInterrupts;
	
  INIT_PLL();
  
  Init_PIT();
  
  INIT_port();
  
  INIT_AD();
  
  LEDCPU_dir=1;
  
	EnableInterrupts;
	
	Start_ATD();
	
	ECT_TFLG1_C0F = 1;
  ECT_TC0 = ECT_TCNT + 1250;         //设置输出比较时间为5ms
	
	for(;;)
	
	{
	
	if (ATD0STAT0_SCF)        
	
	    // 一轮序列转换结束,SCF置1
	    //  ATD0STAT0_SCF ------- 转换序列完成标志位
      //      在单次转换模式时, 当转换完成后置位(SCAN=0) 
      //      在连续转换模式时, 当第一次转换完成后置位(SCAN=1)
      
      /*
      // ATD0STAT0 - ATD 0 Status Register 0; 0x000002C6 
          typedef union {
            byte Byte;
            struct {
              byte CC0         :1;                 // Conversion Counter 0 
              byte CC1         :1;                 // Conversion Counter 1 
              byte CC2         :1;                 // Conversion Counter 2 
              byte CC3         :1;                 // Conversion Counter 3 
              byte FIFOR       :1;                 // FIFO Over Run Flag 
              byte ETORF       :1;                 // External Trigger Overrun Flag 
              byte             :1; 
              byte SCF         :1;                 // Sequence Complete Flag 
            } Bits;
            struct {
              byte grpCC   :4;
              byte         :1;
              byte         :1;
              byte         :1;
              byte         :1;
            } MergedBits;
          } ATD0STAT0STR;
          extern volatile ATD0STAT0STR _ATD0STAT0 @(REG_BASE + 0x000002C6UL);
          #define ATD0STAT0                       _ATD0STAT0.Byte
          #define ATD0STAT0_CC0                   _ATD0STAT0.Bits.CC0
          #define ATD0STAT0_CC1                   _ATD0STAT0.Bits.CC1
          #define ATD0STAT0_CC2                   _ATD0STAT0.Bits.CC2
          #define ATD0STAT0_CC3                   _ATD0STAT0.Bits.CC3
          #define ATD0STAT0_FIFOR                 _ATD0STAT0.Bits.FIFOR
          #define ATD0STAT0_ETORF                 _ATD0STAT0.Bits.ETORF
          #define ATD0STAT0_SCF                   _ATD0STAT0.Bits.SCF
          #define ATD0STAT0_CC                    _ATD0STAT0.MergedBits.grpCC
      */
	
	{
	  
        ATD0STAT0_SCF =1;        // 写1清除   
        
       // 读转换结果寄存器
        AD_in0 = ATD0DR1L;
        AD_in1 = ATD0DR0L;
        
        data1 = AD_in0/1000;
        data2 = AD_in0%1000/100;
        data3 = AD_in0%1000%100/10;
        data4 = AD_in0%1000%100%10;
        delay();  
        
        if(AD_in0 > AD_in1)
      
        LEDCPU = 0;
        
      else
      
        LEDCPU = 1;  
           
      }
	}	 
	 
}

导入到开发板,观察到现象:


拨动电位计:


猜你喜欢

转载自blog.csdn.net/weixin_41695564/article/details/81020730