嵌入式设计与开发项目-ADC应用程序设计(解决多通道冲突问题)

嵌入式设计与开发项目-ADC应用程序设计(解决多通道冲突问题),第1张

嵌入式设计与开发项目-ADC应用程序设计
  • 一、实现的功能
  • 二、根据功能实现代码
    • 1、主文件main.c
    • 2、ADC头文件“adc.h”
    • 3、ADC源文件“adc.c”
  • 三、实现功能过程的注意与学习点
    • 1、注意点
    • 2、学习的知识点

一、实现的功能

ADC有18个转换通道,其中通道0~通道15是外部通道,使用的GPIO如下图:
ADC1的通道16与内部的温度传感器相连(推荐采样17.1us),通道17与参考电源VREFINT 相连,使用ADC_TempSensorVrefintCmd()使能。

  • ①通过LED1 ~ LED8显示0 ~ 255的数据,每隔1s增加1;
  • ②每隔1s获取一次内部温度AD值和通道8外接电位器的AD值,并将其AD值和电压值打印到串口上面;
  • ③把内部温度的AD值转化为温室值;
    串口效果图:
二、根据功能实现代码 1、主文件main.c
#include"key.h"
#include"led.h"
#include"lcd.h"
#include "usart.h"
#include "i2c.h"
#include "adc.h"

unsigned int uiAdc_Val;
unsigned char ucSec,ucSec1;
unsigned char pucStr[21];
unsigned long ulTick_ms;

void ADC_Proc(void);

int main(void)
{
	SysTick_Config(72000);	//定时1ms(HCLK = 72MHz)
	KEY_Init();
	LED_Init();
	
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	USART2_Init(9600);
	i2c_init();
	ADC1_Init();
	
	sprintf((char *)pucStr,"	ADC DEMO");
	printf("%s\r\n",pucStr);
		
	while(1)
	 {
		LED_Disp(ucSec);
		ADC_Proc();
	 }
	}
	
	void ADC_Proc(void)
	{
		float fAdc_Val;
		if(ucSec != ucSec1)
		{
			ucSec1 = ucSec;
			
			uiAdc_Val = ADC1_Conv();
			fAdc_Val = (float)uiAdc_Val*3.3/4095;
			sprintf((char *)pucStr,"	%04u %5.2f",uiAdc_Val,fAdc_Val);
			printf("%s",pucStr);
			
			uiAdc_Val = ADC1_InjeConv();
			fAdc_Val = (float)25+(5855.85-3.3*uiAdc_Val)/17.6085;
			sprintf((char *)pucStr,"	%04u %5.2f",uiAdc_Val,fAdc_Val);
			LCD_DisplayStringLine(Line6,pucStr);
			printf("%s\r\n",pucStr);
		}
	}
//SysTick 中断处理程序
	void SysTick_Handler(void)
	{
		ulTick_ms++;
		if(ulTick_ms % 1000 ==0)
		ucSec++;
		
	}
	

主函数分析:❤️ ❤️ ❤️

  1. 通过ucSec1和ucSec变量判断是否相等,判断上一次的状态是否与现在不同,从而实现1s采集一次ADC值;
  2. ADC值与电压的转化关系(分辨率为12,参考电压为3.3v),采集的电压 = 采集的ADC值 / 4095(212-1) * 3.3;
  3. %04u 表示用4位数字表示uiAdc_Val,如果不够4位往前面补0,%5.2f 表示用5位数并包含2位小数表示fAdc_Val;
  4. 通道16所连内部温度的计算,芯片内部温度 = 25 + (5855.85 - 3.3 * ADC值) / 17.6085;
2、ADC头文件“adc.h”
#include"stm32f10x.h"

void ADC1_Init(void);
unsigned int ADC1_Conv(void);
unsigned int ADC1_InjeConv(void);

简要分析:❤️ ❤️

  1. 包含通道8对于的引脚PB0和通道16以及ADC1的初始化;
  2. 转换通道使用规则通道返回的ADC值;
  3. 转换通道使用注入通道返回的ADC值;
3、ADC源文件“adc.c”
#include"adc.h"
void ADC1_Init(void)
{
	//初始化结构体
	GPIO_InitTypeDef GPIO_InitStruct;
	ADC_InitTypeDef ADC_InitStruct;
	
	//允许GPIOB和ADC1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	
	//PB0-IN8模拟输入
	GPIO_InitStruct.GPIO_Pin =GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AIN;
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	//初始化ADC1
	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;		//独立工作模式
	ADC_InitStruct.ADC_ScanConvMode =DISABLE;		//非扫描模式,采集多通道才使能
	ADC_InitStruct.ADC_ContinuousConvMode =DISABLE;		//关闭连续转换 
	ADC_InitStruct.ADC_ExternalTrigConv =ADC_ExternalTrigConv_None;		//禁止触发检测,使用软件触发 
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;		//右对齐
	ADC_InitStruct.ADC_NbrOfChannel = 1;		//顺序进行规则转换的ADC通道的数目(根据ADC采集通道数量修改)
	ADC_Init(ADC1,&ADC_InitStruct);		//ADC1初始化
	
	//配置通道8
	ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1,
	ADC_SampleTime_1Cycles5);		//设置指定 ADC 的规则组通道8,一个序列,采样时间1.5个周期
	//配置通道16
	ADC_InjectedChannelConfig(ADC1, ADC_Channel_16, 1,
	ADC_SampleTime_239Cycles5);		//设置指定 ADC 的注入组通道16,一个序列,采样时间239.5个周期
	
	ADC_TempSensorVrefintCmd(ENABLE);	//使能内部通道	
	ADC_AutoInjectedConvCmd(ADC1,ENABLE);  //用于使能或失能规则通道组转换结束后自动的注入通道组转换
	
	//启动ADC1
	ADC_Cmd(ADC1,ENABLE);
	//校准ADC1
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));		//等待校准结束
}

unsigned int ADC1_Conv(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);		//使能指定的ADC1的软件转换启动功能
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
			return ADC_GetConversionValue(ADC1);
}

unsigned int ADC1_InjeConv(void)
{
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_JEOC));
			return ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);
}

简要分析:❤️ ❤️

  1. 通道8所对应的PB0的GPIO初始化顺序:①初始化GPIO结构体 → ②使能GPIOB对应的APB2时钟 → ③配置引脚、模拟输入模式 → ④初始化GPIO的结构体;
  2. 配置ADC1的顺序:①初始化ADC结构体 → ②使能ADC1对应的APB2时钟 → ③配置工作模式、(禁止)使能扫描模式、(禁止)使能连续转换模式、不使用外部中断触发、向右对齐、ADC转换通道一个 → ④初始化ADC1的结构体 → ⑤配置通道的采样顺序与周期 → ⑥使能规则和注入通道 → ⑦启动ADC1 → ⑧进行ADC的校准;
  3. 获取规则通道ADC值unsigned int ADC1_Conv(void),先启动ADC1的软件转换功能,然后检测是否获取到ADC的标志位,最后**ADC_GetConversionValue()**获取规则通道的值;
  4. 获取注入通道ADC值unsigned int ADC1_InjeConv(void),先启动ADC1的软件转换功能,然后检测是否获取到ADC1的标志位,清除标志位,最后通过**ADC_GetInjectedConversionValue()**返回标志位;
三、实现功能过程的注意与学习点 1、注意点

1、同一个ADC进行多个规则通道采集,会产生串联干扰,可分别设置规则通道和注入通道进行ADC采集,解决多通道采集干扰问题;
2、配置ADC参数可根据实际需求进行配置,可灵活更换一些参数;

2、学习的知识点
  1. 规则通道由最多16个通道组成,按顺序转换,使用ADC_RegularChannelConfig()进行配置,使用ADC_GetConversionValue()获取转换值;
  2. 注入通道由最多4个通道组成,可插入转换,使用ADC_InjectedChannelConfig()进行配置,使用ADC_GetInjectedConversionValue()获取转换值
  3. ADC通道配置的一个主要参数是采样时间,采样时间通过采用周期数进行配置,两者的关系是 : ` `` 采样时间 = (采样周期数 + 12.5) / fADCCLK (ADC时钟频率)
  4. 默认状态下,ADCCLK为36MHz,改变规则通道8会引起内部通道16的波动,是因为采样时间有问题,RCC_ADCCLKConfig(RCC_PCLK2_Div6)设置ADCCLK为12MHz温度基本保持稳定。


    ❤️ ❤️ ❤️ ❤️ ❤️ ❤️

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/674353.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-19
下一篇 2022-04-19

发表评论

登录后才能评论

评论列表(0条)

保存