STM8单片机ADC连续采样模式

701 阅读3分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

 STM8S003单片机内部ADC为12位,A/D转换的各个通道可以执行单次和连续的转换模式。

 单次转换模式的意思就是,ADC每次转换一次数据后,就会停止转换,如果还需要继续转换的话,就需要手动开启第二次转换功能。

 连续转换模式的意思就是每次转换结束后,系统会自动开启第二次转换,不需要手动设置第二次转换的开启,也就是说连续转换模式只需要开启一次。

ADC框图如下:

image.png

ADC连续模式转换时序图如下:

image.png

通过时序图可以看出,在第2次转换完成后,第一次采样的结果才会输出,也就是结果输出比采样滞后了一个周期。

下面用代码来实现ADC的连续转换模式:

#include "adc.h"
#include "main.h"

u16  DATAH = 0;                          //ADC转换值高8位
u16  DATAL = 0;                          //ADC转换值低8位
_Bool ADC_flag = 0;                     //ADC转换成功标志

//AD通道引脚初始化
void ADC_GPIO_Init( void )
{
    PD_DDR &= ~( 1 << 3 );              //PD3 设置为输入      电流
    PD_CR1 &= ~( 1 << 3 );              //PD3 设置为悬空输入
}
//ch 为单片机的对应管脚
void ADC_CH_Init( u8 ch )
{
    char l = 0;
    ADC_CR1  = 0x00;                    //fADC = fMASTER/2, 8Mhz  单次转换,禁止转换
    ADC_CR1 |= ( 1 << 1 );              //开启连续转换模式
    ADC_CSR  = ch + 1;                  //控制状态寄存器 选择要 AD输入通道  如:PD2(AIN3)
    ADC_CR2  = 0x00;                    //默认左对齐 读数据时先读高在读低
    ADC_TDRL = ( 1 << ( ch + 1 ) );     //禁止相应通道 施密特触发功能 1左移ch+1位
    ADC_CR1 |= 0x01;                    //使能ADC并开始转换
    //ADC_CSR |= 0x20;                    //EOCIE 使能转换结束中断  EOC中断使能
    for( l = 0; l < 100; l++ );         //延时,保证ADC模块的上电完成 至少7us
    ADC_CR1 = ADC_CR1 | 0x01;           //再次将CR1寄存器的最低位置1 使能ADC 并开始转换
}

//采集PD3电压值
u16 ReadVol_CH3( void )
{
    u16 voltage = 0;
    if( ADC_CSR & 0x80 )
    {
        DATAH = ADC_DRH;                    // 读出ADC结果的高8位
        DATAL = ADC_DRL;                    // 读出ADC结果的低8位
        voltage = ( DATAH << 2 ) + DATAL ; //得到十位精度的数据  0--1024
        ADC_CSR &= 0x7F;
    };
    return voltage;
}

连续转换模式,只需要开启一次转换,然后一直等待数据转换结束,读取数据就行。由于连续转换模转换速度和快,使用中断的话,系统中断太频繁,影响其他代码执行。所以可以不需要中断去读取数据,需要数据的时候直接判断转换结束标志位去读取数据就行。 ADC_CSR寄存器如下:

image.png 当ADC转换结束后ADC_CSR寄存器的EOC位就会置1,读取完采样结果后需要手动将EOC位清零。 由于连续转换模式在初始化之后只会转换当前通道,如果要切换到其他通道需要重新初始化ADC。

在主程序中直接调用通道读取函数就行。

#include "iostm8s103F3.h"
#include "led.h"
#include "adc.h"
#include "stdio.h"
void SysClkInit( void )
{
    CLK_SWR = 0xe1;       //HSI为主时钟源  16MHz CPU时钟频率
    CLK_CKDIVR = 0x00;    //CPU时钟0分频,系统时钟0分频
}
void main( void )
{
    u16 val1 = 0;
    u16 i=0;
    u16 value[450]={0};
    SysClkInit();
    __asm( "sim" );                       //禁止中断
    LED_GPIO_Init();
    ADC_CH_Init( 3 );
    __asm( "rim" );                       //开启中断
    while( 1 )
    {
        LED = !LED;
        for(i=0;i<450;i++)
        {
          val1 = ReadVol_CH3();
          value[i]=val1;
        }
        i=0;
    }
}

在主函数中连续读取450次采样的数据存储在数组中。