双从ADC同步规则模式采集实验

这里使用ADC1和ADC2同时采集实验,ADC1采集的数据放在DR低16位,ADC2采集的数据放在DR高16位,最后传输给定义的数组中输出。
在这里插入图片描述
创建bsp_adc.h和bsp_adc.c两个文件:
bsp_adc.h

#ifndef __BSP_ADC_H_
#define __BSP_ADC_H_

#include "stm32f10x.h"

// 双模式时,ADC1和ADC2转换的数据都存放在ADC1的数据寄存器,
// ADC1的在低十六位,ADC2的在高十六位
// 双ADC模式的第一个ADC,必须是ADC1
#define    ADCx_1                           ADC1
#define    ADCx_1_APBxClock_FUN             RCC_APB2PeriphClockCmd
#define    ADCx_1_CLK                       RCC_APB2Periph_ADC1

#define    ADCx_1_GPIO_APBxClock_FUN        RCC_APB2PeriphClockCmd
#define    ADCx_1_GPIO_CLK                  RCC_APB2Periph_GPIOC  
#define    ADCx_1_PORT                      GPIOC
#define    ADCx_1_PIN                       GPIO_Pin_1
#define    ADCx_1_CHANNEL                   ADC_Channel_11

// 双ADC模式的第二个ADC,必须是ADC2
#define    ADCx_2                           ADC2
#define    ADCx_2_APBxClock_FUN             RCC_APB2PeriphClockCmd
#define    ADCx_2_CLK                       RCC_APB2Periph_ADC2

#define    ADCx_2_GPIO_APBxClock_FUN        RCC_APB2PeriphClockCmd
#define    ADCx_2_GPIO_CLK                  RCC_APB2Periph_GPIOC  
#define    ADCx_2_PORT                      GPIOC
#define    ADCx_2_PIN                       GPIO_Pin_4
#define    ADCx_2_CHANNEL                   ADC_Channel_14

#define    NOFCHANEL                        1

// ADC 通道宏定义
#define    ADC_DMA_CHANNEL                  DMA1_Channel1

void ADCx_Init(void);

#endif

bsp_adc.c

#include "bsp_adc.h"

__IO uint32_t ADC_ConvertedValue[] = {0};

static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// ADCx_1 GPIO 初始化
	ADCx_1_GPIO_APBxClock_FUN ( ADCx_1_GPIO_CLK, ENABLE );
	GPIO_InitStructure.GPIO_Pin = ADCx_1_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(ADCx_1_PORT, &GPIO_InitStructure);

	// ADCx_2 GPIO 初始化
	ADCx_1_GPIO_APBxClock_FUN ( ADCx_2_GPIO_CLK, ENABLE );
	GPIO_InitStructure.GPIO_Pin = ADCx_2_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(ADCx_2_PORT, &GPIO_InitStructure);		
}

static void ADCx_Mode_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	// 打开DMA时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	 // 打开ADC1时钟
	ADCx_1_APBxClock_FUN ( ADCx_1_CLK, ENABLE );
	 // 打开ADC2时钟
	ADCx_2_APBxClock_FUN ( ADCx_2_CLK, ENABLE );
	
/*....................DMA模式配置............................*/	
	// 复位DMA控制器
	DMA_DeInit(ADC_DMA_CHANNEL);
	
	// 配置 DMA 初始化结构体
	// 外设基址为:ADC 数据寄存器地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADCx_1->DR ) );
	// 存储器地址,实际上就是一个内部SRAM的变量
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue;
	// 数据源来自外设
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	// 缓冲区大小为6,缓冲区的大小应该等于存储器的大小
	DMA_InitStructure.DMA_BufferSize = NOFCHANEL;              
	// 外设寄存器只有一个,地址不用递增
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	// 存储器地址固定
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;    
	// 外设数据大小为半字,即两个字节
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
	// 存储器数据大小也为半字,跟外设数据大小相同
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
	// 循环传输模式
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
  // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	// 禁止存储器到存储器模式,因为是从外设到存储器
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	// 初始化DMA
	DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
	// 使能 DMA 通道
	DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);	
	
/*....................ADC1模式配置............................*/
	//ADC模式配置
	//只是用一个ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
	//开启扫描模式,多通道需要
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;          
	//连续转化模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	//不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	//转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	//转换通道6个
	ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL;
	//初始化ADC
	ADC_Init(ADCx_1, &ADC_InitStructure);
	//配置ADC时钟为CLK的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	// 配置ADC 通道的转换顺序(这里的转换顺序可以随意更改)和采样时间
	ADC_RegularChannelConfig(ADCx_1, ADCx_1_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	
/*....................ADC2模式配置............................*/
	//只是用一个ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
	//开启扫描模式,多通道需要
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;          
	//连续转化模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	//不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	//转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	//转换通道6个
	ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL;
	//初始化ADC
	ADC_Init(ADCx_2, &ADC_InitStructure);
	//配置ADC时钟为CLK的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	// 配置ADC 通道的转换顺序(这里的转换顺序可以随意更改)和采样时间
	ADC_RegularChannelConfig(ADCx_2, ADCx_2_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	
    //使能ADC_DMA请求,只能是ADC1的
	ADC_DMACmd(ADCx_1,ENABLE);
	
/*.....................ADCx_1校准................*/
	//开启ADC,并开始转换
	ADC_Cmd(ADCx_1,ENABLE);
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx_1);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx_1));
	// ADC开始校准
	ADC_StartCalibration(ADCx_1);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx_1));
	
/*....................ADCx_2校准................*/
	//开启ADC,并开始转换
	ADC_Cmd(ADCx_2,ENABLE);
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx_2);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx_2));
	// ADC开始校准
	ADC_StartCalibration(ADCx_2);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx_2));	
	
	
	/* 使能ADCx_2的外部触发转换 */
    ADC_ExternalTrigConvCmd(ADC2, ENABLE);
	//ADCx_1使用软件触发ADC转换
	ADC_SoftwareStartConvCmd(ADCx_1,ENABLE);
}

/**
  * @brief  ADC初始化
  * @param  无
  * @retval 无
  */
void ADCx_Init(void)
{
	ADCx_GPIO_Config();
	ADCx_Mode_Config();
}

main()

#include "stm32f10x.h"    //相当于51单片中的#include <reg51.h>
#include "bsp_led.h"
#include "bsp_usart.h" 
#include "bsp_adc.h" 

extern __IO uint32_t ADC_ConvertedValue[NOFCHANEL];

// 局部变量,用于保存转换计算后的电压值 	 
float ADC_ConvertedValueLocal[NOFCHANEL*2];   

// 软件延时
void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
} 

int main(void)
{
     uint16_t temp0 = 1,temp1 = 0;
	
	 //配置串口
	 USART_Config(); 
	 //ADC初始化
	 ADCx_Init();
	
	 printf("\r\n ----这是一个ADC单通道中断读取实验----\r\n");
	
	while (1)
	{	
    // 取出ADC1数据寄存器的高16位,这个是ADC2的转换数据
		temp0 = (ADC_ConvertedValue[0]&0XFFFF0000) >> 16;
		// 取出ADC1数据寄存器的低16位,这个是ADC1的转换数据
		temp1 = (ADC_ConvertedValue[0]&0XFFFF);	
		
		ADC_ConvertedValueLocal[0] =(float) temp0/4096*3.3;
		ADC_ConvertedValueLocal[1] =(float) temp1/4096*3.3;
		
		printf("\r\n ADCx_1 value = %f V \r\n",ADC_ConvertedValueLocal[1]);
		printf("\r\n ADCx_2 value = %f V \r\n" ,ADC_ConvertedValueLocal[0]);
		
		printf("\r\n\r\n");
		Delay(0xffffee); 
		 
	}
}

在这里插入图片描述
bsp_adc.h

#ifndef __BSP_ADC_H_
#define __BSP_ADC_H_

#include "stm32f10x.h"


// 双模式时,ADC1和ADC2转换的数据都存放在ADC1的数据寄存器,
// ADC1的在低十六位,ADC2的在高十六位
// 双ADC模式的第一个ADC,必须是ADC1
#define    ADCx_1                           ADC1
#define    ADCx_1_APBxClock_FUN             RCC_APB2PeriphClockCmd
#define    ADCx_1_CLK                       RCC_APB2Periph_ADC1

#define    ADCx_1_GPIO_APBxClock_FUN        RCC_APB2PeriphClockCmd
#define    ADCx_1_GPIO_CLK                  RCC_APB2Periph_GPIOC  
#define    ADCx_1_PORT                      GPIOC

#define    ADCx_1_PIN                       GPIO_Pin_1
#define    ADCx_1_CHANNEL                   ADC_Channel_11

#define    ADCx_1_2_PIN                       GPIO_Pin_2
#define    ADCx_1_2_CHANNEL                   ADC_Channel_12

// 双ADC模式的第二个ADC,必须是ADC2
#define    ADCx_2                           ADC2
#define    ADCx_2_APBxClock_FUN             RCC_APB2PeriphClockCmd
#define    ADCx_2_CLK                       RCC_APB2Periph_ADC2

#define    ADCx_2_GPIO_APBxClock_FUN        RCC_APB2PeriphClockCmd
#define    ADCx_2_GPIO_CLK                  RCC_APB2Periph_GPIOC  
#define    ADCx_2_PORT                      GPIOC

#define    ADCx_2_PIN                       GPIO_Pin_4
#define    ADCx_2_CHANNEL                   ADC_Channel_14

#define    ADCx_2_2_PIN                       GPIO_Pin_5
#define    ADCx_2_2_CHANNEL                   ADC_Channel_15

#define    NOFCHANEL                        2

// ADC 通道宏定义
#define    ADC_DMA_CHANNEL                  DMA1_Channel1

void ADCx_Init(void);

#endif

bsp_adc.c

#include "bsp_adc.h"

__IO uint32_t ADC_ConvertedValue[];

static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// ADCx_1 GPIO 初始化
	ADCx_1_GPIO_APBxClock_FUN ( ADCx_1_GPIO_CLK, ENABLE );
	GPIO_InitStructure.GPIO_Pin = ADCx_1_PIN|ADCx_1_2_PIN;    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(ADCx_1_PORT, &GPIO_InitStructure);

	// ADCx_2 GPIO 初始化
	ADCx_1_GPIO_APBxClock_FUN ( ADCx_2_GPIO_CLK, ENABLE );
	GPIO_InitStructure.GPIO_Pin = ADCx_2_PIN|ADCx_2_2_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(ADCx_2_PORT, &GPIO_InitStructure);		
}

static void ADCx_Mode_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	// 打开DMA时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	 // 打开ADC1时钟
	ADCx_1_APBxClock_FUN ( ADCx_1_CLK, ENABLE );
	 // 打开ADC2时钟
	ADCx_2_APBxClock_FUN ( ADCx_2_CLK, ENABLE );
	
	
/*....................DMA模式配置............................*/	
	// 复位DMA控制器
	DMA_DeInit(ADC_DMA_CHANNEL);
	
	// 配置 DMA 初始化结构体
	// 外设基址为:ADC 数据寄存器地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADCx_1->DR ) );
	// 存储器地址,实际上就是一个内部SRAM的变量
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue;
	// 数据源来自外设
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	// 缓冲区大小为6,缓冲区的大小应该等于存储器的大小
	DMA_InitStructure.DMA_BufferSize = NOFCHANEL;              
	// 外设寄存器只有一个,地址不用递增
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	// 存储器地址固定
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    
	// 外设数据大小为半字,即两个字节
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
	// 存储器数据大小也为半字,跟外设数据大小相同
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
	// 循环传输模式
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
  // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	// 禁止存储器到存储器模式,因为是从外设到存储器
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	// 初始化DMA
	DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
	// 使能 DMA 通道
	DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);	
	
	
/*....................ADC1模式配置............................*/
	//ADC模式配置
	//只是用一个ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
	//开启扫描模式,多通道需要
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;          
	//连续转化模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	//不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	//转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	//转换通道6个
	ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL;
	//初始化ADC
	ADC_Init(ADCx_1, &ADC_InitStructure);
	//配置ADC时钟为CLK的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	// 配置ADC 通道的转换顺序(这里的转换顺序可以随意更改)和采样时间
	ADC_RegularChannelConfig(ADCx_1, ADCx_1_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADCx_1, ADCx_1_2_CHANNEL, 2, ADC_SampleTime_55Cycles5);

/*....................ADC2模式配置............................*/
	//只是用一个ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
	//开启扫描模式,多通道需要
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;          
	//连续转化模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	//不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	//转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	//转换通道6个
	ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL;
	//初始化ADC
	ADC_Init(ADCx_2, &ADC_InitStructure);
	//配置ADC时钟为CLK的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	// 配置ADC 通道的转换顺序(这里的转换顺序可以随意更改)和采样时间
	ADC_RegularChannelConfig(ADCx_2, ADCx_2_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADCx_2, ADCx_2_2_CHANNEL, 2, ADC_SampleTime_55Cycles5);
	
  //使能ADC_DMA请求,只能是ADC1的
	ADC_DMACmd(ADCx_1,ENABLE);
	
/*.....................ADCx_1校准................*/
	//开启ADC,并开始转换
	ADC_Cmd(ADCx_1,ENABLE);
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx_1);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx_1));
	// ADC开始校准
	ADC_StartCalibration(ADCx_1);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx_1));
	
/*....................ADCx_2校准................*/
	//开启ADC,并开始转换
	ADC_Cmd(ADCx_2,ENABLE);
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx_2);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx_2));
	// ADC开始校准
	ADC_StartCalibration(ADCx_2);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx_2));	
	
	/* 使能ADCx_2的外部触发转换 */
   ADC_ExternalTrigConvCmd(ADC2, ENABLE);
	//ADCx_1使用软件触发ADC转换
	ADC_SoftwareStartConvCmd(ADCx_1,ENABLE);
}

/**
  * @brief  ADC初始化
  * @param  无
  * @retval 无
  */
void ADCx_Init(void)
{
	ADCx_GPIO_Config();
	ADCx_Mode_Config();
}

mian()

#include "stm32f10x.h"    //相当于51单片中的#include <reg51.h>
#include "bsp_led.h"
#include "bsp_usart.h" 
#include "bsp_adc.h" 


extern __IO uint32_t ADC_ConvertedValue[NOFCHANEL];
// 局部变量,用于保存转换计算后的电压值 	 
float ADC_ConvertedValueLocal[NOFCHANEL*2];   

// 软件延时
void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
} 

int main(void)
{
   uint16_t temp0 = 0,temp1 = 0,temp2 = 0,temp3 = 0;  //存放4个pc1/2/4/5的16位的模拟电压数值
	
	 //配置串口
	 USART_Config(); 
	 //ADC初始化
	 ADCx_Init();
	
	 printf("\r\n ----这是一个ADC单通道中断读取实验----\r\n");
	
	while (1)
	{	/*......ADC1/2传送第一通道的时候,也就是红色线条的时候.......*/
       // 取出ADC1数据寄存器的高16位,这个是ADC2的转换数据
		temp0 = (ADC_ConvertedValue[0]&0XFFFF0000) >> 16;
		// 取出ADC1数据寄存器的低16位,这个是ADC1的转换数据
		temp1 = (ADC_ConvertedValue[0]&0XFFFF);	
		
		/*......ADC1/2传送第二通道的时候,也就是黄色线条的时候.......*/
		// 取出ADC1数据寄存器的高16位,这个是ADC2的转换数据
		temp2 = (ADC_ConvertedValue[1]&0XFFFF0000) >> 16;
		// 取出ADC1数据寄存器的低16位,这个是ADC1的转换数据
		temp3 = (ADC_ConvertedValue[1]&0XFFFF);	
		
		
		ADC_ConvertedValueLocal[0] =(float) temp0/4096*3.3;
		ADC_ConvertedValueLocal[1] =(float) temp1/4096*3.3;
		ADC_ConvertedValueLocal[2] =(float) temp2/4096*3.3;
		ADC_ConvertedValueLocal[3] =(float) temp3/4096*3.3;
		
		printf("\r\n ADCx_1 PC1 value = %f V \r\n",ADC_ConvertedValueLocal[1]);
		printf("\r\n ADCx_1_2 PC2 value = %f V \r\n" ,ADC_ConvertedValueLocal[3]);
		printf("\r\n ADCx_2 PC4 value = %f V \r\n",ADC_ConvertedValueLocal[0]);
		printf("\r\n ADCx_2_2 PC5 value = %f V \r\n" ,ADC_ConvertedValueLocal[2]);
		
		/*....PC1和PC4属于第一批(红色数据)传输,PC2和PC5属于第二批(黄色数据)传输......*/
		
		printf("\r\n\r\n");
		Delay(0xffffee); 
		 
	}
}




  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值