当前位置: 代码网 > 科技>人工智能>物联网 > STM32编写ADC功能,实现单路测量电压值(OLED显示)

STM32编写ADC功能,实现单路测量电压值(OLED显示)

2024年08月01日 物联网 我要评论
是否启用间隔模式 void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);ADC获取双模式转换值,这个是双ADC模式读取转换结果 void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);第五步:打开ADC_CMD()开启ADC。

先来看看本次实验的结果吧:stm32点电压测量范围为0-3.3v,数值为:0-4095

来看看这个工程的文件布局吧:

实现adc功能总共分为六步:

第一步:开始rcc时钟,包括adc和gpio的时钟,adcclk的分频器也需要配置一下。

第二步:配置gpio,把需要用的gpio配置成模拟输入的模式

第三步:配置多路开关,把左边的通道接入规则组列表里

第四步:配置adc转换器,用结构体配置,一大块的参数。

第五步:打开adc_cmd()开启adc。

第六步:校准adc

接着来学习一下adc相关的库函数:(看起来好像有点乱,后面有截图)

void rcc_adcclkconfig(uint32_t rcc_pclk2); 用来配置adcclk分频器的 void adc_cmd(adc_typedef* adcx, functionalstate newstate); 这个是用来给adc上电的函数 void adc_dmacmd(adc_typedef* adcx, functionalstate newstate); 用来开启dma输出信号的 void adc_itconfig(adc_typedef* adcx, uint16_t adc_it, functionalstate newstate); 中断输出控制 void adc_resetcalibration(adc_typedef* adcx); 复位校准 flagstatus adc_getresetcalibrationstatus(adc_typedef* adcx); 获取复位校准状态 void adc_startcalibration(adc_typedef* adcx); 开始校准 flagstatus adc_getcalibrationstatus(adc_typedef* adcx); 获取开始校准状态 void adc_softwarestartconvcmd(adc_typedef* adcx, functionalstate newstate); adc软件开始转换控制 软件触发的函数 flagstatus adc_getsoftwarestartconvstatus(adc_typedef* adcx); adc获取软件开始转换状态 flagstatus adc_getflagstatus(adc_typedef* adcx, uint8_t adc_flag); 获取转换完成标志位状态,判断eoc标志位是不是置1了。 void adc_discmodechannelcountconfig(adc_typedef* adcx, uint8_t number); 间隔几个通道采集信

void adc_discmodecmd(adc_typedef* adcx, functionalstate newstate); 是否启用间隔模式 void adc_regularchannelconfig(adc_typedef* adcx, uint8_t adc_channel, uint8_t rank, uint8_t adc_sampletime); 规则组通道配置 void adc_externaltrigconvcmd(adc_typedef* adcx, functionalstate newstate); adc 外部触发转换控制,就是是否允许外部触发转换 uint16_t adc_getconversionvalue(adc_typedef* adcx); adc获取转换值 uint32_t adc_getdualmodeconversionvalue(void); adc获取双模式转换值,这个是双adc模式读取转换结果 void adc_analogwatchdogcmd(adc_typedef* adcx, uint32_t adc_analogwatchdog);  //是否启动看门口 void adc_analogwatchdogthresholdsconfig(adc_typedef* adcx, uint16_t highthreshold, uint16_t lowthreshold); //配置高低阈值 void adc_analogwatchdogsinglechannelconfig(adc_typedef* adcx, uint8_t adc_channel); //配置看门的通道 配置模拟看门狗的三个函数 void adc_tempsensorvrefintcmd(functionalstate newstate);  //adc温度传感器内部参考电压控制,用来开启内部通道 flagstatus adc_getflagstatus(adc_typedef* adcx, uint8_t adc_flag);  //获取标志位状态 void adc_clearflag(adc_typedef* adcx, uint8_t adc_flag);        // 清楚标志位状态 itstatus adc_getitstatus(adc_typedef* adcx, uint16_t adc_it);     //获取中断状态 void adc_clearitpendingbit(adc_typedef* adcx, uint16_t adc_it);   //清楚中断挂起位

接下来就是每个文件的源码了:

myadc.c文件:

#include "stm32f10x.h"                  // device header


void myadc_init(void)
	
{
	//第一步:开始rcc时钟,包括adc和gpio的时钟,adcclk的分频器也需要配置一下。
	rcc_apb2periphclockcmd(rcc_apb2periph_adc1, enable);   //开启adc1的时钟
	rcc_apb2periphclockcmd(rcc_apb2periph_gpioa, enable);  //开启gpioa的时钟
	
	rcc_adcclkconfig(rcc_pclk2_div6);      // adc的时钟选择6分频,也就是72m/6=12m
	
	//第二步:配置gpio,把需要用的gpio配置成模拟输入的模式
	gpio_inittypedef gpio_initstruct;    //gpio初始化的结构体
	gpio_initstruct.gpio_mode = gpio_mode_ain;  // 模式为模拟输入
	gpio_initstruct.gpio_pin = gpio_pin_0;       // 初始化端口0
	gpio_initstruct.gpio_speed = gpio_speed_50mhz;  //端口频率50m
	gpio_init(gpioa, &gpio_initstruct);           // gpioa初始化
	
	//第三步:配置多路开关,把左边的通道接入规则组列表里
	adc_regularchannelconfig(adc1, adc_channel_0, 1, adc_sampletime_28cycles5); //adc1规则配置(adc1,通道1,列表1,转换时间28.5个时钟(12m))
	
	//第四步:配置adc转换器,用结构体配置,一大块的参数。
	adc_inittypedef adc_initstruct;                    //adc初始化结构体
	adc_initstruct.adc_continuousconvmode = disable;            //连续转换模式:关闭
	adc_initstruct.adc_dataalign = adc_dataalign_right;            // 数据对齐:右对齐
	adc_initstruct.adc_externaltrigconv = adc_externaltrigconv_none;   //adc中断触发:空,也就是软件触发
	adc_initstruct.adc_mode = adc_mode_independent;               // adc模式:独立模式
	adc_initstruct.adc_nbrofchannel = 1;                   //规则组中的通道数:1
	adc_initstruct.adc_scanconvmode = disable;             //扫描模式:关闭
	adc_init(adc1, &adc_initstruct);                    //adc初始化
	//第五步:打开adc_cmd()开启adc。
	adc_cmd(adc1, enable);                        // adc开启
	//第六步:校准adc
	adc_resetcalibration(adc1);                        // 复位校准adc
	while(adc_getresetcalibrationstatus(adc1) == set);    // 等待校准标志位置0
	adc_startcalibration(adc1);                         // 开始复位校准adc
	while(adc_getcalibrationstatus(adc1) == set);          // 等待开始校准结束标志位置0
	
}

uint16_t get_val(void)
{
	adc_softwarestartconvcmd(adc1, enable);                  // 软件触发adc使能
	while(adc_getflagstatus(adc1, adc_flag_eoc) == reset);   // 等待获取eoc标志位置1
	return adc_getconversionvalue(adc1);                    // 返回adc转换的结果值

}

myadc.h文件:

#ifndef __myadc_h
#define __myadc_h


void myadc_init(void);

uint16_t get_val(void);


#endif

主函数main.c文件:

#include "stm32f10x.h"                  // device header
#include "delay.h"
#include "oled.h"
#include "ad.h"

uint16_t advalue;			//定义ad值变量
float voltage;				//定义电压变量

int main(void)
{
	/*模块初始化*/
	oled_init();			//oled初始化
	ad_init();				//ad初始化
	
	/*显示静态字符串*/
	oled_showstring(1, 1, "advalue:");
	oled_showstring(2, 1, "voltage:0.00v");
	
	while (1)
	{
		advalue = ad_getvalue();					//获取ad转换的值
		voltage = (float)advalue / 4095 * 3.3;		//将ad值线性变换到0~3.3的范围,表示电压
		
		oled_shownum(1, 9, advalue, 4);				//显示ad值
		oled_shownum(2, 9, voltage, 1);				//显示电压值的整数部分
		oled_shownum(2, 11, (uint16_t)(voltage * 100) % 100, 2);	//显示电压值的小数部分
		
		delay_ms(100);			//延时100ms,手动增加一些转换的间隔时间
	}
}

还有一个oled的代码就不展示了,没有的可以在之前的博文中找到,都有公布过,自己挨片的看就能找到的,编译后写入到stm32中就能看到实验结果了,调整电位器就能看到电压和数值的变化,电位器中间抽头接a0,另外两个头中的一个接3.3v电源,这就是整个的接线图了。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com