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); //打印输出 

}

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你写一个使用STC89C52的ADC模数转换的C语言程序,如下所示: ``` #include <reg52.h> sbit ADC_CS = P3^7; // ADC片选 sbit ADC_CLK = P3^6; // ADC时钟 sbit ADC_DIN = P3^5; // ADC数据输入 sbit ADC_DOUT = P3^4; // ADC数据输出 // 初始化ADC模块 void initADC() { ADC_CS = 1; ADC_CLK = 0; ADC_DIN = 0; ADC_DOUT = 1; } // 读取指定通道的AD值 unsigned char readADC(unsigned char channel) { unsigned char i; unsigned char dat1 = 0, dat2 = 0; ADC_CS = 0; ADC_CLK = 0; ADC_DIN = 1; ADC_CLK = 1; ADC_DIN = 1; ADC_CLK = 0; // 发送起始位 ADC_DIN = 0; ADC_CLK = 1; ADC_DIN = 1; ADC_CLK = 0; // 发送单片机高4位地址和转换通道 for (i = 0; i < 4; i++) { ADC_DIN = (channel & 0x08) >> 3; ADC_CLK = 1; ADC_DIN = 1; ADC_CLK = 0; channel <<= 1; } // 接收AD值高8位 for (i = 0; i < 8; i++) { ADC_CLK = 1; dat1 <<= 1; dat1 |= ADC_DOUT; ADC_CLK = 0; } // 接收AD值低2位和校验位 for (i = 0; i < 3; i++) { ADC_CLK = 1; dat2 <<= 1; dat2 |= ADC_DOUT; ADC_CLK = 0; } ADC_CS = 1; return dat1; } void main() { unsigned char AD_value; initADC(); // 初始化ADC模块 while (1) { AD_value = readADC(0); // 读取ADC通道0的值 // 在此进行需要的操作 } } ``` 这个程序会初始化ADC模块,然后通过指定通道读取AD值,并在while循环中进行需要的操作。你可以在while循环中加入你的操作,例如将AD值输出到LCD显示屏上,或者通过蓝牙模块发送到手机上。当然,需要根据实际情况修改程序。希望这个程序对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值