STM32F1进行ADC采样转换,通过中断获取采样后的数据

该主题比上一主题主要是使用了中断

1.main.c文件

#include "stm32f10x.h"
#include "adc.h"
#include "usart1.h"

uint16_t adc_val = 0;
uint8_t cnt = 0;
void delay(void)
{
    uint32_t t = 0;
    for(t = 0; t < 0xfffef; t ++);
}

int main(void)
{
    USART1_Init();
    ADC1_Init_Config();
    
    //ADC规则通道配置
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_239Cycles5);
    //RANK:数值越小,越先转换;这里通道2,第一个进行AD转换;要是有多个通道的话,设定先后顺序
    //    ADC采样周期计算公式 = ADC_SampleTime_xxxCycles5 + 12.5个周期,这里是256个周期,频率设置成了12MHz,所以采样时间 = 256/12MHz = 21.3us,采样时间长,采样会准确些

    //ADC采样前先进行校准动作
    ADC_ResetCalibration(ADC1);//复位校准
    while(ADC_GetResetCalibrationStatus(ADC1) != RESET); //平时是1,复位完成变成0

    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1) != RESET);//平时是1,校准完成变成0

    


    while(1)
    {
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);    //软件启动AD转换功能
//        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //平时是0,转换完成变成1    ;这次使用的中断,转换完成会进入中断,读取数据。用的ADC_GetITStatus函数

        
        printf("AD-VALUE:%d--- %.3f\r\n", cnt,(float)adc_val/4096.0*3.3);//这里注意需要除以4096.0,如果写成了整数,打印输出就会变成0.0了

        delay();
    }
}

和前篇的差异标红处理展示;

2.adc.c文件

#include "adc.h"



void ADC1_Init_Config(void)
{
    
    ADC_InitTypeDef  ADC_InitStruct;

    //1.配置ADC的GPIO引脚
    GPIO_InitTypeDef  GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//输入功能不用设置输出速度参数
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
    
    //2.配置时钟,GPIOA时钟和ADC1外设时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE);

    //PA2 ADC_IN2 
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    //3.配置ADC模式相关参数
    ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; //设置成连续转换模式(ENABLE)或者单次转换模式(DISABLE)
    ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐,12位的数据,右对齐不用处理高位,高位就是0
    ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;    //若是选择外部触发转换,选择对应的触发条件,否则设置为不使用外部触发
    ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//多种模式组合,选择一种
    ADC_InitStruct.ADC_NbrOfChannel = 1;//需要转换的通道数,这里只有1个通道要转换
    ADC_InitStruct.ADC_ScanConvMode = DISABLE;//多通道扫描转换(ENABLE),或者是单通道转换(DISABLE),这里选择单通道转换

    //4.配置ADC时钟不能超过14MHz    系统时钟72MHz进行6分频,12MHz
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    //5.ADC1初始化
    ADC_Init(ADC1, &ADC_InitStruct);

    //6.ADC中断使能    ,看到中断,要想到NVIC配置
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
    //7.进行中断相关设置
    ADC_NVIC_Config();

    //8.ADC1功能使能
    ADC_Cmd(ADC1, ENABLE);
}

3.新增加了nvic.c文件

#include "nvic.h"


void ADC_NVIC_Config(void)
{
    NVIC_InitTypeDef    NVIC_InitStruct;



    NVIC_InitStruct.NVIC_IRQChannel = ADC1_2_IRQn;    //ADC中断功能
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;      //响应优先级
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);     //中断组配置
    
    NVIC_Init(&NVIC_InitStruct);  

}

4.中断函数返回ADC采样数据

void ADC1_2_IRQHandler(void)
{
    if(ADC_GetITStatus(ADC1, ADC_IT_EOC))      //如果,ADC1转换结束,则读取数据
    {
        adc_val = ADC_GetConversionValue(ADC1);
        if(cnt < 200)cnt ++;
    }
    

    ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);  //读取完后,清除标志位
}

虽然设置的是单次转换【ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;】,但是因为在主函数,主循环中,一段时间进行一次软件启动AD转换,所以AD一直出来新的采样值。

posted @ 2025-03-28 21:15  了解2号  阅读(348)  评论(0)    收藏  举报