STM32F407-ADC(模数转换)

一、硬件

STM32F407开发板,杜邦线。

通过通道获取板载电压的模拟输入信号转变为数字信号,并通过转换变成电压。

STM32F407有3个ADC,每个ADC有16个通道,下表为ADC通道对应的引脚,使用哪个通道就用杜邦线将对应的引脚与模拟输入连接起来。

通道号

ADC1

ADC2

ADC3

通道0

PA0

PA0

PA0

通道1

PA1

PA1

PA1

通道2

PA2

PA2

PA2

通道3

PA3

PA3

PA3

通道4

PA4

PA4

PF6

通道5

PA5

PA5

PF7

通道6

PA6

PA6

PF8

通道7

PA7

PA7

PF9

通道8

PB0

PB0

PF10

通道9

PB1

PB1

PF3

通道10

PC0

PC0

PC0

通道11

PC1

PC1

PC1

通道12

PC2

PC2

PC2

通道13

PC3

PC3

PC3

通道14

PC4

PC4

PF4

通道15

PC5

PC5

PF5

二、整体流程 

① 开启PA时钟和ADC1时钟,设置PA1为模拟输入。

RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);      

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);        

GPIO_Init();  

对于IO初始化要注意的是这里采用的模式为模拟输入模式:

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

② 复位ADC1: 

ADC_DeInit();

③ 初始化ADC_CCR寄存器。    

 ADC_CommonInit();

该函数传入参数为实例化的结构体,有四个参数分别是ADC模式,预分频系数,延迟周期,DMA访问模式。其中为了保证ADC时钟的准确性,最小采样时间0.42us(ADC时钟=36MHz,采样周期为3周期下得到),要挑选合适的预分频系数保证时钟小于36MHz,延迟周期越大采样延迟越高。

④初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。      

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);

其中的 ADC_Resolution选择了12位,因为寄存器为16位,放不满,所以还要设置它的对齐方式。只用到了一个通道,因此转换规则序列为1。

⑤ 使能ADC。         

ADC_Cmd(ADC1, ENABLE);

⑥配置规则通道参数:    

 ADC_RegularChannelConfig();

⑦开启软件转换:ADC_SoftwareStartConvCmd(ADC1);

⑧ 等待转换完成,读取ADC值。    

用while判断转换是否完成,调取ADC_GetFlagStatus可以知道当前转换的状态。

最后返回ADC_GetConversionValue(ADC1)的值。

在主函数只需对读取到的数值进行相应的转换输出即可。

三、源码

ADC部分

#include "adc.h"
#include "sys.h"
#include "delay.h"

void Adc_Init(void) 				//ADC通道初始化
{
	
	GPIO_InitTypeDef  GPIO_InitStructure;
	ADC_CommonInitTypeDef ADC_CommonInitStruct;
	ADC_InitTypeDef ADC_InitStruct;
	
	RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	ADC_DeInit();//ADC复位
	
	ADC_CommonInitStruct.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;
	ADC_CommonInitStruct.ADC_Mode=ADC_Mode_Independent;
	ADC_CommonInitStruct.ADC_Prescaler=ADC_Prescaler_Div4;
	ADC_CommonInitStruct.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
	
	ADC_CommonInit(&ADC_CommonInitStruct);


	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;
	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
	ADC_InitStruct.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;
	ADC_InitStruct.ADC_NbrOfConversion=1;
	ADC_InitStruct.ADC_Resolution=ADC_Resolution_12b;
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;
	
	ADC_Init(ADC1, &ADC_InitStruct);

ADC_Cmd(ADC1, ENABLE);



}


u16  Get_Adc(u8 ch) 				//获得某个通道值 
{
	
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles );			    
  
	ADC_SoftwareStartConv(ADC1);	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));

	return ADC_GetConversionValue(ADC1);
	
	
}


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函数

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "adc.h"



int main(void)
{ 
 	u16 adcx;
	float temp;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);    //初始化延时函数
	uart_init(115200);	//初始化串口波特率为115200
	LED_Init();					//初始化LED 
 	LCD_Init();         //初始化LCD接口
	Adc_Init();         //初始化ADC
	POINT_COLOR=RED; 
	LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");	
	LCD_ShowString(30,70,200,16,16,"ADC TEST");	
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2014/5/6");	  
	POINT_COLOR=BLUE;//设置字体为蓝色
	LCD_ShowString(30,130,200,16,16,"ADC1_CH5_VAL:");	      
	LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VOL:0.000V");	//先在固定位置显示小数点      
	while(1)
	{ 
		adcx=Get_Adc_Average(ADC_Channel_5,20);//获取通道5的转换值,20次取平均
		LCD_ShowxNum(134,130,adcx,4,16,0);    //显示ADCC采样后的原始值
		temp=(float)adcx*(3.3/4096);          //获取计算后的带小数的实际电压值,比如3.1111
		adcx=temp;                            //赋值整数部分给adcx变量,因为adcx为u16整形
		LCD_ShowxNum(134,150,adcx,1,16,0);    //显示电压值的整数部分,3.1111的话,这里就是显示3
		temp-=adcx;                           //把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111
		temp*=1000;                           //小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。
		LCD_ShowxNum(150,150,temp,3,16,0X80); //显示小数部分(前面转换为了整形显示),这里显示的就是111.
		LED0=!LED0;
		delay_ms(250);	
	}
}



  • 7
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值