单片机
返回首页

STM8L151系列 单通道ADC数模转换

2020-02-19 来源:eefocus

IAR软件,使用官方halt库


void insertion_sort(u16 a[], u16 length)//插入排序

{

    int len = length;

    int temp;

    int i;//已排好序的序列的下一个元素(待插元素)的下标 

    int j;//有序序列的末尾下标


    for(i = 1;i    {

        temp = a[i];//中间变量 

        j=i-1;

        while(j >= 0 && a[j]>temp){//遍历有序序列,与要插入的元素比较 

            a[j+1] = a[j];//将元素后移,满足条件后移一个位置

            j--; 

        }

        a[j+1] = temp; //插入  

    }



    printf('after_insert: rn');

    for(i = 0 ; i< len; i++)

    {

        DBG_PRINT('%d ',a[i]);

    }

    printf('rn');

}


/*

https://blog.csdn.net/Leo_Luo1/article/details/77370818

    另外STM8L内部还提供了1.2V的参考电压,但是在使用这个参考电压的时候有一些不稳定的现象。ADC_ChannelCmd()


    比如在采集这个参考电压时,如果在读取函数前面加延时,延时的时间不一样得到的采样结果是不一样的,


    另外,这个参考我根据外面提供的VCC作为参考电压来计算的话,得到的值也不是1.2V,这个地方不知道是我的配置出了问题还是这个参考电压本身有问题。

datasheet中写道以下一句话用于解释为什么你的第一次采样不对

The ADC uses the internal reference voltage, so the user must make sure this reference voltage is woken up before enabling the ADC after an exit from Halt or Active-halt mode. 

When enabled, the ADC needs a stabilization time (tWKUP) before starting the first conversion (refer to the device datasheet) Example: after an RTC wakeup (alarm) from Halt mode, 

the ADC is first enabled. Then, the firmware waits for a tWKUP time (3 μs) and the conversion can be started by setting the START bit in the ADC_CR1 register. 

也就是在ref电压稳定后,大概需要等待3us

*/


void init_adc(ADC_Channel_TypeDef ADC_Channel_x)

{

    ADC_Init(ADC1, ADC_ConversionMode_Single, ADC_Resolution_12Bit, ADC_Prescaler_2);//单次转换,12位分辨率(精度),ADC_clock: 4 /2 =2MHz


//    //        ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_4Cycles); //ADC_clock: 2MHz; 配置ADC为快速通道,采样时间周期为9;  {4; 9; 16; 24; 48; 96; 192; 384;}


    ADC_Cmd(ADC1, ENABLE); //使能ADC1

    ADC_ChannelCmd(ADC1, ADC_Channel_x, ENABLE);//使能 通道x


//    ADC_ChannelCmd(ADC1, ADC_Channel_Vrefint, ENABLE);  //内部参考电压



    ADC_ITConfig(ADC1, ADC_IT_EOC, DISABLE); //Disable End of conversion ADC1 Interrupt

    ADC_DMACmd(ADC1,DISABLE); // 禁止DMA


    ADC_SoftwareStartConv (ADC1);//开始ADC软件转换

}



unsigned short adc_handling(ADC_Channel_TypeDef ADC_Channel_x)

{

    u16 get_value = 0;


    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) ;//等待转换结束

    ADC_ClearFlag (ADC1, ADC_FLAG_EOC);//清除对应标志


    get_value = ADC_GetConversionValue (ADC1);//获取转换值


    return get_value;

}



unsigned short adc_common(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin, ADC_Channel_TypeDef adc_channel)

{

#define ADC_COLLECTION_COUNT    10

    u8 i = 0;

    long sum = 0;

    u16 value=0, tmp_value[ADC_COLLECTION_COUNT] = {0};


    GPIO_Init(GPIOx, GPIO_Pin, GPIO_Mode_In_FL_No_IT);

    CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);//开启ADC时钟


    for(i=0; i    {

        init_adc(adc_channel);

        tmp_value[i] = adc_handling(adc_channel);

    }


    // 应该在操作ADC的寄存器关停它之后,才停止它的时钟。

    ADC_ChannelCmd(ADC1, adc_channel, DISABLE);//禁用 通道x

    ADC_Cmd(ADC1, DISABLE);

    CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, DISABLE);// 禁用ADC时钟


//    GPIO_Init(GPIOx, GPIO_Pin, GPIO_Mode_Out_PP_Low_Slow); //不要设置输出模式;  悬空输入就是 低功耗

    insertion_sort(tmp_value, ADC_COLLECTION_COUNT); // 排序: 去掉 最大值,最小值; 在求平均值

    for(i=1; i        sum += tmp_value[i];


    value = sum / (ADC_COLLECTION_COUNT - 2);

    return value;

}


unsigned short get_adc(void)

{

    return adc_common(GPIOD, GPIO_Pin_2, ADC_Channel_20); //  xx电阻的ADC; PD^2; ADC1_IN20(通道20) 

}

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • RS-485基础知识:处理空闲总线条件的两种常见方法

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章