正点原子STM32F103学习笔记(十一)

您所在的位置:网站首页 dac工作原理 正点原子STM32F103学习笔记(十一)

正点原子STM32F103学习笔记(十一)

2023-08-10 14:28| 来源: 网络整理| 查看: 265

ADC(Analog-to-Digital Converter) STM32F10x ADC特点 12位(位数决定精度)逐次逼近型的模拟数字转换器。最多带3个ADC控制器(每个控制器有多个通道)最多支持18个通道,可最多测量16个外部和2个内部信号源。支持单次和连续转换模式转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。通道0到通道n的自动扫描模式自动校准采样间隔可以按通道编程规则通道和注入通道均有外部触发选项转换结果支持左对齐或右对齐方式存储在16位数据寄存器ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到。)ADC供电要求:2.4V-3.6V(通常0-3.3)ADC输入范围: V R E F ≤ V I N ≤ V 0 R E F + V_{REF}≤ V_{IN} ≤ V_{0REF+} VREF​≤VIN​≤V0REF+​ STM32F10x系列芯片ADC通道和引脚对应关系

在这里插入图片描述

ADC引脚

在这里插入图片描述

模拟参考负极: 一般接地GND 模拟参考正极: 接VDDA 模拟电源: 接数字电源 模拟电源地: 接数字电源地 模拟输入信号: 不可超过模拟参考正极

STM32通道组 规则通道组: 相当正常运行的程序。最多16个通道。 规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则组转换的总数应写入ADC_SQR1寄存器的L[3:0]中注入通道组: 相当于中断。 最多4个通道。 注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组里转化的总数应写入ADC_JSQR寄存器的L[1:0]中 在这里插入图片描述 单次转化&连续转换

在这里插入图片描述

在这里插入图片描述

ADC时钟配置

不要让ADC时钟超过14MHz,否则可能不准。

RCC_ADCCLKConfig(RCC_PCLK2_Div6); 扫描模式在最后一个通道转换结束才会产生中断 ADC的采样时间

在这里插入图片描述

最小转换时间1us(ADC时钟=14MHz,采样周期为1.5周期下得到)

常用库函数 void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);//初始化函数 void ADC_DeInit(ADC_TypeDef* ADCx) void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);//使能函数 void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);//中断配置函数 void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//软件其中转换 void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);//配置规则通道 uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); //下面两个是校准代码,直接复制即可 void ADC_ResetCalibration(ADC_TypeDef* ADCx); FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx); void ADC_StartCalibration(ADC_TypeDef* ADCx); FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx); ADC初始化函数ADC_Init void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); typedef struct { uint32_t ADC_Mode;//ADC模式:配置ADC_CR1寄存器的位[19:16] :DUALMODE[3:0]位 FunctionalState ADC_ScanConvMode; //是否使用扫描模式。ADC_CR1位8:SCAN位 FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换:ADC_CR2的位1:CONT 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_Mode = ADC_Mode_Independent;//独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //不开启扫描 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//单次转换模式,一个通道不需要开启 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发软件 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1;//顺序进行规则转换的ADC通道的数目 ADC_Init(ADC1, &ADC_InitStructure); ADC使能函数 ADC_Cmd(); void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 ADC使能软件转换函数 ADC_SoftwareStartConvCmd

不使用外部触发可以使用软件转换

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1的软件转换启动 ADC 规则通道配置函数ADC_RegularChannelConfig void ADC_RegularChannelConfig(ADC_TypeDef* ADCx,uint8_t ADC_Channel,uint8_t Rank, uint8_t ADC_SampleTime); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1,ADC_SampleTime_239Cycles5 ); //ADC1的通道1在规则序列里的第一个转换,单通道单词转换 ADC 获取转换结果函数ADC_GetConversionValue uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); ADC_GetConversionValue(ADC1);//获取ADC1转换结果 实验

实验目的: ADC1的通道1(PA1)进行单次转化

开启PA口时钟和ADC1时钟,设置PA1为模拟输入。 GPIO_Init(); APB2PeriphClockCmd(); 复位ADC1,同时设置ADC1分频因子。 RCC_ADCCLKConfig(RCC_PCLK2_Div6); ADC_DeInit(ADC1); 初始化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.c #include "adc.h" #include "delay.h" //初始化ADC //这里我们仅以规则通道为例 //我们默认将开启通道0~3 void Adc_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; //PA1 作为模拟通道输入引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚 GPIO_InitStructure.GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); //使能GPIO1,ADC1通道时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC时钟,设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值 //初始化ADC参数 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //扫描模式(是否连续转换)模数转换工作在单次转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发设置,转换由软件而不是外部触发启动 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目 ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 //校准,直接复制就行 ADC_ResetCalibration(ADC1); //使能复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束 ADC_StartCalibration(ADC1); //开启AD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束 } //获得ADC值 //ch:通道值 0~3 u16 Get_Adc(u8 ch) { //设置指定ADC的规则组通道,一个序列,采样时间 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //配置规则通道参数ADC1,ADC通道为ch,在规则序列中第一个转换,采样时间为239.5周期 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开启(使能)指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束,EOC转换结束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果 } u16 Get_Adc_Average(u8 ch,u8 times) { u32 temp_val=0; u8 t; for(t=0;tPA4或者DAC_OUT2->PA5引脚)。 在这里插入图片描述

在这里插入图片描述

输出电压计算

在这里插入图片描述

12位 0-4095

步骤 开启 PA 口时钟,设置 PA4 为模拟输入。 RCC_APB2PeriphClockCmd(RCC_APB2Per iph_GPIOA, ENABLE ); 使能 PORTA 时钟 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 模拟输入 使能 DAC1 时钟。 RCC_APB1PeriphClockCmd(RCC_APB1Peri ph_DAC, ENABLE ); 使能 DAC 通道时钟 初始化 DAC, 设置 DAC 的工作模式。 void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct) typedef struct { uint32_t DAC_Trigger; //是否外部触发 uint32_t DAC_WaveGeneration; //三角波形生成 uint32_t DAC_LFSRUnmask_TriangleAmplitude;//噪声波三角波生成 uint32_t DAC_OutputBuffer;//设置输出缓存控制位,不使用输出缓存, }DAC_InitTypeDef 使能 DAC 转换通道 DAC_Cmd(DAC_Channel_1, ENABLE); // 使能 DAC1 设置 DAC 的输出值。 DAC_SetChannel1Data(DAC_Align_12b_R, 0);//输出0 DAC_ GetDataOutputValue(DAC_Channel_1);//获取输出值 程序 { GPIO_InitTypeDef GPIO_InitStructure; DAC_InitTypeDef DAC_InitType; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_4) ;//PA.4 输出高 DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0 DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生 DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置 DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1 DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1 DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1 DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值 } //设置通道1输出电压 //vol:0~3300,代表0~3.3V void Dac1_Set_Vol(u16 vol) { float temp=vol; temp/=1000; temp=temp*4096/3.3; DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值 }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3