cortex_m3_stm32嵌入式学习笔记(十六):ADC实验(模数转换)

之前没学过数模电,对A/D D/A转换一窍不通,也百度了很多资料大都深奥难懂。。算了,先自以为是一下吧,等以后学了专业课再说。。(寒假回家一定要学。。恩 就这么决定了)看了那么多资料,感觉 A/D转换就是将电压(或者是其他模拟量:如 压力,图像等)转换为数字,D/A就是反过来,而ADC就是A/D转换器,他可以采集外部电压转化为数字。本节实验通过ADC采集外部电压转换为数字显示在屏幕上。


STM32 拥有 1~3 个 ADC( STM32F101/102 系列只有 1 个 ADC),这些 ADC 可以独立使用,也可以使用双重模式(提高采样率)。 STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。 ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。


STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。


通过一个形象的例子可以说明: 假如你在家里的院子内放了 5 个温度探头,室内放了3个温度探头; 你需要时刻监视室外温度即可,但偶尔你想看看室内的温度;因此你可以使用规则通道组循环扫描室外的 5 个探头并显示 AD 转换结果,当你想看室内温度时,通过一个按钮启动注入转换组(3 个室内探头)并暂时显示室内温度,当你放开这个按钮后,系统又会回到规则通道组继续检测室外温度。从系统设计上,测量并显示室内温度的过程中断了测量并显示室外温度的过程,但程序设计上可以在初始化阶段分别设置好不同的转换组,系统运行中不必再变更循环转换的配置,从而达到两个任务互不干扰和快速切换的结果。可以设想一下,如果没有规则组和注入组的划分,当你按下按钮后,需要从新配置 AD 循环扫描的通道,然后在释放按钮后需再次配置 AD 循环扫描的通道。

但本节只用到规则通道,因为是单次转换模式。。大概可以理解为我们现在只测量一个地方的电压值。。

配置ADC步骤如下:

1) 开启 PA 口和 ADC1 时钟,设置 PA1 为模拟输入。
STM32F103RCT6 的 ADC 通道 1 在 PA1 上,所以,我们先要使能 PORTA 的时钟,然后设置 PA1 为模拟输入。 使能 GPIOA 和 ADC 时钟用 RCC_APB2PeriphClockCmd 函数,设置 PA1的输入方式,使用 GPIO_Init 函数即可。这里我们列出 STM32 的 ADC 通道与 GPIO 对应表:

   
2)复位 ADC1,同时设置 ADC1 分频因子。
3)初始化 ADC1 参数,设置 ADC1 的工作模式以及规则序列的相关信息。
4)使能 ADC 并校准。
5)读取 ADC 值。

配置ADC的文件adc.c


#include "adc.h"
void Adc_Init(void)
{
	ADC_InitTypeDef ADC_ist;
	GPIO_InitTypeDef GPIO_ist;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE );
	//72M/6=12,ADC 最大时间不能超过 14M
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置 ADC分频因子6
	//PA1 作为模拟通道输入引脚
	GPIO_ist.GPIO_Pin=GPIO_Pin_1;
	GPIO_ist.GPIO_Mode=GPIO_Mode_AIN;//模拟输入
	GPIO_Init(GPIOA,&GPIO_ist);
	
	ADC_DeInit(ADC1);//复位 ADC1,将外设 ADC1 的全部寄存器重设为缺省值
	ADC_ist.ADC_Mode= ADC_Mode_Independent;//ADC 独立模式
	ADC_ist.ADC_ScanConvMode=DISABLE;//单通道模式
	ADC_ist.ADC_ContinuousConvMode=DISABLE;//单次转换模式
	//转换由软件而不是外部触发启动
	ADC_ist.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
	ADC_ist.ADC_DataAlign=ADC_DataAlign_Right;//ADC 数据右对齐
	ADC_ist.ADC_NbrOfChannel=1;//顺序进行规则转换的 ADC 通道的数目
	ADC_Init(ADC1,&ADC_ist);
	
	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); 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的 ADC1 的软件转换功能
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换结束
	return ADC_GetConversionValue(ADC1);//返回最近一次 ADC1 规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 tem_val=0;
	u8 i;
	for(i=0;i<times;i++)
	{
		tem_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return tem_val/times;
}


adc.h
#ifndef _ADC_H
#define _ADC_H
#include "sys.h"
#include "delay.h"
void Adc_Init(void);
u16 Get_Adc(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);
#endif

主函数
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
void init()
{
	delay_init();	    	 //延时函数初始化	  
	uart_init(9600);	 	//串口初始化为9600
	LED_Init();		  		//初始化与LED连接的硬件接口
 	LCD_Init();
	Adc_Init();
	POINT_COLOR=RED;//设置字体为红色
	LCD_ShowString(60,40,200,24,24,"ADC Test ^-^");
	LCD_ShowString(60,70,200,16,16,"Medium difficulty");
	LCD_ShowString(60,90,200,16,16,"2015/1/24");
	LCD_ShowString(60,110,200,16,16,"By--Mr yh");
	//显示提示信息
	POINT_COLOR=BLUE;//设置字体为蓝色
	LCD_ShowString(60,130,200,16,16,"ADC_CH0_VAL:"); 
	LCD_ShowString(60,150,200,16,16,"ADC_CH0_VOL:0.000V");
}
int main(void)
{
	u16 adcnum;
	float tem;
	init();
	while(1)
	{
		adcnum=Get_Adc_Average(ADC_Channel_1,10);
		LCD_ShowxNum(156,130,adcnum,4,16,0);//显示ADC的值
		tem=(float)adcnum*(3.3/4096);
		adcnum=tem;
		LCD_ShowxNum(156,150,adcnum,1,16,0);//显示电压值的整数位
		tem-=adcnum;
		tem*=1000;
		LCD_ShowxNum(172,150,tem,3,16,0x80);//显示ADC的值的小数位
		LED0=!LED0;
		delay_ms(250);
	}
}


获得了ADC的值之后。。 再转换成电压值的公式就看不懂了。。orz

不过有一个地方需要注意 LCD_ShowxNum()的用法

再次翻出它的源码

//显示数字,高位为0,还是显示
//x,y:起点坐标
//num:数值(0~999999999);	 
//len:长度(即要显示的位数)
//size:字体大小
//mode:
//[7]:0,不填充;1,填充0.
//[6:1]:保留
//[0]:0,非叠加显示;1,叠加显示.
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
{  
	u8 t,temp;
	u8 enshow=0;						   
	for(t=0;t<len;t++)
	{
		temp=(num/LCD_Pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				if(mode&0X80)LCD_ShowChar(x+(size/2)*t,y,'0',size,mode&0X01);  
				else LCD_ShowChar(x+(size/2)*t,y,' ',size,mode&0X01);  
 				continue;
			}else enshow=1; 
		 	 
		}
	 	LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,mode&0X01); 
	}
} 
看到最后一个参数的说明, mode 是一个8位的变量,第7位为0代表不填充,1代表填充。

一开始对填充这个概念没什么理解,于是将两种结果(填充和不填充)烧进去看了一下,发现显示0.001 的时候,如果选不填充,它会显示0.  1(点和1之间有2个空格),如果是填充就会显示0.001 (正常显示)所以我对填充的理解是:假如一个数6, 你想显示006,那么需要设置数的长度为3,填充模式



  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于ARM Cortex-M3STM32嵌入式系统是一种高性能、低功耗的嵌入式系统,可广泛应用于各种领域。它的工作原理是基于ARM Cortex-M3内核的芯片,该内核具有较强的计算能力和多重存储器接口。STM32系列芯片结合了低功耗、高性能和丰富的外设功能,能够满足不同的应用需求。 STM32嵌入式系统的应用十分广泛。首先,它可以应用于工业自动化控制领域。通过与各种传感器和执行器的连接,STM32可以实现对温度、湿度、压力等各种参数的实时监测和控制。其低功耗特性也使其适合在长时间运行的智能仪表和机械设备中使用。 其次,STM32嵌入式系统可应用于物联网设备。通过内置的无线通信模块,如Wi-Fi、蓝牙和LoRa等,STM32可以与其他设备进行无线通信,并实现数据的传输和远程控制,适用于智能家居、智能城市等场景。 此外,STM32还可以应用于消费电子产品领域。其丰富的外设接口可以与LCD显示屏、摄像头、音频设备等进行连接,从而实现手机、平板电脑和音频播放器等产品的功能。 总体来说,基于ARM Cortex-M3STM32嵌入式系统具有高性能、低功耗、丰富的外设接口等特点,可以广泛应用于工业自动化、物联网设备和消费电子等众多领域,为各类产品提供强大的计算和控制能力。 ### 回答2: 基于ARM Cortex-M3STM32嵌入式系统是一种高性能、低功耗的解决方案。STM32系列微控制器基于ARM Cortex-M3内核,具有丰富的外设和功能,适用于各种嵌入式应用。 STM32嵌入式系统原理是基于ARM Cortex-M3内核的运行机制。ARM Cortex-M3是一种32位的低功耗处理器,具有较高的性能和灵活性。STM32通过在芯片上集成了丰富的外设模块(例如通用输入输出、串行通信接口、模数转换器等)以及存储器和时钟管理模块,实现了完整的嵌入式系统功能。 嵌入式系统应用方面,STM32可广泛应用于工控、家电、汽车电子、医疗设备等领域。在工控领域,STM32可用于控制和监测生产过程,实现智能化管理。在家电领域,STM32可用于控制空调、洗衣机等家电设备,提高其性能和用户体验。在汽车电子领域,STM32可用于车载娱乐、导航和车身控制等系统。在医疗设备领域,STM32可用于监测和控制医疗设备,提高诊断和治疗效果。 STM32的优点包括低功耗、高性能、丰富的外设、易于开发和灵活的应用性。低功耗使得STM32在电池供电或移动设备应用中非常适用。高性能和丰富的外设让STM32能够处理复杂的任务和连接多种外部设备。易于开发的特性使得开发者能够快速上手并进行系统开发。灵活的应用性使得STM32能够应对不同的应用需求和系统架构。 总之,基于ARM Cortex-M3STM32嵌入式系统以其优异的性能和丰富的外设被广泛应用于各种嵌入式系统领域,为各种应用提供了高效、低功耗的解决方案。 ### 回答3: STM32是意法半导体公司推出的一种基于ARM Cortex-M3内核的嵌入式系统。它采用了先进的芯片设计和先进的嵌入式开发技术,具有高性能、低功耗和丰富的外设接口等特点。 基于ARM Cortex-M3STM32嵌入式系统原理主要包括以下几个方面: 1. ARM Cortex-M3内核:ARM Cortex-M3是一种高性能、低功耗的32位处理器内核。它具有高性能的运算能力和丰富的指令集,能够处理复杂的计算任务。 2. 外设接口:STM32嵌入式系统提供了丰富的外设接口,包括多个GPIO引脚、UART、SPI、I2C、ADC等。这些外设接口可与外部设备进行通信,实现数据的输入和输出。 3. 存储器:STM32嵌入式系统具有不同类型的存储器,包括闪存、RAM和EEPROM。闪存用于存储程序代码和数据,RAM用于临时数据存储,EEPROM用于非易失性数据存储。 4. 中断系统:STM32嵌入式系统具有强大的中断系统,可实现多任务并发执行。通过中断系统,可以及时响应外部事件,并执行相应的任务。 基于ARM Cortex-M3STM32嵌入式系统应用广泛,主要包括以下几个方面: 1. 工业控制:STM32可以广泛应用于工业自动化领域,用于控制和调节各种设备和系统,如PLC、人机界面等。 2. 智能家居:STM32可以用于智能家居控制系统,实现对家居设备的远程控制和管理,如智能灯光、安防系统等。 3. 汽车电子:STM32可以应用于汽车电子领域,用于发动机控制、车载娱乐系统、导航系统等。 4. 医疗设备:STM32可以应用于医疗设备,如医疗监护仪、心电图仪等,实现对患者的监测和治疗。 总之,基于ARM Cortex-M3STM32嵌入式系统具有高性能、低功耗和丰富的外设接口等特点,广泛应用于各个行业的嵌入式系统开发。它为开发者提供了强大的功能和丰富的接口选项,可以满足不同领域的需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值