freescale MC9S12G128 ADC

Features:

• 8-, 10-bit resolution.
• Automatic return to low power after conversion sequence
• Automatic compare with interrupt for higher than or less/equal than programmable value
• Programmable sample time.
• Left/right justified result data.
• External trigger control.
• Sequence complete interrupt.
• Analog input multiplexer for 8 analog input channels.
• Special conversions for VRH, VRL, (VRL+VRH)/2.
• 1-to-12 conversion sequence lengths.
• Continuous conversion mode.
• Multiple channel scans.
• Configurable external trigger functionality on any AD channel or any of four additional trigger
inputs. The four additional trigger inputs can be chip external or internal. Refer to device
specification for availability and connectivity.
• Configurable location for channel wrap around (when converting multiple channels in a sequence).

Conversion Modes:

Conversion Modes There is software programmable selection between performing single or continuous conversion on a single channel or multiple channels.

MCU Operating Modes:

• Stop Mode
Entering Stop Mode aborts any conversion sequence in progress and if a sequence was aborted
restarts it after exiting stop mode. This has the same effect/consequences as starting a conversion
sequence with write to ATDCTL5. So after exiting from stop mode with a previously aborted
sequence all flags are cleared etc.
• Wait Mode
ADC10B12C behaves same in Run and Wait Mode. For reduced power consumption continuous
conversions should be aborted before entering Wait mode.
• Freeze Mode
In Freeze Mode the ADC10B12C will either continue or finish or stop converting according to the
FRZ1 and FRZ0 bits. This is useful for debugging and emulation.

Block Diagram:

在这里插入图片描述

信号描述:

ADC输入:
ANx(x=11,10,9,8,7,6,5,4,3,2,1,0)一共12路ADC IN通路;

触发控制:
ETRIG3,ETRIG2,ETRIG1,ETRIG0;

参考电压:
VRH(high reference voltage)高压参考;
VRL(low reference voltage)低压参考;

供电接口:
VDDA, VSSA 模拟电源,模拟地;

寄存器:

寄存器列表:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ATDCTL0:

在这里插入图片描述
在这里插入图片描述

ATDCTL1:

在这里插入图片描述
分辨率设置:
在这里插入图片描述
在这里插入图片描述

ATDCTL2:

在这里插入图片描述
在这里插入图片描述

ATDCTL3:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ATDCTL4:

在这里插入图片描述

ATDCTL5:

在这里插入图片描述
在这里插入图片描述

ATDSTAT0:

在这里插入图片描述
在这里插入图片描述

ATDCMPE:

在这里插入图片描述

ATDSTAT2:

在这里插入图片描述

ATDDIEN:

在这里插入图片描述

ATDCMPHT:

在这里插入图片描述

ATDDRn:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

PRR0:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

PRR1:

DDR1AD0
在这里插入图片描述

演示代码:

单次转换模式:

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

#include <stdio.h>

#define D_BUSCLK_FREQ   (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE  (9600)     // 串口波特率  


unsigned char txbuff[256]={
    
    0};   // 发送缓存
unsigned char rxbuff[256]={
    
    0};   // 接收缓存

unsigned char *send;

unsigned int AD_in1,AD_in0;

/*************************************************************/
/*                初始化AD通道为数字输入通道                 */
/*************************************************************/
void adc_init(void) 
{
    
    
  
  /* 1.TODO:设置AIN引脚为输入, 设置有误会影响到测试精度和稳定性 */
  //DDR1AD = 0x00;      //设置AD8~AD16为输入
  DDR1AD_DDR1AD0 = 0; //设置AD0为输入
  DDR1AD_DDR1AD1 = 0; //设置AD1为输入
  
  //DDR0AD=0x00;        //设置AD8~AD15为输入
  DDR0AD_DDR0AD0 = 0; //设置AD8为输入
  DDR0AD_DDR0AD1 = 0; //设置AD9为输入

  
  /* 2.TODO:使能ATD数字输入通道 */
  ATDDIEN= 0x30;   // ATDDIEN[11~0] ATD Digital Input Enable, 使能AD00和AD01数字输入通道
    
  #if 1 
  // 按位操作寄存器
  ATDCTL1_SRES = 0x01; // 采样分辨率 0x00:8bit, 0x01:10bit
  
  ATDCTL2_AFFC = 1;     // 0:写1到CCF[n]清空指定通道转换完成标记, 1:快速清空所有通道转换完成标记
  ATDCTL2_ASCIE   = 0;  // ATD 数列完成中断 0:关闭, 1:使能
  ATDCTL2_ACMPIE  = 0;  // ATD 比较完成中断 0:关闭, 1:使能
  
  
  // 外部触发模式配置,这里不使能
  ATDCTL2_ETRIGE = 0;  // 0:关闭外部触发模式, 1:使能外部触发模式
  //LE:P 0:0下降沿,0:1上升沿,1:0:低电平, 1:1高电平
  ATDCTL2_ETRIGLE = 0; 
  ATDCTL2_ETRIGP = 0;
    
  ATDCTL3_DJM = 1;   // 通常设置为1;  0:left justified, 1:right justified.
  ATDCTL3_S8C = 0;  
  ATDCTL3_S4C = 0;
  ATDCTL3_S2C = 0;
  ATDCTL3_S1C = 1;
  ATDCTL3_FIFO = 0;
  ATDCTL3_FRZ  = 0x0; // 0:连续转换, 1:保留,2:完成当前转换冻结,3:立即冻结
  
  
  //ATDCTL4 采样时间选择,ATD时钟perscaler=fBUS/(2*(PRS+1))
  ATDCTL4_SMP = 0; //采样时间选择0~7  [4,6,8,10,12,16,20,24 ATD clock cycles]
  ATDCTL4_PRS = 3; //  (fBUS)16000000/(2*(3+1)) = 16000000/8 = 2MHz 
  
  #else
  // 字节操作寄存器
  ATDCTL2 = 0x40;    //启动A/D模块,快速清零,禁止中断
  ATDCTL1_SRES=1;    //选用10位模数转换
  ATDCTL3 = 0x88;    //每次只转换一个通道
  ATDCTL4 = 0x03;    //AD模块时钟频率为2MHz
  #endif
  
}


/*************************************************************/
/*                        起动AD转换                         */
/*************************************************************/
unsigned int AD_capture(unsigned char chanel) 
{
    
    
 unsigned int AD_data;
 switch(chanel)
 {
    
     
  case 0:
    ATDCTL5 = 0x00;    //转换AD00
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 1:
    ATDCTL5 = 0x01;    //转换AD01
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;
  
  case 2:
    ATDCTL5 = 0x02;    //转换AD02
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;
 
  case 3:
    ATDCTL5 = 0x03;    //转换AD03
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 4:
    ATDCTL5 = 0x04;    //转换AD04
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 5:
    ATDCTL5 = 0x05;    //转换AD05
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 6:
    ATDCTL5 = 0x06;    //转换AD06
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 7:
    ATDCTL5 = 0x07;    //转换AD07
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 8:
    ATDCTL5 = 0x08;    //转换AD08
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 9:
    ATDCTL5 = 0x09;    //转换AD09
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 10:
    ATDCTL5 = 0x0a;    //转换AD10
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 11:
    ATDCTL5 = 0x0b;    //转换AD11
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 12:
    ATDCTL5 = 0x0c;    //转换AD12
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 13:
    ATDCTL5 = 0x0d;    //转换AD13
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 14:
    ATDCTL5 = 0x0e;    //转换AD14
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;

  case 15:
    ATDCTL5 = 0x0f;    //转换AD15
    while(!ATDSTAT0_SCF);
    AD_data = ATDDR0;
    break;
  
 }
 return(AD_data);
}


/*************************************************************/
/*                       串口发送函数                        */
/*************************************************************/
void csi_send(unsigned char data) 
{
    
    
  while(!SCI0SR1_TDRE);         //等待发送数据寄存器(缓冲器)为空
  SCI0DRL = data;
}

/*************************************************************/
/*                       串口接收函数                        */
/*************************************************************/
unsigned char csi_receive(void) 
{
    
    
  while(!SCI0SR1_RDRF);          //等待发送数据寄存器满
  return(SCI0DRL);
}

/*************************************************************/
/**   定义了这个两个接口就可以使用printf函数格式化输出      **/
/**   TERMIO_PutChar                                        **/
/**   TERMIO_GetChar                                        **/
/*************************************************************/
void TERMIO_PutChar(char ch){
    
    
  csi_send((unsigned char)ch);
}

char TERMIO_GetChar(void){
    
    
  return (char)csi_receive();
}


void sci_init(void) {
    
    
  SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE;    // 设置SCI0波特率 busCLK/16/BAUDRATE;
  SCI0CR1 = 0x00;    //设置SCI0为正常模式,八位数据位,无奇偶校验  7:LOOPS 6:SCISWAI 5:RSRC 4:M     3:WAKE 2:ILT  1:PE   0:PT
  SCI0CR2 = 0x0C;    //允许收发数据,允许收发中断功能              7:TIE,  6:TCIE,   5:RIE, 4:ILIE, 3:TE,  2:RE,  1:RWU, 0:SBK
}


/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
    
    
  CPMUPROT = 0x26;              //保护时钟配置寄存器
  
  CPMUCLKS_PSTP = 0;            //禁用PLL
  CPMUCLKS_PLLSEL = 1;          //选择PLL作为系统时钟源
  
  CPMUOSC_OSCE = 1;             //外部晶振使能
  while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能

  // BUSCLK = (PLLCLK / 2)   总线频率=(锁相环频率/2)
  
  
  #if 1
  //fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1) 
  CPMUSYNR = 0x07;                                                  
  //CPMUREFDIV = 0x0F; // PLLCLK:16M  BUSCLK:8M   
  CPMUREFDIV = 0x07; // PLLCLK:32M  BUSCLK:16M   
  //CPMUREFDIV = 0x03; // PLLCLK:64M  BUSCLK:32M        
  #endif
  
  #if 0
  //fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
  //CPMUSYNR = 0x45; // PLLCLK:48M     BUSCLK:24M
  //CPMUSYNR = 0x44; // PLLCLK:40M     BUSCLK:20M
  //CPMUSYNR = 0x43; // PLLCLK:32M     BUSCLK:16M
  //CPMUSYNR = 0x42; // PLLCLK:24M     BUSCLK:12M
  CPMUSYNR = 0x01; // PLLCLK:16M    BUSCLK:8M
  CPMUREFDIV = 0x81;//REFDIV基准分频器配置
  #endif
    
  CPMUPOSTDIV = 0x00;           // PLL CLOCK = VCO CLOCK / (POSTDIV + 1) 
                              
  _asm(nop);
  _asm(nop);
  
  CPMUPLL=0x10;               //锁相环调频启用,用以减少噪音
    
  while(CPMUFLG_LOCK == 0);	  //等待PLL稳定
  
  	  
  CPMUPROT = 0x00;            //关闭保护时钟
  CPMUCLKS_PLLSEL = 1;        //使能PLL
}


/**************************************************************/
/** AD比较中断程序 **/
/**************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt VectorNumber_Vatdcompare void atdcmp_irq(void)
{
    
    

}
#pragma CODE_SEG DEFAULT


/**************************************************************/
/** AD转换中断程序 **/
/**************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt VectorNumber_Vatd void atd_irq(void)
{
    
    
  
}
#pragma CODE_SEG DEFAULT


unsigned int get_adcvalue(unsigned char ch) {
    
    
  unsigned int adcsum=0;
  int i=0;
  for (i=0; i<50; i++){
    
    
    adcsum += AD_capture(ch);
  }
  
  return (unsigned int)adcsum/i;
  
}
  

void main(void) {
    
    
  /* put your own code here */
  
  DisableInterrupts;
  pll_init();
  sci_init();
  adc_init();
	EnableInterrupts;

  (void)printf("************** ADC ****************\n");
 
  for(;;) {
    
    
    AD_in0 = AD_capture(0);
    AD_in1 = AD_capture(1);
    
    //AD_in0 = get_adcvalue(8);
    //AD_in1 = get_adcvalue(9);
    (void)printf("AD_in0:%d, AD_in1:%d\n", AD_in0, AD_in1);
   
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

扫描转换模式:

外部触发模式:

猜你喜欢

转载自blog.csdn.net/u013420428/article/details/112981313
ADC