wenyangzeng 发表于 2017-4-6 22:29:08

【NUCLEO-L496ZG评测】评测5:过采样ADC

本帖最后由 wenyangzeng 于 2018-10-30 16:35 编辑

【NUCLEO-L469ZG评测】评测1:编译环境建立
【NUCLEO-L469ZG评测】评测2:Coremark跑分
【NUCLEO-L469ZG评测】评测3:低功耗测试
【NUCLEO-L469ZG评测】评测4:USB_FS_OTG
【NUCLEO-L496ZG评测】评测5:过采样ADC
【NUCLEO-L496ZG评测】评测6:可编程运放PGA



    STM32L496的又一个亮点是具有过采样ADC功能。
通过配置最大过采样率(ADC_OVERSAMPLING_RATIO_128)其ADC转换结果为0xFFF * 128 = 0x7FF80,居然可以达到19位的精度。
硬件连接:

电位器连接开发板的A_VDD和A_GND,抽头接PA4(ADC_CHANNEL_9),PC8-PC11用于驱动OLED屏显示转换结果。

软件:
    在STM32Cube_FW_L4_V1.7.0\Projects\STM32L496ZG-Nucleo\Examples\ADC\ADC_OverSampler提供了过采样ADC的演示软件包。可以直接应用,在工程中添加了OLED.C文件。在main()函数中添加调用OLED显示的函数。



#include "main.h"
#include "OLED.h"
ADC_HandleTypeDef      AdcHandle;
ADC_ChannelConfTypeDef   sConfig;
uint32_t               uwConvertedValue;
uint32_t               uwInputVoltage;
void SystemClock_Config(void);
static void Error_Handler(void);
uint8_t disp_buf;
int main(void)
{
HAL_Init();
SystemClock_Config();
BSP_LED_Init(LED1);
OLED_Init();
OLED_Print(0, 0,"STM32L469ZG",TYPE16X16,TYPE8X16);
OLED_Print(0, 16, "ADC_OVERSAMPLING",TYPE16X16,TYPE8X16);
AdcHandle.Instance          = ADCx;
if (HAL_ADC_DeInit(&AdcHandle) != HAL_OK)
   {
    Error_Handler();
   }
AdcHandle.Init.ClockPrescaler      = ADC_CLOCK_ASYNC_DIV1;
AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;
AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
AdcHandle.Init.ScanConvMode          = DISABLE;
AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
AdcHandle.Init.LowPowerAutoWait      = DISABLE;
AdcHandle.Init.ContinuousConvMode    = ENABLE;restart after each conversion) */
AdcHandle.Init.NbrOfConversion       = 1;
AdcHandle.Init.DiscontinuousConvMode = DISABLE;
AdcHandle.Init.NbrOfDiscConversion   = 1;
AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;
AdcHandle.Init.ExternalTrigConvEdge= ADC_EXTERNALTRIGCONVEDGE_NONE;
AdcHandle.Init.DMAContinuousRequests = DISABLE;
AdcHandle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;
AdcHandle.Init.OversamplingMode      = ENABLE;
AdcHandle.Init.Oversampling.Ratio               = OVERSAMPLING_RATIO;
AdcHandle.Init.Oversampling.RightBitShift         = RIGHTBITSHIFT;
AdcHandle.Init.Oversampling.TriggeredMode         = TRIGGEREDMODE;
AdcHandle.Init.Oversampling.OversamplingStopReset = OVERSAMPLINGSTOPRESET;
if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
    {
    Error_Handler();
    }
if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED) != HAL_OK)
   {
    Error_Handler();
   }
sConfig.Channel      = ADCx_CHANNEL;
sConfig.Rank         = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5;
sConfig.SingleDiff   = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
{
    Error_Handler();
}

if (HAL_ADC_Start(&AdcHandle) != HAL_OK)
{
    Error_Handler();
}

while (1)
{   
    if (HAL_ADC_PollForConversion(&AdcHandle, 10) != HAL_OK)
    {
      Error_Handler();
    }
    uwConvertedValue = HAL_ADC_GetValue(&AdcHandle);
    uwInputVoltage = uwConvertedValue * 3300;
    uwInputVoltage = uwInputVoltage / 0xFFF0;

    disp_buf=uwInputVoltage%10000/1000+0x30;
    disp_buf='.';
    disp_buf=uwInputVoltage%1000/100+0x30;      
    disp_buf=uwInputVoltage%100/10+0x30;      
    disp_buf=uwInputVoltage%10+0x30;
    disp_buf=' ';
    disp_buf='V';
    OLED_Print(36, 40, disp_buf,TYPE16X16,TYPE8X16);
   
}
}

void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLP = 7;
RCC_OscInitStruct.PLL.PLLQ = 4;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
    while(1);
}

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
    while(1);
}
}
static void Error_Handler(void)
{
BSP_LED_On(LED1);
while (1)
{
}
}编译下载运行.
http://player.youku.com/player.php/sid/XMjY5MTE3NTg2NA==/v.swf



https://v.youku.com/v_show/id_XMjY5MTE3NTg2NA==.html?spm=a2hzp.8253869.0.0

注:读数出现变化时是因为正在调整电位器
    运行结果令人满意,本评测的ADC转换电压范围是0.000-3.300V,分辨率为1mV,ADC转换结果未作任何滤波处理,当电位器调整到某个位置不动后,读数最后一位数居然纹丝不动。可见该方案的ADC转换结果具有极高的分辨率和信噪比,如果用于数字表头产品是非常优秀的选择。







strang 发表于 2017-4-7 16:30:39

不错,很给力!~

wenyangzeng 发表于 2017-4-7 19:03:14

strang 发表于 2017-4-7 16:30
不错,很给力!~

谢谢支持

anywill 发表于 2017-4-8 12:24:40

很强大且实用的一项功能,以后留意一下,本来想买16位的采集模块

wenyangzeng 发表于 2017-4-8 13:02:18

anywill 发表于 2017-4-8 12:24
很强大且实用的一项功能,以后留意一下,本来想买16位的采集模块

这个系列芯片的这个功能应该是可以考虑选择的。

bjdj0000 发表于 2018-10-1 18:00:35

过采样DMA传输函数是哪个呢?

yl19960531 发表于 2018-10-30 14:48:04

楼主视频好像打不开了,能否再传一份?

wenyangzeng 发表于 2018-10-30 16:24:55

本帖最后由 wenyangzeng 于 2018-10-30 16:27 编辑

yl19960531 发表于 2018-10-30 14:48
楼主视频好像打不开了,能否再传一份?好像是社区网页的问题,破总能否帮助解决一下。@zero99

wenyangzeng 发表于 2018-10-30 16:29:43

本帖最后由 wenyangzeng 于 2018-10-30 16:33 编辑

yl19960531 发表于 2018-10-30 14:48
楼主视频好像打不开了,能否再传一份?https://v.youku.com/v_show/id_XMjY5MTE3NTg2NA==.html?spm=a2hzp.8253869.0.0


yl19960531 发表于 2018-12-11 16:22:41

请问这个采样频率是多少?辛苦楼主了
页: [1] 2
查看完整版本: 【NUCLEO-L496ZG评测】评测5:过采样ADC