发新帖我要提问
123
返回列表
打印
[STM32F1]

stm32F103——ADC与DMA(按键与光敏电阻)

[复制链接]
楼主: 我爱台妹mmd
手机看帖
扫描二维码
随时随地手机跟帖
41
我爱台妹mmd|  楼主 | 2023-11-26 01:06 | 只看该作者 |只看大图 回帖奖励 |倒序浏览

使用特权

评论回复
42
我爱台妹mmd|  楼主 | 2023-11-26 01:06 | 只看该作者
设置采样通道、采样通道的顺序Rank与采样时间ADC_SampleTime。采样顺序就是,比如通道11设置为1,通道10设置为2,那么先采集通道11的数据,再采集通道10的数据。采样时间,如下图:

使用特权

评论回复
43
我爱台妹mmd|  楼主 | 2023-11-26 01:06 | 只看该作者
注意:采样时间越长,采样出来的数据越准确。在12Mhz频率下,最长的239.5个周期就是21us,采样50个数据总共也就花费21* 50 = 1050us的时间(即1.05ms),对于整个按键动作来说,这个时间非常短。


注意:获取ADC校准寄存器的状态标志位与以往的不一样。它是正在执行校准初始化的过程中时,标志位置1。已经完成校准初始化时,标志位置0。

        注意:ADC要在使能之后,才能开始进行校准。

使用特权

评论回复
44
我爱台妹mmd|  楼主 | 2023-11-26 01:07 | 只看该作者
编写代码

#define ADC_CH 2
#define ADC_data_size 50
uint16_t ADC_DATA[ADC_data_size][ADC_CH];        //用来存储数据的二维数组

void ADC1_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    ADC_InitTypeDef ADC_InitStruct;
    DMA_InitTypeDef DMA_InitStruct;
    // 1,打开时钟----ADC1,GPIOC,AFIO,DMA1
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

    // 2,ADC预分频器---6分频---ADCCLK=12MHZ
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    // 3,初始化GPIOC
    GPIO_InitStruct.GPIO_Pin    =GPIO_Pin_0|GPIO_Pin_1;
    GPIO_InitStruct.GPIO_Mode   =GPIO_Mode_AIN;
    GPIO_Init(GPIOC,&GPIO_InitStruct);

    // 4,初始化ADC1
    ADC_InitStruct.ADC_ContinuousConvMode   =ENABLE;
    ADC_InitStruct.ADC_DataAlign            =ADC_DataAlign_Right;
    ADC_InitStruct.ADC_ExternalTrigConv     =ADC_ExternalTrigConv_None;
    ADC_InitStruct.ADC_Mode                 =ADC_Mode_Independent;
    ADC_InitStruct.ADC_NbrOfChannel         =ADC_CH;        //宏定义ADC_CH = 2
    ADC_InitStruct.ADC_ScanConvMode         =ENABLE;
    ADC_Init(ADC1,&ADC_InitStruct);

    // 5,使能ADC的DMA
    ADC_DMACmd(ADC1,ENABLE);

    // 6,DMA初始化
    DMA_InitStruct.DMA_PeripheralBaseAddr   =(uint32_t)&ADC1->DR;      
    DMA_InitStruct.DMA_MemoryBaseAddr       =(uint32_t)ADC_DATA;  /*这里强转为(uint32_t)类型,是因为在结构体DMA_InitStruct里面,成员DMA_MemoryBaseAddr是uint32_t类型的*/
    DMA_InitStruct.DMA_DIR                  =DMA_DIR_PeripheralSRC;
    DMA_InitStruct.DMA_PeripheralInc        =DMA_PeripheralInc_Disable;
    DMA_InitStruct.DMA_MemoryInc            =DMA_MemoryInc_Enable;
    DMA_InitStruct.DMA_PeripheralDataSize   =DMA_PeripheralDataSize_HalfWord;
    DMA_InitStruct.DMA_MemoryDataSize       =DMA_MemoryDataSize_HalfWord;
    DMA_InitStruct.DMA_BufferSize           =ADC_CH*ADC_data_size;
    DMA_InitStruct.DMA_M2M                  =DMA_M2M_Disable;
    DMA_InitStruct.DMA_Mode                 =DMA_Mode_Circular;
    DMA_InitStruct.DMA_Priority             =DMA_Priority_High;
    DMA_Init(DMA1_Channel1,&DMA_InitStruct);

    // 7,使能DMA1通道1
    DMA_Cmd(DMA1_Channel1, ENABLE);

    // 8,配置通道10和通道11的采样顺序和采样时间
    ADC_RegularChannelConfig(ADC1,ADC_Channel_10, 1,ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_11, 2,ADC_SampleTime_239Cycles5);

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

    // 10,校准
    ADC_ResetCalibration(ADC1);
    while(SET==ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(SET==ADC_GetCalibrationStatus(ADC1));

    // 11,软件触发ADC
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}


uint16_t ADC_RG_Value(void)        //将采集到的50个光敏电阻电压的数据累加起来,然后求平均值
{
    uint32_t SUM=0;
    uint8_t i;
    for(i=0;i<ADC_data_size;i++){
        SUM=SUM+ADC_DATA[i][0];
    }
    return (uint16_t)(SUM/ADC_data_size);
}

uint16_t ADC_KEY_Value(void)        //将采集到的50个按键电压的数据累加起来,然后求平均值
{
    uint32_t SUM=0;
    uint8_t i;
    for(i=0;i<ADC_data_size;i++){
        SUM=SUM+ADC_DATA[i][1];
    }
    return (uint16_t)(SUM/ADC_data_size);
}


int main(void)
{
   
    RCC_ConfigTo72M();
    Systick_Config(72);
    DMA1CH2_Config(SRC,DRC,data_size);
    ADC1_Config();
    while(1){
        printf("ADC_RG_Value=%d\n",ADC_RG_Value());
        printf("ADC_KEY_Value=%d\n",ADC_KEY_Value());

   }
}

注意:DMA搬运数据,是来一个数据搬运一次,而不是,不管来不来数据它都独自一人,在一个孤独的角落默默的搬运。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则