网站站点规划实例,黄山5个最佳景点,公司企业网站搭建,淄博做企业网站哪家好一、ADC介绍
12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道#xff0c;可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
二、框图分析 按照顺序分析#xff1a;…一、ADC介绍
12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
二、框图分析 按照顺序分析
1、电压输入范围ADC 输入范围为VREF- ≤ VIN ≤ VREF。由 VREF-、VREF 、VDDA、 VSSA、这四个外部引脚决定。一般把 VSSA 和 VREF-接地把 VREF和 VDDA 接 3V3得到ADC 的输入电压范围为0~3.3V。 2、输入通道可分为注入通道和规则通道 前者常用。关于输入通道查询可以参考《STM32F103xCDE_数据手册》 下面是总结好的表格F103x 系列 对应的引脚几乎完全一样 下面是ZET6的 3、 转换顺序 规则序列 通过控制ADC规则序列寄存器 ADC_SQR1 、ADC_SQR2、ADC_SQR3 来配置规则通道的转换顺序 如果通道 16 想第一次转换那么在 SQ1[4:0] 写 16 即可。SQR2 控制着规则序列中的第 7 到第12 个转换对应的位为SQ7[4:0]~SQ12[4:0]如果通道 1 想第 8 个转换则 SQ8[4:0] 写 1 即可。SQR1 控制着规则序列中的第 13 到第 16 个转换对应位为SQ13[4:0]~SQ16[4:0]如果通道 6 想第 10 个转换则 SQ10[4:0] 写 6 即可。具体使用多少个通道由 SQR1 的位L[3:0]决定最多 16 个通道。
注入序列 ADC注入序列寄存器ADC_JSQR 。注入序列寄存器 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 一样。 4、触发源选择 通道配置完成转换顺序也已经确定下面就是触发源的选择。通过ADC控制寄存器 1(ADC_CR1)、ADC控制寄存器 2(ADC_CR2)选择触发源 5、转换时间
ADC 时钟 ADC 输入时钟 ADC_CLK 由 PCLK2 经过分频产生最大是 14M分频因子由 RCC 时钟配置寄存器 RCC_CFGR 的位 15:14 ADCPRE[1:0]设置可以是 2/4/6/8 分频一般我们设置 PCLK2HCLK72M。一般选择8分频。
采样时间 采样的周期数可通过 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常用1.17us。
6、数据寄存器一切准备就绪后ADC 转换后的数据根据转换组的不同规则组的数据放在 ADC_DR寄存器注入组的数据放在 JDRx。
规则数据寄存器
注入数据寄存器
7、中断
转换结束中断 数据转换结束后可以产生中断中断分为三种规则通道转换结束中断注入转换通道转换结束中断模拟看门狗中断。可以根据相应的中断标志位编写对应的中断服务函数。事件是否发生可以访问ADC状态寄存器(ADC_SR)
模拟看门狗中断 当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时就会产生中断前提是我们开启了模拟看门狗中断其中低阈值和高阈值由 ADC_LTR 和 ADC_HTR 设置。例如我们设置高阈值是 2.5V那么模拟电压超过 2.5V 的时候就会产生模拟看门狗中断反之低阈值也一样。
三、编程相关
在编程的时候我们只需要配置对用的结构体即可
ADC_InitTypeDef 结构体
typedef struct
{uint32_t ADC_Mode; // ADC 工作模式选择FunctionalState ADC_ScanConvMode; /* ADC 扫描多通道或者单次单通道模式选择 */FunctionalState ADC_ContinuousConvMode; // ADC 单次转换或者连续转换选择uint32_t ADC_ExternalTrigConv; // ADC 转换触发信号选择uint32_t ADC_DataAlign; // ADC 数据寄存器对齐格式uint8_t ADC_NbrOfChannel; // ADC 采集通道数
}ADC_InitTypeDef;ADC_Mode配置 ADC 的模式当使用一个 ADC 时是独立模式使用两个 ADC 时 是双模式在双模式下还有很多细分模式可选。
ScanConvMode可选参数为 ENABLE 和 DISABLE配置是否使用扫描。如果是单通 道 AD 转 换 使 用 DISABLE 如 果 是 多 通 道 AD 转 换 使 用 ENABLE 。
ADC_ContinuousConvMode可选参数为 ENABLE 和 DISABLE配置是启动自动连 续转换还是单次转换。使用 ENABLE 配置为使能自动连续转换使用 DISABLE 配置为单 次转换转换一次后停止需要手动控制才重新启动转换。
ADC_ExternalTrigConv外部触发选择框图中中列举了很多外部触发条件可根据 项目需求配置触发来源。一般使用软件自动触发。
ADC_DataAlign转换结果数据对齐模式可选右对齐 ADC_DataAlign_Right 或者左 对齐 ADC_DataAlign_Left。一般选择右对齐模式。不然读取数据 还得处理。
ADC_NbrOfChannelAD 转换通道数目根据实际设置即可。具体的通道数和通道的 转换顺序是配置规则序列或注入序列寄存器
实例一《中断单通道读取ADC》
编程要点
初始 ADC 用到的 GPIO设置 ADC 的工作参数并初始化设置 ADC 工作时钟设置 ADC 转换通道顺序及采样时间配置使能 ADC 转换完成中断在中断内读取转换完数据使能 ADC使能软件触发 ADC 转换。 ADC 转换结果数据使用中断方式读取这里没有使用 DMA 进行数据传输。
1.初始 ADC 用到的 GPIO
void ADCx_GPIO_Config(void)
{ //以PA1为例GPIO_InitTypeDef GPIO_InitStruct;//开启GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//选择模拟模式GPIO_InitStruct.GPIO_Mode GPIO_Mode_AIN;GPIO_InitStruct.GPIO_Pin GPIO_Pin_1;GPIO_Init(ADCx_GPIO_PORT,GPIO_InitStruct);
}2.配置ADC
void ADCx_Config(void)
{ //ADC1 Channel_1ADC_InitTypeDef ADC_InitStruct;//开启ADC时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);ADC_InitStruct.ADC_Mode ADC_Mode_Independent; // 只使用一个ADC属于单模式ADC_InitStruct.ADC_ScanConvMode DISABLE; //只有一个通道关闭扫描模式ADC_InitStruct.ADC_ContinuousConvMode ENABLE; // 连续转换模式ADC_InitStruct.ADC_ExternalTrigConv ADC_ExternalTrigConv_None;// 不用外部触发转换软件启即可ADC_InitStruct.ADC_DataAlign ADC_DataAlign_Right; // 转换结果右对齐ADC_InitStruct.ADC_NbrOfChannel 1; // 转换通道个数//初始化ADC_Init(ADC1,ADC_InitStruct);//配置ADC时钟狿CLK2的8分频即9MHzRCC_ADCCLKConfig(RCC_PCLK2_Div8);// 配置ADC 通道的转换顺序和采样时间ADC_RegularChannelConfig(ADC1,ADC_1_Channel,1,ADC_SampleTime_55Cycles5);// ADC 转换结束产生中断在中断服务程序中读取转换值ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);// 开启ADC 并开始转换ADC_Cmd(ADC1,ENABLE);ADC_ResetCalibration(ADC1);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC1));// ADC开始校准ADC_StartCalibration(ADC1);// 等待校准完成while(ADC_GetCalibrationStatus(ADC1));// 由于没有采用外部触发所以使用软件触发ADC转换 ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
3.配置NVIC
void ADC_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;// 优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);// 配置中断优先级NVIC_InitStructure.NVIC_IRQChannel ADC1_2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStructure);
}4.编写中断服务函数
void ADC1_2_IRQHandler(void)
{ uint8_t i 0;if (ADC_GetITStatus(ADC_x,ADC_IT_EOC)SET) {//读取ADC的转换值ADC_Convert_Value (float)ADC_GetConversionValue(ADC_x)/4096*3.3;ADC_ClearITPendingBit(ADC_x,ADC_IT_EOC); //清除转换完成标志位等待下一次}
}5.测试函数
uint16_t ADC_USART_Value 0;
uint16_t ADC_USART_Value2 0;
void _ADC_IT_Init(void)
{ADCx_GPIO_Config();ADCx_Config();ADC_NVIC_Config();}
void delay(uint32_t count)
{while(count--);
}
int main(void)
{LED_GPIO_Config();USARTx_Config();ADC_IT_Init();printf(\r\n ----这是一个ADC多通道采集实验----\r\n);while(1){ADC_USART_Value 2(float) ADC_USART_Value ; printf(\r\n The current AD value 0x%04X \r\n, ADC_USART_Value; printf(\r\n The current AD value %f V \r\n,ADC_USART_Value2); printf(\r\n\r\n);delay(0x3fffff);}
}实例二《DMA多通道读取ADC》
编程要点
初始 ADC 用到的 GPIO设置 ADC 的工作参数并初始化设置 ADC 工作时钟设置 ADC 转换通道顺序及采样时间配置使能 ADC 转换完成中断在中断内读取转换完数据使能 ADC使能软件触发 ADC 转换。 这里使用 DMA 进行数据传输还需配置DMA。
有一点需要注意 仅 ADC1 和 ADC3 有DMA传输功能。分别对应 DMA1 的通道 1 DMA2 的通道 5 1.初始 ADC 用到的 GPIO
void ADCx_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(ADCx_GPIO_CLK,ENABLE);GPIO_InitStruct.GPIO_Mode GPIO_Mode_AIN;GPIO_InitStruct.GPIO_Pin ADC_1_Pin|ADC_1_Pin| //ADC_2_Pin和SUART冲突 因此删除ADC_3_Pin|ADC_4_Pin|ADC_5_Pin|ADC_6_Pin|ADC_7_Pin;GPIO_Init(ADCx_GPIO_PORT,GPIO_InitStruct);
}2.初始 DMA
void ADC_DMA_Config(void)
{DMA_InitTypeDef DMA_InitStruct;RCC_AHBPeriphClockCmd(DMA_CLK,ENABLE);//外设基址为ADC 数据寄存器地址DMA_InitStruct.DMA_PeripheralBaseAddr (uint32_t)((ADC_x-DR)); // 存储器地址DMA_InitStruct.DMA_MemoryBaseAddr (uint32_t)ADC_USART_Value; // 数据源来自外设DMA_InitStruct.DMA_DIR DMA_DIR_PeripheralSRC; //缓冲区大小应该等于数据目的地的大小DMA_InitStruct.DMA_BufferSize BUFFERSIZE; // 外设寄存器只有一个地址不用递增 DMA_InitStruct.DMA_PeripheralInc DMA_PeripheralInc_Disable; //存储器地址递增DMA_InitStruct.DMA_MemoryInc DMA_MemoryInc_Enable; //外设数据大小为半字即两个字节 DMA_InitStruct.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; //内存数据大小也为半字跟外设数据大小相同DMA_InitStruct.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord;//循环传输模式DMA_InitStruct.DMA_Mode DMA_Mode_Circular; //DMA传输通道优先级为高当使用一个DMA通道时优先级设置不影响DMA_InitStruct.DMA_Priority DMA_Priority_High;//禁止存储器到存储器模式因为是从外设到存储器DMA_InitStruct.DMA_M2M DMA_M2M_Disable;DMA_Init(DMA_CHANNEL,DMA_InitStruct);DMA_Cmd(DMA_CHANNEL,ENABLE);}3.初始 ADC
void ADCx_Config(void)
{ADC_InitTypeDef ADC_InitStruct;//开启ADC时钟RCC_APB2PeriphClockCmd(ADCx_CLK,ENABLE);ADC_InitStruct.ADC_Mode ADC_Mode_Independent; // 只使用一个ADC属于单模式ADC_InitStruct.ADC_ScanConvMode ENABLE; //6通道开启扫描ADC_InitStruct.ADC_ContinuousConvMode ENABLE;// 连续转换模式ADC_InitStruct.ADC_ExternalTrigConv ADC_ExternalTrigConv_None;// 不用外部触发转换软件开启即可ADC_InitStruct.ADC_DataAlign ADC_DataAlign_Right; // 转换结果右对齐ADC_InitStruct.ADC_NbrOfChannel ADC_num; // 转换通道个数//初始化ADC_Init(ADC_x,ADC_InitStruct);//配置ADC时钟狿CLK2的8分频即9MHzRCC_ADCCLKConfig(RCC_PCLK2_Div8);// 配置ADC 通道的转换顺序和采样时间ADC_RegularChannelConfig(ADC_x,ADC_1_Channel,1,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC_x,ADC_4_Channel,2,ADC_SampleTime_55Cycles5); //A2 A3用于串口ADC_RegularChannelConfig(ADC_x,ADC_5_Channel,3,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC_x,ADC_6_Channel,4,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC_x,ADC_7_Channel,5,ADC_SampleTime_55Cycles5);// 使能ADC DMA 请求ADC_DMACmd(ADC_x, ENABLE);// 开启ADC 并开始转换ADC_Cmd(ADC_x,ENABLE);ADC_ResetCalibration(ADC_x);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC_x));// ADC开始校准ADC_StartCalibration(ADC_x);// 等待校准完成while(ADC_GetCalibrationStatus(ADC_x));// 由于没有采用外部触发所以使用软件触发ADC转换 ADC_SoftwareStartConvCmd(ADC_x,ENABLE);
}void ADCx_DMA_Init(void)
{ADCx_GPIO_Config();ADC_DMA_Config();ADCx_Config();
}4.测试函数
void delay(uint32_t count)
{while(count--);
}int main(void)
{LED_GPIO_Config();USARTx_Config();ADCx_DMA_Init();//ADC_IT_Init();printf(\r\n ----这是一个ADC多通道采集实验----\r\n);while(1){printf(\r PA1 value %f V \r\n,(float)ADC_USART_Value[0]/4096*3.3);printf(\r PA4 value %f V \r\n,(float)ADC_USART_Value[1]/4096*3.3);printf(\r PA5 value %f V \r\n,(float)ADC_USART_Value[2]/4096*3.3);printf(\r PA6 value %f V \r\n,(float)ADC_USART_Value[3]/4096*3.3);printf(\r PA7 value %f V \r\n\n\n\n\n,(float)ADC_USART_Value[4]/4096*3.3);delay(0x3fffff);}
}头文件 #include “bsp_dma.h”
#ifndef _BSP_DMA_H_
#define _BSP_DMA_H_#include stm32f10x.h#define BUFFERSIZE 5
#define DMA_CHANNEL DMA1_Channel1 //手册
#define DMA_CLK RCC_AHBPeriph_DMA1void ADC_DMA_Config(void);#endif /*_BSP_DMA_H_*/#include “bsp_adc.h”
#ifndef _BSP_ADC_H_
#define _BSP_ADC_H_
#include stm32f10x.h#define ADC_num 5#define ADC_x ADC1
#define ADCx_CLK RCC_APB2Periph_ADC1#define ADCx_GPIO_PORT GPIOA
#define ADCx_GPIO_CLK RCC_APB2Periph_GPIOA#define ADC_1_Pin GPIO_Pin_1
#define ADC_2_Pin GPIO_Pin_2
#define ADC_3_Pin GPIO_Pin_3
#define ADC_4_Pin GPIO_Pin_4
#define ADC_5_Pin GPIO_Pin_5
#define ADC_6_Pin GPIO_Pin_6
#define ADC_7_Pin GPIO_Pin_7#define ADC_1_Channel ADC_Channel_1
#define ADC_2_Channel ADC_Channel_2
#define ADC_3_Channel ADC_Channel_3
#define ADC_4_Channel ADC_Channel_4
#define ADC_5_Channel ADC_Channel_5
#define ADC_6_Channel ADC_Channel_6
#define ADC_7_Channel ADC_Channel_7extern uint16_t ADC_USART_Value[ADC_num];
extern float ADC_Convert_Value[ADC_num];void ADCx_GPIO_Config(void);
void ADCx_Config(void);
void ADC_DMA_Config(void);
void ADCx_DMA_Init(void);#endif /*_BSP_ADC_H_*/
欢迎交流探讨大家一起进步吧冲冲冲