STC8H系列—11.ADC模数转换控制教程

一、概述:

   STC8H系列自带一组ADC转换器,传统的c51单片机需外挂AD芯片实现该功能,内置ADC不仅转换速度快,而且精度很高(12位),Stc8h系统最高可以达到每秒钟80万次的转换速度,相对来说已经是高效转换了。数据的转换结果有两种方式,一种是左对齐,另一种是右对齐,通过对内部寄存器的设置可以达到目的。

Stc8h系列单片机虽然内部只提供了一组ADC转换器,但同样可以实现多ADC转换功能,由于其内置了15个通道,理论上来说可能采用分时采集的方式,达到多ADC转换功能,同时内部提供1.19V基准电压,+VREF脚接MCUVCC,通过反推公式实现电源电压采集功能。

ADC的采集转换结果有两种方式可以实现,一种是通过查询标志位,另一种是中断方式,以下的实例,采集P10引脚的模拟电压值,当按下k1时采用查询方式通过串口2发送至PC接收,当按下K2时采用中断方式同样通中串口2将采集结果发送至PC接收。

二、知识链接:

1、ADC控制寄存器(ADC_CONTR):

其中ADC_POWER位置1时,使能ADC转换器电源。

ADC_START置1时,开始进入ADC转换

ADC_FLAG为ADC转换标志位,当ADC转换完成,硬件自动置1,必须软件方式清零后才能下一次采集。

ADC_CHS:采集通道转换,这里选择默认值0,为P10,而且P10必须为高阻状态。

2、ADC配置寄存器(ADCCFG):

其中RESFMT位,置1时,转换结果右对齐,置0时,转换结果左对齐,ADC_RES和ADC_RESL两个结果寄存器,左对齐则低4位置0,右对齐则高4位置0。下面的实例采用右对齐。

以上为转换时序图,读时序小结如下:

  1. 使能ADC_POWER=1。
  2. 开始转换ADC_START=1。
  3. 当ADC_FLAG=1时读数据,然后清零,准备下一次。

三、实验平台搭建:

   1、MCU:STC-打狗棒系列核心实验板 V2.3

   2、实验板平台:德飞莱LY-51s

   3、硬件连接表:

     电位器------>P10    模拟电压0-5V。

      K1------>P20    查询方式采集ADC

      K2------>P21    中断方式采集ADC

      串口2----->PC   输出采集值    

四、测试源代码:

#include <STC8H.h>

#include "intrins.h"

#include <stdio.h>

sbit Led1=P0^0;

sbit Led2=P0^1;

sbit Led3=P0^2;

sbit Led4=P0^3;

int Adc_value=0;

void Delay1ms(unsigned char x);//当主时钟频率为12M,1ms延时为基准

void init_IO();//初始化IO

void init_Uart2();//串口2初始化

void Uart2Send(char dat);//发送单字符

void init_ADC();//初始化ADC

int ADC_Start();//开始ADC转换

void ADC_StartIsr();//中断方式转换

void main()

{

       int x=0;

     P_SW2 |= 0x80;  //扩展寄存器XFR访问使能 

      init_IO();

      init_Uart2();   

     printf("STC8H ADC Test!");

     init_ADC();

      //ADC_Start();

   while(1)

    {

     if(P20==0)//K0触发ADC

       {

          Delay1ms(20);

         if(P20==0)

         {

            x=0;

            x=ADC_Start();//开始转换

           printf("ADC value=%d",x);

            while(!P20);

         }

       }

       

        if(P21==0)//K1触发ADC中断

       {

          Delay1ms(20);

         if(P21==0)

         {

           ADC_StartIsr();

            while(!P21);

         }

       }

    

    }

}

void init_IO()

{

   RSTCFG=0x50;  //开启RST键进入ISP模式

   P0M1 = 0x00;   P0M0 = 0x00;   //设置P0口为准双向口

   P1M1 = 0x00;   P1M0 = 0x00;   //设置P0口为准双向口

   P2M1 = 0x00;   P2M0 = 0x00;   //设置P1口为准双向口

   P3M1 = 0x00;   P3M0 = 0x00;   //设置P3口为准双向口

   P4M1 = 0x00;   P4M0 = 0x00;   //设置P4口为准双向口

   P5M1 = 0x00;   P5M0 = 0x00;   //设置P5口为准双向口

     

}

void init_ADC()//初始化ADC

{

   P1M1=0x01;P1M0=00;//配置P10为高阻模式

    ADC_CONTR=0x00;

   //ADCTIM=0x3f;  

    ADCCFG=0x20;//设置12位结果为右对齐

    ADC_RES=0x00;

    ADC_RESL=0x00;

   ADC_CONTR|=0x80;//打开ADC_Power

  

    EA=1;//开中总断

    EADC=1;//开ADC中断

}

int ADC_Start()

{

  int x=0;   

   ADC_CONTR|=0x40;//开启ADC_START 

   _nop_();

   _nop_();

   _nop_();

   while(ADC_CONTR&0x20==0);

   ADC_CONTR&=~0x20;//ADCFLAG=0;

   x=ADC_RES*256;   //高位值

   x+=ADC_RESL;  //低位值   

  return x;  

}

void ADC_StartIsr()

{

  ADC_CONTR&=~0x20;//ADCFLAG=0;

   ADC_CONTR|=0x40;//开启ADC_START

}

void init_Uart2()//波特率11.0592

{

    S2CON=0x10;   //打开允许接收

     T2L = 0xE8;    //设置定时初始值

     T2H = 0xFF;    //设置定时初始值

     AUXR|=0x04;   //开启T2定时器1T工作模式

     AUXR|=0x10;   //开启T2定时器T2R=1  

     IE2|=0x01;//开启ES=1

      P_SW2|=0x01;//串口2脚位切换,将串口2脚位切换到P46、P47,默认P10、P11    

}

void Uart2Send(char dat)//u2发送单字符

{

    S2BUF=dat;

    while((S2CON & 2) == 0);

    S2CON &= ~2;    //Clear Tx flag

}

char putchar(char c)//重写printf

{

   Uart2Send(c);

   return c;

}

void Delay1ms(unsigned char x)    //@12.000MHz

{

   unsigned char i, j;

  

   while(x--)

   {

      i = 16;

     j = 147;

      do

      {

        while (--j);

      } while (--i);

   } 

}

void ADC_isr() interrupt 5 //中断方式

{

  int Adc_value=0;

   Led1=~Led1;

   ADC_CONTR&=~0x20;//ADCFLAG=0;

   Adc_value=ADC_RES*256; //高位值

   Adc_value+=ADC_RESL;  //低位值

   ADC_RES=0x00;

   ADC_RESL=0x00;

  printf("ADC ISR value=%d",Adc_value); //打印输出 

}

猜你喜欢

转载自blog.csdn.net/qq_21082985/article/details/132147173
今日推荐