衡水营销型网站建设,hao123上网从这里开始,关键词优化和seo,西安有什么好玩的地方景点推荐基于stm32f103系列 基于《零死角玩转 STM32F103—指南者》
ADC简介
stm32f103上的ADC
数量#xff1a;3 精度:12bit(4096) 通道#xff1a;ADC1#xff0c;ADC2均有16个通道#xff0c;ADC3有8个 功能: 转换结束、注入转换结束和发生模拟看门狗事件时产生中断。 …基于stm32f103系列 基于《零死角玩转 STM32F103—指南者》
ADC简介
stm32f103上的ADC
数量3 精度:12bit(4096) 通道ADC1ADC2均有16个通道ADC3有8个 功能: 转换结束、注入转换结束和发生模拟看门狗事件时产生中断。 单次和连续转换模式 从通道0到通道n的自动扫描模式 自校准 带内嵌数据一致性的数据对齐 采样间隔可以按通道分别编程 规则转换和注入转换均有外部触发选项 间断模式 双重模式(带2个或以上ADC的器件)
输入电压范围 输入通道
根据手册选择输入通道
转换顺序
规则序列
规则序列 从小到大依次转换 配置SQR3、SQR2、SQR1寄存器。按顺序从SQR3中的SQ1SQ2到SQR1中的SQ16
注入序列
注入序列 依据通道数目从大到小或者从小到大 注入序列寄存器 JSQR 只有一个最多支持 4 个通道。具体多少个由 JSQR 的 JL[2:0]决定。如果 JL的 值小于 4 的话则 JSQR 跟 SQR决定转换顺序的设置不一样第一次转换的不是 JSQR1[4:0]而是 JCQRx[4:0] x 4-JL跟 SQR 刚好相反。如果 JL001 个转换那么转换的顺序是从 JSQR4[4:0]开始而不是从 JSQR1[4:0]开始这个要注意编程的时候不要搞错。当 JL 等于 4 时跟 SQR 一样。
触发源
1.CR寄存器中的CONbit位使能开始转换 2.触发启动 内部定时器触发和外部 IO 触发 触发源有很多具体选择哪一种触发源由 ADC 控制寄存器 2:ADC_CR2 的EXTSEL[2:0]和 JEXTSEL[2:0]位来控制。EXTSEL[2:0]用于选择规则通道的触发源JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后触发源是否要激活则由ADC 控制寄存器 2:ADC_CR2 的 EXTTRIG 和 JEXTTRIG 这两位来激活。其中 ADC3 的规则转换和注入转换的触发源与 ADC1/2 的有所不同。
EXTSEL[2:0]和JEXTSEL2:0]控制位允许应用程序选择8个可能的事件中的某一个可以触发规则和注入组的采样。
转换时间
ADC 时钟
ADC 输入时钟 ADC_CLK 由 PCLK2 经过分频产生最大是 14M分频因子由 RCC 时钟配置寄存器 RCC_CFGR 的位 15:14 ADCPRE[1:0]设置可以是 2/4/6/8 分频注意这里没有 1 分频。一般我们设置 PCLK2HCLK72M。
采样时间
ADC 使用若干个 ADC_CLK 周期对输入的电压进行采样采样的周期数可通过 ADC 采样时间寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位设置ADC_SMPR2 控制的是通道 0~9ADC_SMPR1 控制的是通道 10~17。每个通道可以分别用不同的时间采样。其中采样周期最小是 1.5 个即如果我们要达到最快的采样那么应该设置采样周期为 1.5 个周期这里说的周期就是 1/ADC_CLK。
ADC 的转换时间跟 ADC 的输入时钟和采样时间有关公式为Tconv 采样时间 12.5 个周期。当 ADCLK 14MHZ 最高采样时间设置为 1.5 周期最快那么总的转换时间最短Tconv 1.5 周期 12.5 周期 14 周期 1us。
一般我们设置 PCLK272M经过 ADC 预分频器能分频到最大的时钟只能是 12M采样周期设置为 1.5 个周期算出最短的转换时间为 1.17us这个才是最常用的。
数据寄存器 ADC-DR
ADC 转换后的数据根据转换组的不同规则组的数据放在 ADC_DR寄存器注入组的数据放在 JDRx。
规则数据寄存器 ADC_DR寄存器
ADC 规则组数据寄存器 ADC_DR 只有一个是一个 32 位的寄存器低 16 位在单 ADC时使用高 16 位是在 ADC1 中双模式下保存 ADC2 转换的规则数据双模式就是 ADC1 和ADC2 同时使用。
规则通道可以有 16 个这么多可规则数据寄存器只有一个如果使用多通道转换那转换的数据就全部都挤在了 DR 里面前一个时间点转换的通道数据就会被下一个时间点的另外一个通道转换的数据覆盖掉所以当通道转换完成后就应该把数据取走或者开启 DMA 模式把数据传输到内存里面不然就会造成数据的覆盖。最常用的做法就是开启 DMA 传输。
注入数据寄存器 JDRx寄存器
ADC 注入组最多有 4 个通道刚好注入数据寄存器也有 4 个每个通道对应着自己的寄存器不会跟规则寄存器那样产生数据覆盖的问题。ADC_JDRx 是 32 位的低 16 位有效高 16 位保留数据同样分为左对齐和右对齐具体是以哪一种方式存放由ADC_CR2 的 11 位 ALIGN 设置。
中断
转换结束中断
数据转换结束后可以产生中断中断分为三种规则通道转换结束中断注入转换通道转换结束中断模拟看门狗中断。
模拟看门狗中断
当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时就会产生中断前提是我们开启了模拟看门狗中断其中低阈值和高阈值由 ADC_LTR 和 ADC_HTR 设置。例如我们设置高阈值是 2.5V那么模拟电压超过 2.5V的时候就会产生模拟看门狗中断反之低阈值也一样。
DMA请求
规则和注入通道转换结束后除了产生中断外还可以产生 DMA 请求把转换好的数据直接存储在内存里面。要注意的是只有 ADC1 和 ADC3 可以产生 DMA 请求。
编程要点
独立单通道
ADC GPIO 初始化 static void ADCx_GPIO_Config(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2,ENABLE)GPIO_InitStructure.GPIO_Pin GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN;//模拟输入GPIO_Init(GPIOC, GPIO_InitStructure);}ADC 工作模式配置
// ADC 编号选择
// 可以是 ADC1/2如果使用 ADC3中断相关的要改成 ADC3 的
#define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADCx ADC2
#define ADC_CLK RCC_APB2Periph_ADC2// ADC GPIO 宏定义
// 注意用作 ADC 采集的 IO 必须没有复用否则采集电压会有影响
#define ADC_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADC_GPIO_CLK RCC_APB2Periph_GPIOC
#define ADC_PORT GPIOC
#define ADC_PIN GPIO_Pin_1
// ADC 通道宏定义
#define ADC_CHANNEL ADC_Channel_11// ADC 中断相关宏定义
#define ADC_IRQ ADC1_2_IRQn
#define ADC_IRQHandler ADC1_2_IRQHandlerstatic void ADCx_Mode_Config(void)
{ADC_InitTypeDef ADC_InitStructure;// 打开 ADC 时钟ADC_APBxClock_FUN ( ADC_CLK, ENABLE );// ADC 模式配置// 只使用一个 ADC属于独立模式ADC_InitStructure.ADC_Mode ADC_Mode_Independent;// 禁止扫描模式多通道才要单通道不需要ADC_InitStructure.ADC_ScanConvMode DISABLE ;// 连续转换模式ADC_InitStructure.ADC_ContinuousConvMode ENABLE;// 不用外部触发转换软件开启即可ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None;// 转换结果右对齐ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right;// 转换通道 1 个ADC_InitStructure.ADC_NbrOfChannel 1;// 初始化 ADCADC_Init(ADCx, ADC_InitStructure);// 配置 ADC 时钟狿 CLK2 的 8 分频即 9MHzRCC_ADCCLKConfig(RCC_PCLK2_Div8);// 配置 ADC 通道转换顺序为 1第一个转换采样时间为 55.5 个时钟周期ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1,ADC_SampleTime_55Cycles5);// ADC 转换结束产生中断在中断服务程序中读取转换值ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);// 开启 ADC 并开始转换ADC_Cmd(ADCx, ENABLE);// 初始化 ADC 校准寄存器ADC_ResetCalibration(ADCx);// 等待校准寄存器初始化完成while (ADC_GetResetCalibrationStatus(ADCx));// ADC 开始校准ADC_StartCalibration(ADCx);// 等待校准完成while (ADC_GetCalibrationStatus(ADCx));// 由于没有采用外部触发所以使用软件触发 ADC 转换ADC_SoftwareStartConvCmd(ADCx, ENABLE);}ADC 中断配置
NVIC配置
static void ADC_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel ADC_IRQ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStructure);
}开启ADC中断
// ADC 转换结束产生中断在中断服务程序中读取转换值ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);ADC中断服务函数 1.ADC1和ADC2共有一个中断服务函数 2.中断服务函数中读取ADC状态寄存器SR的相应位置
void ADC_IRQHandler(void)
{if (ADC_GetITStatus(ADCx,ADC_IT_EOC)SET) {// 读取 ADC 的转换值ADC_ConvertedValue ADC_GetConversionValue(ADCx);}ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
}独立模式多通道采集
初始化 ADC GPIO初始化 ADC 工作参数配置 DMA 工作参数读取 ADC 采集的数据
GPIO配置
static void ADCx_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 打开 ADC IO 端口时钟ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );// 配置 ADC IO 引脚模式GPIO_InitStructure.GPIO_Pin ADC_PIN1|ADC_PIN2|ADC_PIN3|ADC_PIN4|ADC_PIN5;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN;// 初始化 ADC IOGPIO_Init(ADC_PORT, GPIO_InitStructure);}ADC以及DMA模式配置
static void ADCx_Mode_Config(void)
{DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;// 打开 DMA 时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// 打开 ADC 时钟ADC_APBxClock_FUN ( ADC_CLK, ENABLE );/* ------------------DMA 模式配置---------------- */// 复位 DMA 控制器DMA_DeInit(ADC_DMA_CHANNEL);// 配置 DMA 初始化结构体// 外设基址为ADC 数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr (u32)(( ADCx-DR ));// 存储器地址DMA_InitStructure.DMA_MemoryBaseAddr (u32)ADC_ConvertedValue;// 数据源来自外设DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC;// 缓冲区大小应该等于数据目的地的大小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_HalfWord;// 内存数据大小也为半字跟外设数据大小相同DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord;// 循环传输模式DMA_InitStructure.DMA_Mode DMA_Mode_Circular;// DMA 传输通道优先级为高当使用一个 DMA 通道时优先级设置不影响DMA_InitStructure.DMA_Priority DMA_Priority_High;// 禁止存储器到存储器模式因为是从外设到存储器DMA_InitStructure.DMA_M2M DMA_M2M_Disable;// 初始化 DMADMA_Init(ADC_DMA_CHANNEL, DMA_InitStructure);// 使能 DMA 通道DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);/* ----------------ADC 模式配置--------------------- */// 只使用一个 ADC属于单模式ADC_InitStructure.ADC_Mode ADC_Mode_Independent;// 扫描模式ADC_InitStructure.ADC_ScanConvMode ENABLE ;// 连续转换模式ADC_InitStructure.ADC_ContinuousConvMode ENABLE;// 不用外部触发转换软件开启即可ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None;// 转换结果右对齐ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right;// 转换通道个数ADC_InitStructure.ADC_NbrOfChannel NOFCHANEL;// 初始化 ADCADC_Init(ADCx, ADC_InitStructure);// 配置 ADC 时钟狿 CLK2 的 8 分频即 9MHzRCC_ADCCLKConfig(RCC_PCLK2_Div8);// 配置 ADC 通道的转换顺序和采样时间ADC_RegularChannelConfig(ADCx, ADC_CHANNEL1, 1,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADCx, ADC_CHANNEL2, 2,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADCx, ADC_CHANNEL3, 3,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADCx, ADC_CHANNEL4, 4,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADCx, ADC_CHANNEL5, 5,ADC_SampleTime_55Cycles5);// 使能 ADC DMA 请求ADC_DMACmd(ADCx, ENABLE);// 开启 ADC 并开始转换ADC_Cmd(ADCx, ENABLE);// 初始化 ADC 校准寄存器ADC_ResetCalibration(ADCx);// 等待校准寄存器初始化完成while (ADC_GetResetCalibrationStatus(ADCx));// ADC 开始校准ADC_StartCalibration(ADCx);// 等待校准完成while (ADC_GetCalibrationStatus(ADCx));// 由于没有采用外部触发所以使用软件触发 ADC 转换ADC_SoftwareStartConvCmd(ADCx, ENABLE);}双重 ADC 同步规则模式采集
参看《零死角玩转STM32—F103指南者》