STM32 ADC输入采集电压

#include "stm32f10x.h"                  // Device header
#include "stdio.h"
#include "delay.h"




/*********************串口调试输出**********************/

void led()//led PE5初始化
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_InitStruct);
}
void CUSART_init()//串口初始化函数
{
	GPIO_InitTypeDef GPIO_InitStruct;//GPIO结构体
	USART_InitTypeDef USART_InitStruct;//USART结构体
	NVIC_InitTypeDef NVIC_InitStruct;//中断结构体
	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;//设置RX,TX端口串口使能
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;//设置端口浮空输入
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;//设置RX,TX端口串口使能
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	USART_InitStruct.USART_BaudRate=9600;//波特率
	USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流设置
	USART_InitStruct.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;//设置串口模式
	USART_InitStruct.USART_Parity=USART_Parity_No;//不使用奇偶校验
	USART_InitStruct.USART_StopBits=USART_StopBits_1;//设置停止位 1
	USART_InitStruct.USART_WordLength=USART_WordLength_8b;//传输或接受传输数据位
	
	USART_Init(USART1,&USART_InitStruct);
	
	USART_Cmd(USART1,ENABLE);//使能串口
	
 
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断 	
	
	
	NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStruct);
}
 
 
 
#define USAERT_REC_LEN 200
unsigned char USART_RX_BUF[USAERT_REC_LEN]; //接受缓冲
unsigned int USART_RX_STA =0; //接受状态标志位
 
  
/*
USART_RX_STA 定义为一个 16进制的标志位
接收到 0x8000 为 1000 0000 0000 0000 最高位(第15位)接收到1,表示接受完成
接收到 0x4000 同上第14位接收到1,表示接受到0x0d
0d 表示回车
oa 表示换行
以0d,0a结尾表示接收完成
注意:蓝牙和STM32的波特率必须一致
如需使用蓝牙app与MCU通信将TX接到RX
*/
void USART1_IRQHandler()//串口一中断服务函数
{
	unsigned char res;  //将接受的数据存放data
	if(USART_GetITStatus(USART1,USART_IT_RXNE)!= RESET)//接受的数据以0x0d,0x0a结尾
	{
		res=USART_ReceiveData(USART1);//读取接受数据
		if((USART_RX_STA&0x8000)==0)//接受未完成
		{
			if(USART_RX_STA&0x4000)//接收到0x0d
			{
				if(res != 0x0a)//如果未接受到0x0a
				{
					USART_RX_STA=0;
				}
				else
				{
					USART_RX_STA|=0x8000;//接收完成 
				}
			}
			else//如果未接受到0x0d
			{
				if(res==0x0d)//接收到了
				{
					USART_RX_STA|=0x4000;
				}
				else
				{
					USART_RX_BUF[USART_RX_STA&0x3ffff]=res;// 0011 1111 1111 1111,储存数据个数
					USART_RX_STA++;//接受到的有效数据个数+1 
					GPIO_SetBits(GPIOE,GPIO_Pin_6);//关闭led
					if(res== 0x45)//HC-05接收到0x45这个数据
					{
						GPIO_SetBits(GPIOE,GPIO_Pin_5);//关闭led
	
					}
					if(USART_RX_STA>(USAERT_REC_LEN-1))//接收数据出错,重新开始接受
					{
						USART_RX_STA=0;
					}
				}
			}
		}
		
	
			USART_SendData(USART1,res);//将储存的数据发送出去
	}
	
} 
 

// 发送数据

int fputc(int ch, FILE *f)

{

USART_SendData(USART1, (unsigned char) ch);// USART1 可以换成 USART2 等

while (!(USART1->SR & USART_FLAG_TXE));

return (ch);

}

// 接收数据

int GetKey (void) {

while (!(USART1->SR & USART_FLAG_RXNE));

return ((int)(USART1->DR & 0x1FF));

}









/****************************ADC转换********************************************/
void Adc_cfg()
{
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );	  //使能ADC1通道时钟
 

	

	//PA1 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
	
	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_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能
}

//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
  	//设置指定ADC的规则组通道,一个序列,采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,采样时间为239.5周期	  			    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}


u16 Count_AdcVal(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;;
}


int main()
{
	 float  temp;
	u16 value;
	Adc_cfg();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	CUSART_init();
	led();
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);											
	
	printf("Set OK!\n");
	while(1)
	{
		Delay_ms(500);
		value=Count_AdcVal(ADC_Channel_1,20);
		temp=(float)value * 3.3/4096;
		printf("%2.2f\t",temp);
		Delay_ms(500);
	}
	
}
 

接线:ADC1电压采集端口PA1

坑:程序无问题,如遇到PA1接GND不为0V,只需将Verf接至3.3V,作为芯片的外部参考基准输入。把这两者连接,就是使用Vref作为参考基准

Verf:Vref就是指输入的模拟电压的最大值, 用于比较输入电压, ADC的输入的有效范围:0-Vref, 如果是10bit ADC,Vref=5v, 2^10(1024):5v, 那么ADC的分辨率为5/1024=0.00488v

  • 5
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
STM32中,ADC可以用来读取模拟电压值。以下是一个简单的示例程序,演示如何使用STM32ADC读取电压值: ``` #include "stm32f10x.h" void adc_init(void) { //使能ADC1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //设置ADC1输入通道为ADC1通道16(PC0) ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5); //使能ADC1 ADC_Cmd(ADC1, ENABLE); //校准ADC1 ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); } u16 adc_get_value(void) { //启动ADC转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //等待转换完成 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //返回转换值 return ADC_GetConversionValue(ADC1); } float adc_get_voltage(void) { //读取ADC转换值 u16 adc_value = adc_get_value(); //计算电压值 float voltage = (float)adc_value * 3.3 / 4096; return voltage; } int main(void) { //初始化ADC adc_init(); while(1) { //读取电压值 float voltage = adc_get_voltage(); //等待一段时间 for(int i=0; i<1000000; i++); } } ``` 在上面的代码中,我们首先需要初始化ADC,然后使用adc_get_voltage()函数读取电压值。注意,上面的代码中假设使用的是ADC1通道10,如果需要使用其他通道,请修改ADC_RegularChannelConfig()函数的参数。另外,上面的代码中假设使用的是3.3V电压参考,如果使用其他电压参考,请修改adc_get_voltage()函数中的计算公式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃瓜的亚瑟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值