- 0 实现结果说明
- 1 视频
- 2 ADC的基本原理
- 2.1 ADC的特点
- 2.2 STM32F40x系列ADC外部通道和引脚对应关系
- 2.3 ADC引脚
- 2.4 STM32通道组
- 2.5 单次转化VS 连续转换
- 2.6 扫描模式
- 3 ADC相关的寄存器
- 3.1 ADC_CR1控制寄存器1
- 3.2 ADC_CR2寄存器
- 3.3 ADC_SMPR1/2寄存器
- 3.4 ADC_SQR1/SQR2/SQR3规则序列寄存器
- 3.5 ADC_JSQR注入系列寄存器
- 4 ADC的采样时间
- 5 ADC函数说明
- 5.1 ADC通用初始化函数ADC_CommonInit
- 5.2 ADC初始化函数ADC_Init
- 5.3 ADC使能函数 ADC_Cmd();
- 5.4 ADC使能软件转换函数 ADC_SoftwareStartConvCmd
- 5.5 ADC 获取转换结果函数ADC_GetConversionValue
- 6 设置ADC的步骤:
- 7 具体实现代码:
- 8 ADC模数转换项目文件下载
STM32F407ZG的adc模数转换,采集modbus模块的模拟量,把采集的数据通过串口通信发到串口小助手。每次采集的时候,led都会闪一下。
1 视频https://www.bilibili.com/video/BV1uB4y1y78H/
STM32F407adc模数转换,采集modbus模块的模拟量,把采集的数据通过串口通信发到串口小助手。每次采集的时候,led都会闪一下。
2 ADC的基本原理ADC是Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
- 规则通道组:相当正常运行的程序。最多16个通道。规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则组转换的总数应写入ADC_SQR1寄存器的L[3:0]中
- 注入通道组:相当于中断。最多4个通道。注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组里转化的总数应写入ADC_JSQR寄存器的L[1:0]中。
- 如图
STM32F4的ADC的各通道可以单次,连续,扫描
或者间断模式执行。
在扫描模式下,由ADC_SQRx或者ADC_JSQRx寄存器选中的通道被转换。如果设置了EOCIE或者JEOCIE为0,在最后一个通道转换完毕后才会产生EOC或者JEOC中断。
结构体里面的成员 : ADC_ScanConvMode
STM官方定义
STM官方定义
最小采样时间0.42us(ADC时钟=36MHz,采样周期为3周期下得到)
void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
typedef struct
{
uint32_t ADC_Mode;//多重ADC模式选择
uint32_t ADC_Prescaler; //ADC预分频
uint32_t ADC_DMAAccessMode; //DMA访问模式
uint32_t ADC_TwoSamplingDelay; //2个采样阶段之间的延迟
}ADC_CommonInitTypeDef;
这些参数用来配置ADC_CCR寄存器的相关参数
例:
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
ADC_CommonInit(&ADC_CommonInitStructure);
5.2 ADC初始化函数ADC_Init
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
typedef struct
{
uint32_t ADC_Resolution;//ADC分辨率
FunctionalState ADC_ScanConvMode; //是否使用扫描模式。ADC_CR1位8:SCAN位
FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换:ADC_CR2的位1:CONT
uint32_t ADC_ExternalTrigConvEdge; //外部触发使能方式:ADC_CR2的位29:28,EXTEN
uint32_t ADC_ExternalTrigConv; //触发方式:ADC_CR2的位[19:17] :EXTSEL[2:0]
uint32_t ADC_DataAlign; //对齐方式:左对齐还是右对齐:ADC_CR2的位11:ALIGN
uint8_t ADC_NbrOfChannel;//规则通道序列长度:ADC_SQR1的位[23:20]: L[3:0]
}ADC_InitTypeDef;
例:
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中
ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
5.3 ADC使能函数 ADC_Cmd();
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
例:
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
5.4 ADC使能软件转换函数 ADC_SoftwareStartConvCmd
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
例:
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1的软件转换启动
5.5 ADC 获取转换结果函数ADC_GetConversionValue
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
例:
ADC_GetConversionValue(ADC1);//获取ADC1转换结果
6 设置ADC的步骤:
- 开启PA口时钟和ADC1时钟,设置PA1为模拟输入。
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
GPIO_Init(); - 复位ADC1,同时设置ADC1分频因子。
ADC_DeInit(ADC1); - 初始化ADC_CCR寄存器。
ADC_CommonInit(); - 初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); - 使能ADC。
ADC_Cmd(ADC1, ENABLE); - 配置规则通道参数:
ADC_RegularChannelConfig(); - 开启软件转换:ADC_SoftwareStartConvCmd(ADC1);
- 等待转换完成,读取ADC值。
ADC_GetConversionValue(ADC1);
adc.h
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#define ADC_CH5 5 //通道 5
void Adc_Init(void); //ADC 初始化
u16 Get_Adc(u8 ch); //获得某个通道值
u16 Get_Adc_Average(u8 ch,u8 times);//得到某个通道给定次数采样的平均值
#endif
adc.c
#include "adc.h"
#include "sys.h"
#include "delay.h"
void Adc_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStruct;
ADC_InitTypeDef ADC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//使能ADC1时钟
//ADC1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //GPIOA5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA5
//adc复位
ADC_DeInit();
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE); //ADC1复位
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE); //复位结束
ADC_CommonInitStruct.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;//DMA失能
ADC_CommonInitStruct.ADC_Mode=ADC_Mode_Independent; //独立模式
ADC_CommonInitStruct.ADC_Prescaler=ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz
ADC_CommonInitStruct.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟
ADC_CommonInit(&ADC_CommonInitStruct); //初始化
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1
ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
ADC_Cmd(ADC1, ENABLE);//开启AD转换器
}
//获得ADC值
//ch: @ref ADC_channels
//通道值 0~16取值范围为:ADC_Channel_0~ADC_Channel_16
//返回值:转换结果
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles);//ADC1,ADC通道,480个周期,提高采样时间可以提高精确度
ADC_SoftwareStartConv(ADC1); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
//获取通道ch的转换值,取times次,然后平均
//ch:通道编号
//times:获取次数
//返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u8 ch, u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val +=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
main.c
#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "r232.h"
#include "adc.h"
#include "led.h"
void USART2_IRQHandler(void);
//中断处理函数
void USART2_IRQHandler(void)
{
u16 adcx;
u8 res;
if (USART_GetFlagStatus(USART2, USART_FLAG_PE) != RESET)
{
USART_ReceiveData(USART2);
USART_ClearFlag(USART2, USART_FLAG_PE);
}
if (USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET)
{
USART_ReceiveData(USART2);
USART_ClearFlag(USART2, USART_FLAG_ORE);
}
if (USART_GetFlagStatus(USART2, USART_FLAG_FE) != RESET)
{
USART_ReceiveData(USART2);
USART_ClearFlag(USART2, USART_FLAG_FE);
}
if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET )
{
GPIO_ResetBits(GPIOF,GPIO_Pin_13);
adcx=Get_Adc_Average(ADC_Channel_5,30);//获取通道5的转换值,30次取平均
USART_SendData(USART2,adcx);
GPIO_ResetBits(GPIOF,GPIO_Pin_14);
delay_ms(250);
USART_ClearFlag(USART2,USART_IT_RXNE);
}
GPIO_SetBits(GPIOF, GPIO_Pin_14 );
}
int main(void)
{
//配置中断优先分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(50);
LED_Init();
My_USART2_Init();
Adc_Init();
while(1)
{
}
}
8 ADC模数转换项目文件下载
https://download.csdn.net/download/qq_50808730/85574161
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)