ADC模块示例程序_沁恒CH585EVT

  • CH585/CH584提供了12位模数转换器,支持差分和单端输入,支持14路外部电压采样信号通道,3路内部信号:内部的温度检测通道、内部的电池电压检测通道、内部的 NFC 能量检测通道

  • MounRiver Studio使用PRINT时默认不支持打印浮点数,如果要打印浮点数,需要如图配置
    aa936b8bfba7e3fcf4fd6bf18203cc73

  • 内部温度采样

    PRINT("\n1.Temperature sampling...\n");
    ADC_InterTSSampInit();//内置温度传感器采样初始化

    ADC_ExcutSingleConver();//时间足够时建议再次转换并丢弃首次ADC数据
    for(i = 0; i < 20; i++)
    {
        adcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
    }
    for(i = 0; i < 20; i++)
    {
        uint32_t C25 = 0;
        C25 = (*((PUINT32)ROM_CFG_TMP_25C));//25°C温度传感器校准值
        PRINT("%d %d %d \n", adc_to_temperature_celsius(adcBuff[i]),adcBuff[i],C25);
    }
  • 单通道采样
    /* 单通道采样:选择adc通道0做采样,对应 PA4引脚, 带数据校准功能 */
    PRINT("\n2.Single channel sampling...\n");
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating);
    // 采样率最高8M
    ADC_ExtSingleChSampInit(SampleFreq_8_or_4, ADC_PGA_1_4);
        RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
        PRINT("RoughCalib_Value =%d \n", RoughCalib_Value);
        ADC_ChannelCfg(0);
        ADC_ExcutSingleConver();//时间足够时建议再次转换并丢弃首次ADC数据
        for(i = 0; i < 20; i++)
        {
            adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
        }
        for(i = 0; i < 20; i++)
        {
            PRINT("%d \n", adcBuff[i]); // 注意:由于ADC内部偏差的存在,当采样电压在所选增益范围极限附近的时候,可能会出现数据溢出的现象
            float vol = (adcBuff[i]/PGA_DIV_12_ - 3.0f) * VREF;
            PRINT("voltage is %.2f mv\n", vol);
        }
  • ADC_ExtSingleChSampInit(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga):
    • ADC_SampClkTypeDef:采样频率,SampleFreq_8_or_4,4M或8M与时钟源有关,HSI为4M,HSE为8M
      ADC_SignalPGATypeDef:PGA增益
      {E3297C15-672E-42E5-8BE2-A1BDC4E8777B}
  • DMA采样
  /* DMA单通道采样:选择adc通道0做采样,对应 PA4引脚 */
    PRINT("\n3.Single channel DMA sampling...\n");
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating);
    ADC_ExtSingleChSampInit(SampleFreq_8_or_4, ADC_PGA_1_4);//ADC单通道采样,8M,PGA 1/4倍
    ADC_ChannelCfg(0);//chan 0/PA4
    ADC_ExcutSingleConver();//时间足够时建议再次转换并丢弃首次ADC数据
    ADC_AutoConverCycle(192); // 采样周期为 (256-192)*16个系统时钟
    ADC_DMACfg(ENABLE, (uint32_t)&adcBuff[0], (uint32_t)&adcBuff[40], ADC_Mode_Single);//enable DMA, 单次模式(传输完40次后停止)
    PFIC_EnableIRQ(ADC_IRQn);
    ADC_StartAutoDMA();//启动ADC自动DMA采样(开始连续采样,DMA自动搬运)
    while(!DMA_end);
    DMA_end = 0;
    ADC_DMACfg(DISABLE, 0, 0, 0);//disable DMA
    for(i = 0; i < 40; i++)
    {
        PRINT("%d \n", adcBuff[i]);
        float vol = (adcBuff[i]/PGA_DIV_12_ - 3.0f) * VREF;
        PRINT("voltage is %.2f mv\n", vol);
    }
	
	__INTERRUPT
__HIGH_CODE
void ADC_IRQHandler(void) //adc中断服务程序
{
#if(!ADC_SCAN_MODE_EXAM)
    if(ADC_GetDMAStatus())//DMA trans finish
    {
        ADC_StopAutoDMA();
        R32_ADC_DMA_BEG = ((uint32_t)adcBuff) & 0x1ffff;//重置DMA地址
        ADC_ClearDMAFlag();
        DMA_end = 1;
    }
    if(ADC_GetITStatus())
     {
         ADC_ClearITFlag();
     }
}
    /* 差分通道采样:选择adc通道0做采样,对应 PA4(AIN0)、PA12(AIN2) */
    PRINT("\n4.Diff channel sampling...\n");
    GPIOA_ModeCfg(GPIO_Pin_4 | GPIO_Pin_12, GPIO_ModeIN_Floating);
    ADC_ExtDiffChSampInit(SampleFreq_8_or_4, ADC_PGA_1_4);//8M
    ADC_ChannelCfg(0);
    ADC_ExcutSingleConver();//时间足够时建议再次转换并丢弃首次ADC数据
    for(i = 0; i < 20; i++)
    {
        adcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
    }
    for(i = 0; i < 20; i++)
    {
        PRINT("%d \n", adcBuff[i]);
        float vol = (adcBuff[i]/PGA_DIV_12_ - 4.0f) * VREF;//计算与普通ADC不同
        PRINT("voltage is %.2f mv\n", vol);
    }

0cf63fab-234e-4209-9b38-df6595a46403

/* 单通道采样:中断方式,选择adc通道1做采样,对应 PA5引脚, 不带数据校准功能 */
 /* 单通道采样:中断方式,选择adc通道1做采样,对应 PA5引脚, 不带数据校准功能 */
    PRINT("\n6.Single channel sampling in interrupt mode...\n");
    GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating);
    ADC_ExtSingleChSampInit(SampleFreq_8_or_4, ADC_PGA_1_4);
    ADC_ChannelCfg(1);
    ADC_ExcutSingleConver();//时间足够时建议再次转换并丢弃首次ADC数据
    adclen = 0;
    ADC_ClearITFlag();
    PFIC_EnableIRQ(ADC_IRQn);
    ADC_StartUp();
    while(1)
    {
        if(temp_flag == 1)
        {
            for(i = 0; i < 20; i++)
            {
                PRINT("%d \n", adcBuff[i]);
                float vol = (adcBuff[i]/PGA_DIV_12_ - 3.0f) * VREF;
                PRINT("voltage is %.2f mv\n", vol);
            }
            ADC_StartUp();
            temp_flag = 0;
            adclen = 0;
        }
    };
	
__INTERRUPT
__HIGH_CODE
void ADC_IRQHandler(void) //adc中断服务程序
{
    if(ADC_GetITStatus())
    {
        ADC_ClearITFlag();
        if(adclen < 20)
        {
            adcBuff[adclen] = ADC_ReadConverValue();
            ADC_StartUp(); // 作用清除中断标志并开启新一轮采样
        }
        adclen++;
    }
    temp_flag = 1;
}
  • 扫描模式
/*********************************************************************
 * @fn      ADC_Scan
 *
 * @brief   ADC扫描
 *
 * @return  none
 */
void ADC_Scan( void )
{

    ADC_RegDeinit();    // 复位ADC寄存器
    Touch_RegDeinit();  // 复位Touch寄存器
    memset( adcBuff, 0, 200 );//adc buff size is 200
    memset( adcBuff1, 0, 200 );

    /* 配置全部 22 个 AIN 引脚为浮空输入 */
    for ( uint8_t ch = CH_EXTIN_0; ch <= CH_EXTIN_21; ch++ )
    {
        ADC_AinGpioCfg( ch );//配置浮空,关闭数字输入模式
    }

    ADC_ExtSingleChSampInit( SAMPLE_CLK_96_OR_124_8, ADC_PGA_1_2);//配置采样频率和增益,注意增益的配置

    RoughCalib_Value = ADC_DataCalib_Rough();//校准值
    PRINT( "RoughCalib_Value =%d \n", RoughCalib_Value );
    ADC_ChannelCfg( scan_ch[ 0 ] );//

    R32_ADC_SCAN_CFG4 = 0;
    /* 打包通道 1~8 到 SCAN_CFG1(每通道 4 位) */
    uint32_t cfg1     = 0;
    for ( int i = 0; i < 8; i++ )
    {
        cfg1 |= ( (uint32_t)( scan_ch[ i + 1 ] ) << ( i * 4 ) );
        if ( scan_ch[ i + 1 ] > CH_EXTIN_15 )
            R32_ADC_SCAN_CFG4 |= (uint32_t)1 << ( i + 1 - 1 );
    }
    R32_ADC_SCAN_CFG1 = cfg1;

    /* 打包通道 9~13 到 SCAN_CFG2,加上扫描控制位 */
    uint32_t cfg2 = 0;
    for ( int i = 0; i < 5; i++ )
    {
        cfg2 |= ( (uint32_t)( scan_ch[ i + 9 ] ) << ( i * 4 ) );
        if ( scan_ch[ i + 9 ] > CH_EXTIN_15 )
            R32_ADC_SCAN_CFG4 |= (uint32_t)1 << ( i + 9 );
    }
    R32_ADC_SCAN_CFG2 = cfg2;

    /* 打包通道 14~21 到 SCAN_CFG3,加上扫描控制位 */
    uint32_t cfg3 = 0;
    for ( int i = 0; i < 8; i++ )
    {
        cfg3 |= ( (uint32_t)( scan_ch[ i + 14 ] ) << ( i * 4 ) );
        if ( scan_ch[ i + 14 ] > CH_EXTIN_15 )
            R32_ADC_SCAN_CFG4 |= (uint32_t)1 << ( i + 14 );
    }
    R32_ADC_SCAN_CFG3 = cfg3;

    R32_ADC_SCAN_CFG2 |= ( ( ( ADC_SCAN_CH_NUM - 1 ) & 0x0F ) << 24 ); /* scan_num = 22-1=21 ADC_SCAN_CH_NUM - 1*/
    R32_ADC_SCAN_CFG2 |= RB_ADC_SCAN_NUM_H;                            /* SCAN_NUM 高位(支持 >16 通道) */
    R32_ADC_SCAN_CFG2 |= RB_ADC_SCAN_SEL;                              /* 选择 ADC(非 TKEY),扫描由 SCAN_NUM 非零自动激活 */
    R32_ADC_SCAN_CFG2 &= ~RB_ADC_IE_SCAN_END;                          /*扫描结束中断使能*/
    R32_ADC_SCAN_CFG2 &= ~RB_EHCH_TIM;//每个通道采样次数复位
    R32_ADC_SCAN_CFG2 |= 1 << 20;                                      /* 扫描过程中每个通道采样2次,dma缓冲区需要配置2*scan_num */
    R32_ADC_SCAN_CFG2 |= RB_ADC_SCAN_EN;                               /* 扫描使能 */


    R32_ADC_DMA_BEG  = (uint32_t)&adcBuff[ 0 ] & 0x3ffff;//DMA 起始缓冲区地址
    R32_ADC_DMA_END  = (uint32_t)&adcBuff[ ADC_SCAN_CH_NUM * 2 ] & 0x3ffff;
    R8_ADC_CTRL_DMA |= RB_ADC_DMA_ENABLE |RB_SCAN_AUTO_TYPE;//连续触发扫描
    PFIC_EnableIRQ( ADC_IRQn );
    SCAN_end = 0;//end flag
    ADC_StartUp();//执行单次转换
    while ( !SCAN_end ); /* 等待 DMA 完成 */
    SCAN_end = 0;

    PFIC_DisableIRQ( ADC_IRQn );
    ADC_DMACfg( DISABLE, 0, 0, 0 );

    /* 关闭扫描模式 */
    R32_ADC_SCAN_CFG2 = 0;

    for ( int i = 0; i < ADC_SCAN_CH_NUM; i++ )
    {
        PRINT( "SCAN_CH%d: %d %d \n", i, adcBuff[ i * 2 ] + RoughCalib_Value, adcBuff[ i * 2 + 1 ] + RoughCalib_Value );
    }
}
posted @ 2026-05-22 16:38  J_02346  阅读(33)  评论(0)    收藏  举报