ADC采样串口显示采样结果(STM32F103RCT6)

本文重点叙述如何使用单片机STM32F103RCT6的ADC外设进行电压采样并通过串口显示。

一、硬件连接

STM32F103RCT6共有三个ADC,本例中使用ADC1(对应数据手册中的ADC123)的通道1进行采样。ADC1的通道1对应的引脚为PA1。

注意:使用ADC采样时,必须要给ADC提供参考电压(即VREF),并且采样电压不可超过3.3V,如果待采样值超过3.3V或者过小,则需要是使用运放将其缩小或放大,为保证ADC被充分利用,待采样的最大值应接近3.3V,使得采样结果更为准确。

二、程序代码(HAL库)

“adc.h”文件

#ifndef __ADC_H
#define __ADC_H

#include "./SYSTEM/sys/sys.h"

void adc_init(void);            /* ADC初始化 */
u16 get_adc_result(u32 ch);     /* 获得通道值 */
u16 get_adc_result_average(u32 ch, u8 times);   /* 取平均值 */

#endif

“adc.c”文件

#include "adc.h"
#include "./SYSTEM/delay/delay.h"

ADC_HandleTypeDef        ADC1_Handler;

/******************************* ADC初始化 ***********************************/

void adc_init()
{
    RCC_PeriphCLKInitTypeDef    ADC_CLKInit;    /* 外设时钟初始化结构体 */
    
    ADC_CLKInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;   /* 选择ADC时钟 */
    ADC_CLKInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;      /* 选择ADC时钟分频系数 */
    HAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit);                /* 选择ADC时钟源 */
    
    ADC1_Handler.Instance = ADC1;
    ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;      /* 右对齐 */
    ADC1_Handler.Init.ScanConvMode = DISABLE;               /* 非扫描模式 */
    ADC1_Handler.Init.ContinuousConvMode = DISABLE;         /* 关闭连续转换 */
    ADC1_Handler.Init.NbrOfConversion = 1;                  /* 1个转换在规则序列中 也就是只转换规则序列1 */
    ADC1_Handler.Init.DiscontinuousConvMode = DISABLE;      /* 禁止不连续采样模式 */
    ADC1_Handler.Init.NbrOfDiscConversion = 0;              /* 不连续采样通道数为0 */
    ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;/* 软件触发 */
    
    HAL_ADC_Init(&ADC1_Handler);                            /* 初始化 */
    
    HAL_ADCEx_Calibration_Start(&ADC1_Handler);             /* 启动校准 */
}

/******************************* ADC底层驱动 ***********************************/

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef    GPIO_Initure;
    
    __HAL_RCC_ADC1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    GPIO_Initure.Pin = GPIO_PIN_1;
    GPIO_Initure.Mode = GPIO_MODE_ANALOG;
    GPIO_Initure.Pull = GPIO_NOPULL;
    
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}

/******************************* 获取ADC值 ***********************************/

u16 get_adc_result(u32 ch)
{
    ADC_ChannelConfTypeDef  ADC1_ChanConf;
    
    ADC1_ChanConf.Channel = ch;         /* 选择通道 */
    ADC1_ChanConf.Rank = 1;             /* 选择序列 */
    ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;    /* 采样时间 */
    
    HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       /* 通道配置 */
    
    HAL_ADC_Start(&ADC1_Handler);                               /* 开启ADC */
    
    HAL_ADC_PollForConversion(&ADC1_Handler, 10);               /* 轮询转换 */
    
    return (u16) HAL_ADC_GetValue(&ADC1_Handler);               /* 返回最近一次转换值 */
}

/******************************* 获取平均值 ***********************************/

u16 get_adc_result_average(u32 ch, u8 times)
{
    u32 temp_val = 0;
    u8 t;
    for(t=0;t<times;t++)                    /* 获取times次数据 */
    {
        temp_val += get_adc_result(ch);
        delay_ms(5);
    }
    return temp_val/times;                  /* 返回平均值 */
}

“main.c”文件

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/ADC/adc.h"

int main(void)
{
    u16 adcx;
    float temp;


    HAL_Init();
    Stm32_Clock_Init(RCC_PLL_MUL9);
    delay_init(72);
 
    uart_init(115200);
    
    led_init();
    
    adc_init();

        while(1)
    {
        printf("\r\nADC采样值为:");
        
        adcx = get_adc_result_average(ADC_CHANNEL_1, 20);   /* 获取通道1的转换值,20次取平均 */
        printf("\r\n%u\r\n",adcx);    /* 打印数据 */
        
        temp=(float)adcx*(3.3/4096);    /* 获取计算后的带小数的实际电压值,比如3.1111 */
        
        printf("%f\r\n",temp);    /* 打印数据 */
       
        LED(1);
        delay_ms(200);
        LED(0);
        delay_ms(200);
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值