嵌入式编程学习笔记(一)
本文利用 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 DDRPunsigned 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; 0x000002C1struct {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; //设置输出比较时间为5msfor(;;){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;elseLEDCPU = 1; }} }
导入到开发板,观察到现象:
拨动电位计:
嵌入式编程学习笔记(一)相关推荐
- Lua 编程学习笔记
文章目录 Lua 编程学习笔记 一.环境安装 二.Lua 基本语法 1. 注释 2. 标识符 3. 变量 4. 数据类型 5. Lua 运算符 三.循环与流程控制 1. 循环 2. 流程控制 四.函数 ...
- 嵌入式入门学习笔记1:资料收集
嵌入式入门学习笔记1:资料收集 一:网上购买的500G资料 资料地址:https://pan.baidu.com/s/1siwOPjtcRCPZNikN4-Z2tw 密码:lhnr 二.嵌入式涉及的知 ...
- 嵌入式linux学习笔记--TCP通讯整理
嵌入式linux学习笔记–TCP通讯整理 之前的项目中使用到了比较多的tcp 通讯相关的知识,一直也没有进行整理,今天准备拿出时间好好的整理一下TCP通讯的整个过程.预计会整理linux和window ...
- 多线程编程学习笔记——async和await(三)
接上文 多线程编程学习笔记--async和await(一) 接上文 多线程编程学习笔记--async和await(二) 五. 处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...
- 多线程编程学习笔记——任务并行库(二)
接上文 多线程编程学习笔记--任务并行库(一) 三. 组合任务 本示例是学习如何设置相互依赖的任务.我们学习如何创建一个任务的子任务,这个子任务必须在父任务执行结束之后,再执行. 1,示例代码如下 ...
- 多线程编程学习笔记——任务并行库(三)
接上文 多线程编程学习笔记--任务并行库(一) 接上文 多线程编程学习笔记--任务并行库(二) 六. 实现取消选项 本示例学习如何实现基于Task的异步操作进行取消流程,以及在任务真正运行前如何知 ...
- Linux与C++11多线程编程(学习笔记)
多线程编程与资源同步 在Windows下,主线程退出后,子线程也会被关闭; 在Linux下,主线程退出后,系统不会关闭子线程,这样就产生了僵尸进程 3.2.1创建线程 Linux 线程的创建 #inc ...
- Cocoa编程学习笔记一
Cocoa编程学习笔记一 一.Cocoa的起源 Mac OS X的窗口服务器与UNIX中的X窗口服务器具有相同的功能:从用户那里接受事件,并将时间转发给应用程序,将应用程序发过来的数据显示在屏幕上.N ...
- 多线程编程学习笔记——使用并发集合(三)
接上文 多线程编程学习笔记--使用并发集合(一) 接上文 多线程编程学习笔记--使用并发集合(二) 四. 使用ConcurrentBag创建一个可扩展的爬虫 本示例在多个独立的即可生产任务又可消费 ...
最新文章
- Android扫描二维码 实现 登录网页
- YaaS,we can!
- 520 页机器学习笔记!图文并茂可能更适合你
- 从GB到GBDT到XGBoost
- 云计算机室局域网时通时断,为什么网上邻居时通时断?
- JBPM与设计模式之职责链模式
- SGU 222 Little Rooks
- 客户永远是对的---我的理解:做事不要抱怨,别为失败找借口。
- tableView选中行的调用顺序/ 取消选中Cell
- 【Ansible 文档】【译文】Ad-Hoc 命令介绍
- AV系统类毕业论文文献有哪些?
- 按键精灵定位坐标循环_按键精灵的控制命令居然恐怖到了这种程度
- android支付宝运动修改器,支付宝运动修改器
- SweepProfile for 3dMax石膏线生成插件使用教程
- 全民居家都带不动的AI健身,到底是不是伪命题?
- 知识点滴 - 关于苹果认证MFI
- Photoshop7.0序列号
- 如何编辑eps格式的图片
- 分类模型常用的评价指标
- scrapy 爬取指定贴吧