本文利用 MC9S12XEP100 单片机来学习A/D采集功能。
首先开发板上有两个电位计作为A/D采集的输入信号,拉下图所示:
将采集到的信号作比较,利用判断结果来控制开发板上的二极管的开和灭,二极管的电路连接如下:
然后将AD0的转换后的结果采用扫描的方式输出在数码管上,数码管的电路原理图如下:
数码管的每个阳极连接一个限流电阻,8个阳极和单片机的PP0~PP7引脚相连。数码管的四个阴极采用4个三极管作为开关。三极管的基极经过电阻之后与单片机的PK3~PK0引脚相连。按照这个电路,扫描的具体方法是:P口输出第一位数码的码段, K口控制第一位导通而其他三位不导通,延时5ms后,P口输出第二位数码的码段, K口控制第二位导通而其他三位不导通,如此直到扫描完第四位后,继续扫描第一位。
在code warrior中程序源代码如下所示:
#include /* 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;
}
}
}
导入到开发板,观察到现象:
拨动电位计: