这里使用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);
}
}