飞思卡尔XS128八位数模转换模块的实验与心得体会
数模转换的编程流程:
① 锁相环时钟设置,这一步不细讲,后面会有文章来专门解释锁相环的设置,将总线时钟频率升到32MHz
② ATDCTL2(控制寄存器2)设置,这个寄存器主要针对标志快速清除,触发方式与中断使能,这里设置为快速清零,中断禁能
③ ATDCTL1_SRES选用8位
④ ATDCTL3选择对齐方式与序列转换长度
⑤ ATDCTL4选择采样时间与采样时钟分频系数
⑥ ATDCTL5选择通道转换,注意,看好电路图,你是从哪个通道采来的信号,不单单要从软件寄存器上去选择,还要符合硬件原理图。两个电位计在开发板上的连接原理图是接着AD00和AD01。
⑦ ATDSTAT0_SCF状态结束标志位判断
⑧ 按照结果寄存器的保存位置输出到变量里观察
代码标注
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#define BUS_CLOCK 32000000 //总线频率,改变总线频率直接在此处修改
#define OSC_CLOCK 16000000 //晶振频率
#define LEDCPU PORTK_PK4
#define LEDCPU_dir DDRK_DDRK4
unsigned char AD_in1,AD_in0,Lilun_AD1,Lilun_AD0;
/*************************************************************/
/* 初始化锁相环 */
/*************************************************************/
void INIT_PLL(void)
{
CLKSEL &= 0x7f; //设置OSCCLK作为系统时钟
PLLCTL &= 0x8F; //禁止锁相环
//PLLCLK=2×OSCCLK×(SYNDIV+1)/(REFDIV+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; //使能锁相环 PLLCLOCK CONTROL
asm NOP;
asm NOP;
while(!(CRGFLG&0x08)); //PLLCLK锁定
CLKSEL |= 0x80; //设置PLLCLK为系统时钟
}
/*************************************************************/
/* 初始化AD模块 */
/*************************************************************/
void INIT_AD(void)
{
ATD0CTL2 = 0x40; //Bit7:只读不用管
//Bit6:标志快速清除,不用读状态寄存器直接读了结果寄存器就清除
// 如果不是快速清除的话需要读完所有才能清除
//Bit5:停止模式时,转换被终止
//Bit4:有效边沿触发模式
//Bit3:低电平或者下降沿触发
//Bit2:禁止外部触发模式
//Bit1:ASCIE ATD序列结束中断禁能
//Bit0:禁能比较中断
//启动A/D模块,快速清零,禁止中断 0100 0000
ATD0CTL1_SRES=0; //选用8位模数转换 ERES[1:0]是精度选择
ATD0CTL3 = 0x88; //每次只转换一个通道 1000 1000
//Bit7:DJM 1为右对齐也就是说结果寄存器的数据是怎么向映射到IP数据总线上
//对于八位分辨率右对齐,结果寄存器映射到数据总线的0-7位,7是高位
//Bit6 5 4 3 S8C/S4C/S2C/S1C 0001 每个序列转换长度(转换了多少次)为1,分配到ATDDR0
//Bit2:FIFO位 转换序列的转换结果映射到转换结果寄存器中
//Bit1 0:背景调试冻结使能,00忽略背景信号
ATD0CTL4 = 0x07; //Bit15 14 13:SMP[2:0]表示采样时间,000为采样时间的ATD时钟周期数为4个
//这里需要注意的是,采样周期有三个阶段,第一第二个阶段是不能控制的,第三个转换时长可以控制
//也就是说,一共会消耗第一阶段2+第二阶段4+第三阶段自己选择的时长来完成采样
//Bit[13:8]:PRS[4:0]时钟预分频器,构成时钟的预分频系数PRS
//计算式为f=fBUS/(2*(PRS+1)),注意范围500kHz-2MHz
//总线时钟32MHz f=32/(2*(7+1))=2MHz
//AD模块时钟频率为2MHz 0000 0111
}
/*************************************************************/
/* 起动AD转换 */
/*************************************************************/
unsigned char AD_capture(unsigned char chanel)
{
unsigned char AD_data;
switch(chanel)
{
case 0:
ATD0CTL5 = 0x00; //转换AD00 Bit6:SC 禁止特殊通道转换
//Bit5:SCAN 单次执行转换序列模式,不连续
//Bit4:MULT 多通道采集 0是单通道指定采集
//Bit[3:0]:CD CC CB CA选择模拟输入通道 AD0
/***********************************************************/
/*例子:MULT+CC/CB/CA+S8C/S4C/S2C/S1C */
/*0+0/1/0+0/0/1/1单通道模式AD2通道采集转化3次放到ATDDR[0:2]*/
/*1+0/1/0+0/0/1/1多通道模式AD2/AD3/AD4转化放到紸TDDR[0:2] */
/***********************************************************/
//这里就是单通道模式AD0转化一次放到ATDDR0中
while(!ATD0STAT0_SCF); //SCF为状态寄存器结束标志
AD_data = ATD0DR0L; //八位右对齐找ATDDR0L
break;
case 1:
ATD0CTL5 = 0x01; //转换AD01
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 2:
ATD0CTL5 = 0x02; //转换AD02
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 3:
ATD0CTL5 = 0x03; //转换AD03
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 4:
ATD0CTL5 = 0x04; //转换AD04
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 5:
ATD0CTL5 = 0x05; //转换AD05
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 6:
ATD0CTL5 = 0x06; //转换AD06
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 7:
ATD0CTL5 = 0x07; //转换AD07
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 8:
ATD0CTL5 = 0x08; //转换AD08
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 9:
ATD0CTL5 = 0x09; //转换AD09
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 10:
ATD0CTL5 = 0x0a; //转换AD10
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 11:
ATD0CTL5 = 0x0b; //转换AD11
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 12:
ATD0CTL5 = 0x0c; //转换AD12
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 13:
ATD0CTL5 = 0x0d; //转换AD13
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 14:
ATD0CTL5 = 0x0e; //转换AD14
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
case 15:
ATD0CTL5 = 0x0f; //转换AD15
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
break;
}
return(AD_data);
}
/*************************************************************/
/* 主函数 */
/*************************************************************/
void main(void) {
DisableInterrupts;
INIT_PLL();
INIT_AD();
LEDCPU_dir=1;
EnableInterrupts;
for(;;)
{
AD_in1= AD_capture(1);
AD_in0=AD_capture(0);
// Lilun_AD1=AD_in1*5/255;
// Lilun_AD0=AD_in0*5/255; (数据丢失,这样没有任何意义)
if(AD_in1 > AD_in0)
LEDCPU = 0;
else
LEDCPU = 1;
}
}
注:代码来源飞翔单片机开发板演示程序,本人小白,欢迎指出错误