OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4880|回复: 1

STMF407xx双重ADC多通道模式

[复制链接]

10

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1554
金钱
1554
注册时间
2017-10-9
在线时间
131 小时
发表于 2020-6-23 14:32:55 | 显示全部楼层 |阅读模式
本帖最后由 千湖 于 2020-6-23 14:42 编辑

ADC1:CH0、CH1
ADC2:CH2、CH3


双重规则模式,12Bit,右对齐,采样时间为28cycle[可修改],转换周期固定为12cycle;采样时钟21MHz,得到一个数据的时间为:(28+12)/21MHz = 1.9us,

采集到的数据存放在定义的数组中
uint16_t ADC_ConVal[MAX_LEN * (ADC1_CHN + ADC2_CHN)] = {0};     // ADC存储数据

使用DMA2流0通带0进行传输,软件触发转换!


/**
  * @brief   ADC采集数据存放的位置
  *          (n*i+ 0)的下标存放 CH0数据
  *          (n*i+ 1)的下标存放   CH2数据
  *          (n*i+ 2)的下标存放   CH1数据
  *          (n*i+ 3)的下标存放  CH3 数据
  */
uint16_t ADC_ConVal[MAX_LEN * (ADC1_CHN + ADC2_CHN)] = {0};     // ADC存储数据


/*====================单个ADC需要转换的通道数========*/
/**
  * @brief ADC需要转换的通道数
  */
#define     ADC1_CHN            2       // ADC1转换的通道数
#define     ADC2_CHN            2       // ADC2转换的通道数
/*********************************************************/


/*==============一个周期内采集的次数========*/
/**
  * @brief 一个周期内采集的次数
  */
#define     MAX_LEN            1500
/*********************************************************/



/**
  * @brief   ADC初始化 采集上下行数据
  * @param   None
  * @retval  None
  */
void Adc_Init(void)
{
    GPIO_InitTypeDef        GPIO_InitStructure;
    ADC_InitTypeDef         ADC_InitStructure;
    ADC_CommonInitTypeDef   ADC_CommonInitStructure;
    DMA_InitTypeDef         DMA_InitStructure;

    /*=============================配置ADC对应的GPIO=============================*/
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);    // 初始化GPIOA时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;  // PA0,PA1,PA2,PA3
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;            // 模拟输入
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;       // 不带上下拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);



    /*=============================DMA初始化=============================*/
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);    // 使能DMA2时钟

    DMA_InitStructure.DMA_Channel = DMA_Channel_0;          // 选择通道0
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC->CDR);   // ADC->CDR寄存器的地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&(ADC_ConVal);    // 存储数据的地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;             // 外设到存储器
    DMA_InitStructure.DMA_BufferSize = MAX_LEN * (ADC1_CHN + ADC2_CHN); // DMA缓存大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    // 外设地址是否为增量模式
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;             // 存储器地址是否为增量模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 半字
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 半字
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                     // 循环传输模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                 // DMA优先级,高优先级
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;              // 不用FIFO
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;   // FIFO阈值
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;         // 存储器突发、单次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 外设突发、单次传输
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);

    DMA_Cmd(DMA2_Stream0, ENABLE);      // 使能DMA2_Stream0流


    /*=============================ADC时钟使能=============================*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);    // 使能ADC1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);    // 使能ADC2时钟

    RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE);    // ADC1复位
    RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE);   // 复位结束

    RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE);    // ADC2复位
    RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE);   // 复位结束

    /*=============================ADC公共部分配置=============================*/
    ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;    // 双重模式多通道
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;   // ADC采样时钟21MHz
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;    // DMA模式1
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;    // 两个采样延时5个Tadcclk,此配置仅在交替模式中生效
    ADC_CommonInit(&ADC_CommonInitStructure);


    /*=============================ADC1部分配置=============================*/
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;      // 12位
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;                // 扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;          // 连续转换
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;  // 禁止触发检测
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;   // 软件触发,此配置无用
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;      // 右对齐
    ADC_InitStructure.ADC_NbrOfConversion  = ADC1_CHN;          // 转换通道2个   /****此处ADC1和ADC2通道数一样,可以不用再修改,若两个通道数不相同,在2处添加ADC2的通道数*********/

    /*=============================ADC1部分配置=============================*/
    ADC_Init(ADC1, &ADC_InitStructure);
    /*=============================ADC1转换顺序=============================*/
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_28Cycles);   // ADC1_CHANNEL0,第一个转换,采样时间位28个周期
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_28Cycles);   // ADC1_CHANNEL1,第二个转换,采样时间位28个周期



    /*=============================ADC2部分配置=============================*/
    ADC_InitStructure.ADC_NbrOfConversion  = ADC2_CHN;                                     /**********2**********/
    ADC_Init(ADC2, &ADC_InitStructure);
    /*=============================ADC2转换顺序=============================*/
    ADC_RegularChannelConfig(ADC2, ADC_Channel_2, 1, ADC_SampleTime_28Cycles);   // ADC1_CHANNEL2,第一个转换,采样时间位28个周期
    ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 2, ADC_SampleTime_28Cycles);   // ADC1_CHANNEL3,第二个转换,采样时间位28个周期

    ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);  // 使能DMA请求 (多ADC模式)

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

    ADC_SoftwareStartConv(ADC1);    // 开启ADC1转换

}


/**寄存器版的若需要,请留言,我后面补上**/


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2021-12-28
在线时间
2 小时
发表于 2021-12-28 10:41:29 | 显示全部楼层
江湖规矩,先顶为上,建议楼主放一个源码文件
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 09:31

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表