bill0555 发表于 2023-10-22 10:33:33

如何关闭ADC电源?

在使用STC8G1k08中,如要在ADC采集一次后,关闭ADC一段时间再开启,应该如何关闭ADC呢?用了ADC_CONTR &= ~0x80;这个语句,并没有关闭ADC,一直在采样。请教一下:1.如何关闭ADC??
2.关闭ADC后串口输出的是不是都为0000??
本次借用梁工的例程,做测试。

/*------------------------------------------------------------------*/
/* --- STC MCU International Limited -------------------------------*/
/* --- STC 1T Series MCU RC Demo -----------------------------------*/
/* --- Mobile: (86)13922805190 -------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ---------------------*/
/* --- Web: www.GXWMCU.com -----------------------------------------*/
/* --- QQ:800003751 ----------------------------------------------*/
/* If you want to use the program or the program referenced in the*/
/* article, please specify in which data and procedures from STC    */
/*------------------------------------------------------------------*/

#define MAIN_Fosc                11059200L        //定义主时钟

#define        UART_BaudRate1        115200UL       /* 波特率 */


#include        "STC8xxxx.h"


/*************        功能说明        **************

用户请先别修改程序, 直接下载"01-15路ADC转换-BandGap-串口1(P3.7)返回结果-C语言"里的"ADC.hex"测试. 下载时选择主频11.0592MHZ。

测试时, 电脑的串口助手设置115200,8,n,1.

本程序演示16路ADC(P1.0~P1.7, P3.0~P3.6)和bandgap查询采样,通过串口1(P3.7)发送给上位机,波特率115200,8,n,1.

0~7通道对应P1.0~P1.7, 8~14通道对应P3.0~P3.6, 15通道为内部1.19V基准电压做输入的ADC值.

初始化时先把要ADC转换的引脚设置为高阻输入.

ADC模块是一个硬件模块, 由ADC时钟驱动, 一旦触发ADC转换, 硬件会在ADC时钟驱动下自动完成.
CLK为ADC时钟, 是系统时钟的SysClk/2/(n+1)分频, ADC转换由下列操作完成:
通道选择时间   1或2个CLK (默认1)
通道选择保持时间 1~4个CLK (默认2)
模拟信号采样时间 1~32个CLK (默认11)
ADC转换时间      10个CLK(固定).


******************************************/



/*************        本地常量声明        **************/
#define ADC_START        (1<<6)        /* 自动清0 */
#define ADC_FLAG        (1<<5)        /* 软件清0 */

#define        ADC_SPEED        1                /* 0~15, ADC时钟 = SYSclk/2/(n+1) */
#define        RES_FMT                (1<<5)        /* ADC结果格式 0: 左对齐, ADC_RES: D9 D8 D7 D6 D5 D4 D3 D2, ADC_RESL: D1 D0 000000 */
                                                        /*             1: 右对齐, ADC_RES: 000000D9 D8, ADC_RESL: D7 D6 D5 D4 D3 D2 D1 D0 */

#define CSSETUP                (0<<7)        /* 0~1,ADC通道选择时间      0: 1个ADC时钟, 1: 2个ADC时钟,默认0(默认1个ADC时钟) */
#define CSHOLD                (1<<5)        /* 0~3,ADC通道选择保持时间(n+1)个ADC时钟, 默认1(默认2个ADC时钟)                */
#define SMPDUTY                20                /* 10~31, ADC模拟信号采样时间(n+1)个ADC时钟, 默认10(默认11个ADC时钟)                                */
                                                        /* ADC转换时间: 10位ADC固定为10个ADC时钟, 12位ADC固定为12个ADC时钟.                                 */


/*************        本地变量声明        **************/

bit        B_TX1_Busy;        // 发送忙标志

/*************        本地函数声明        **************/
u16                Get_ADC10bitResult(u8 channel);
void        delay_ms(u8 ms);
void        UART1_config(void);
void         Uart1_TxByte(u8 dat);
void         PrintString1(u8 *puts);
void        ADC_convert(u8 chn);        //chn=0~7对应P1.0~P1.7, chn=8~14对应P3.0~P3.6, chn=15对应BandGap电压

/**********************************************/
void main(void)
{
        u8        i;

        UART1_config();   //初始化串口
        EA = 1;
        B_TX1_Busy= 0;

        P1n_pure_input(0xff);        //设置要做ADC的IO做高阻输入
//        P3n_pure_input(0x7f);        //设置要做ADC的IO做高阻输入
        ADC_CONTR = 0x80 + 0;        //ADC on + channel
        ADCCFG = RES_FMT + ADC_SPEED;
        P_SW2 |=0x80;        //访问XSFR
        ADCTIM = CSSETUP + CSHOLD + SMPDUTY;

        while (1)
        {
                for(i=0; i<16; i++)
                {
                        delay_ms(120);
                        ADC_convert(i);
                        if(i == 7)
                        {
                                Uart1_TxByte(0x0d);
                                Uart1_TxByte(0x0a);
                        }
                        ADC_CONTR = ~0x80;
                }
                        Uart1_TxByte(0x0d);
                        Uart1_TxByte(0x0a);       
       
        }
}


//========================================================================
// 函数: u16        Get_ADC10bitResult(u8 channel))        //channel = 0~15
// 描述: 查询法读一次ADC结果.
// 参数: channel: 选择要转换的ADC, 0~15.
// 返回: 10位ADC结果.
// 版本: V1.0, 2018-11-28
//========================================================================
u16        Get_ADC10bitResult(u8 channel)        //channel = 0~15
{
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = 0x80 | ADC_START | channel;
        NOP(5);                        //
        while((ADC_CONTR & ADC_FLAG) == 0)        ;        //等待ADC结束
        ADC_CONTR &= ~ADC_FLAG;
        return        ((u16)ADC_RES * 256 + (u16)ADC_RESL);
}

#define                SUM_LENGTH        16        /* 平均值采样次数 最大值16 */

/***********************************
查询方式做一次ADC, chn为通道号, chn=0~7对应P1.0~P1.7, chn=8~14对应P3.0~P3.6, chn=15对应BandGap电压.
***********************************/
void        ADC_convert(u8 chn)
{
        u16        j;
        u8        k;                //平均值滤波时使用

//        Get_ADC10bitResult(chn);                //参数i=0~11,15,查询方式做一次ADC, 切换通道后第一次转换结果丢弃. 避免采样电容的残存电压影响.
//        Get_ADC10bitResult(chn);                //参数i=0~11,15,查询方式做一次ADC, 切换通道后第二次转换结果丢弃. 避免采样电容的残存电压影响.
        for(k=0, j=0; k<SUM_LENGTH; k++)        j += Get_ADC10bitResult(chn);        // 采样累加和   参数0~15,查询方式做一次ADC, 返回值就是结果
        j = j / SUM_LENGTH;                // 求平均

        Uart1_TxByte('A');
        Uart1_TxByte('D');
        Uart1_TxByte('C');
        Uart1_TxByte(chn/10+'0');
        Uart1_TxByte(chn%10+'0');

        Uart1_TxByte('=');                                //发送ADC读数
        Uart1_TxByte(j/1000 + '0');
        Uart1_TxByte(j%1000/100 + '0');
        Uart1_TxByte(j%100/10 + '0');
        Uart1_TxByte(j%10 + '0');
        Uart1_TxByte(' ');
        Uart1_TxByte(' ');
}



//========================================================================
// 函数: voiddelay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
voiddelay_ms(u8 ms)
{
   u16 i;
       do
       {
               i = MAIN_Fosc / 10000;
                while(--i)        ;
   }while(--ms);
}


//========================================================================
// 函数: void        UART1_config(u8 brt)
// 描述: UART1初始化函数。
// 参数: brt: 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
// 返回: none.
// 版本: VER1.0
// 日期: 2016-4-28
// 备注:
//========================================================================
void        UART1_config(void)        //
{
        TR1 = 0;
        AUXR &= ~0x01;                //S1 BRT Use Timer1;
        AUXR |=(1<<6);        //Timer1 set as 1T mode
        TMOD &= ~(1<<6);        //Timer1 set As Timer
        TMOD &= ~0x30;                //Timer1_16bitAutoReload;
        TH1 = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate1) / 256;
        TL1 = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate1) % 256;
        ET1 = 0;        //禁止中断
        TR1= 1;

        SCON = (SCON & 0x3f) | (1<<6);        // 8位数据, 1位起始位, 1位停止位, 无校验
        REN = 1;        //允许接收
//        PS= 1;        //高优先级中断
        ES= 1;        //允许中断
//        P_SW1 = P_SW1 & 0x3f;                                P3n_standard(0x03);        //头文件定义的宏, 切换到 P3.0 P3.1
        P_SW1 = (P_SW1 & 0x3f) | (1<<6);        P3n_standard(0xc0);        //头文件定义的宏, 切换到 P3.6 P3.7
//        P_SW1 = (P_SW1 & 0x3f) | (2<<6);        P1n_standard(0xc0);        //头文件定义的宏, 切换到 P1.6 P1.7 (必须使用内部时钟)

        B_TX1_Busy= 0;
}


//========================================================================
// 函数: void Uart1_TxByte(u8 dat)
// 描述: 串口1发送一个字节函数.
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2016-4-28
// 备注:
//========================================================================
void Uart1_TxByte(u8 dat)
{
        B_TX1_Busy = 1;                //标志发送忙
        SBUF = dat;                        //发一个字节
        while(B_TX1_Busy);        //等待发送完成
}


//========================================================================
// 函数: void UART1_int (void) interrupt UART1_VECTOR
// 描述: 串口1中断函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2016-4-28
// 备注:
//========================================================================
void UART1_int (void) interrupt UART1_VECTOR
{
        if(RI)
        {
                RI = 0;
        }

        if(TI)
        {
                TI = 0;
                B_TX1_Busy = 0;
        }
}


梁工 发表于 2023-10-23 12:17:24

ADC_CONTR = 0x00;   //即可关闭ADC模块,一定可以关闭。
再次打开ADC电源,要至少延时1ms再启动ADC转换,模拟电路需要一点时间稳定。
页: [1]
查看完整版本: 如何关闭ADC电源?