目录
内部温度传感器与参照电压
传感器
光敏电阻
热敏电阻
反射式红外
对射式红外
驱动代码
Sensor.h
Sensor.c
AD.h
AD.c
main.c
内部温度传感器与参照电压
STM32有一个内部的温度传感器,可以用来测量CPU及周围的温度。
该温度传感器在内部和ADCx_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值。
支持的温度范围为:-40~125度。精度比较差,为±1.5℃左右。
内部温度传感器更适合于检测温度的变化,而不是测量绝对温度。如果需要测量绝对温度,应该使用一个外部温度传感器。
我们要使用STM32的内部温度传感器,必须先激活ADC的内部通道,这里通过ADC_CR2的TSVREFE位(bit23)设置。设置该位为1则启用内部温度传感器和参照电压。
ADC_TempSensorVrefintCmd(ENABLE);
温度传感器输出电压随温度线性变化,计算公式如下:
T(℃)={(V25-Vsense)/Avg_Slope}+25
上式中:
V25=Vsense在25度时的数值(典型值为:1.43V)。
Avg_Slope=温度与Vsense曲线的平均斜率(单位为mv/℃或uv/℃)(典型值为4.3mv/℃)
内部温度传感器温度和电压关系图
获取温度步骤
传感器
电位器
蓝白电位器是一种可调电阻器,通过旋转它的旋钮,可以调节电阻器的阻值,从而改变输出电压。
传感器模块:传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出
从左到右依次为:光敏传感器,热敏传感器,对射式红外传感器,反射式红外传感器
对射式红外传感器模拟引脚输出无效,而且没有电位器
工作电压:DC3.3-5V,GND与单片机共地
本节将电位器,光敏传感器,热敏传感器,反射式红外传感器接入ADC对应的通道,传感器的数字输出比较简单就不写代码了
硬件电路
这个电压比较器LM393,其实就是是运算放大器
光敏电阻
产品特性
光敏传感器是利用光敏元件将光信号转换为电信号的传感器,一般用来检测周围环境的光线的亮度,触发单片机或继电器模块等。使用宽电压LM393比较器,信号干净,波形好,驱动能力强,超过15mA。配可调电位器可调节检测光线亮度。设有固定螺栓孔M3,方便安装
控制方法
当环境光线亮度达不到设定值时,DO端输出高电平,当外界环境光线亮度超过设定阈值时,DO端输出低电平。检测亮度可以通过电位器进行调节,顺时针调电位器,检测亮度增加;逆时针调电位器,检测亮度减少。
光敏二极管也叫光电二极管。光敏二极管与半导体二极管在结构上是类似的,其管芯是一个具有光敏特征的PN结,具有单向导电性,因此工作时需加上反向电压。无光照时,有很小的饱和反向漏电流,即暗电流,此时光敏二极管截止。当受到光照时,饱和反向漏电流大大增加,形成光电流,它随入射光强度的变化而变化。当光线照射PN结时,可以使PN结中产生电子一空穴对,使少数载流子的密度增加。这些载流子在反向电压下漂移,使反向电流增加。因此可以利用光照强弱来改变电路中的电流。
简而言之:照射光敏二极管的光强不同,通过光敏二极管的电流大小就不同,所以可以通过检测电流大小,达到检测光强的目的。 利用这个电流变化,我们串接一个电阻,就可以转换成电压的变化,从而通过ADC读取电压值,判断外部光线的强弱。
光线越强,电压越低,光线越暗,电压越高。
热敏电阻
产品特性
热敏电阻模块对环境温度很敏感,一般用来检测周围环境的温度,采用NTC热敏电阻传感器,温度检测范围为20-80摄氏度。传感器特设M3固定安装孔,调节方向与固定方便易用,使用宽电压LM393比较器,信号干净,波形好,驱动能力强,超过15mA,配可调精密电位器调节灵敏度。
控制方法
通过对电位器的调节,可以改变温度检测的阀值(即控制温度值),如需要控制环境温度为50度时:模块则在相应环境温度调到其绿灯亮,DO则输出低电平,低于此设定温度值时,输出高电平,绿灯不亮
模块数字量输出DO可以与单片机直接相连,通过单片机来检测高低电平,由此来检测环境的温度改变;小板数字量输出DO可以直接驱动继电器模块,由此可以组成一个温控开关,控制相关设备的工作温度,也可以接风扇用来散热等;小板模拟量输出 AO 可以和 AD 模块相连,通过 AD 转换,可以获得环境温度更精准的数值。
反射式红外
采用TCRT5000红外反射传感器,一种集发射与接收于一体的光电传感器,它由一个红外发光二极管和个NPN红外光电三极管组成。检测反射距离1-25mm适用,传感器特设M3固定安装孔,调节方向与固定方便易用,使用宽电压LM393比较器,信号干净,波形好,驱动能力强,超过15mA。
控制方法
接好VCC和GND,模块电源指示灯会亮,TCRT5000传感器的红外发射二极管不断发射红外线,当发射出的红外线没有被反射回来或被反射回来但强度不够大时,红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态;被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮。DO输出接口可以与单片机IO口直接相连,一般接外部中断。模拟输出AO当发射管的红外信号经反射被接收管接收后,接收管的电阻会发生变化,在电路上一般以电压的变化形式体现出来,而经过ADC转换或LM324等电路整形后得到处理后的输出结果。电阻的变化起取于接收管所接收的红外信号强度,常表现在反射面的颜色(反射率)、形状和反射面接收管的距离等方面。
应用案例
可以应用于机器人避障、机器人进行白线或者黑线的跟踪,可以检测白底中的黑线,也可以检测黑底中的白线,是寻线机器的必备传感器。流水线计件、电度表脉冲数据采样、传真机碎纸机纸张检测等众多场合。
对射式红外
产品特性
使用ITR9606高灵敏度槽型光耦器件,它由一个红外发光二极管和一个NPN光电三极管组成,槽宽度为传感器特设M3固定安装孔,调节方向与固定方便易用,使用宽电压LM393比较器,信号干净,波形好,驱动能力强,超过15mA。
应用案例
广泛用于电机转速检测,脉冲计数,位置限位等。
控制方法
接好VCC和GND,模块电源指示灯会亮,模块槽中无遮挡时,接收管导通,模块DO输出低电平,开关指示灯亮;遮挡时,DO输出高电平,开关指示灯灭。模块DO可与继电器相连,组成限位开关等功能,也可以与有源蜂鸣器模块相连,组成报警器。DO输出接口可以与单片机IO口直接相连,一般接外部中断,检测传感器是否有遮档,如用电机码盘则可检测电机的转速。
数字开关量DO输出(0和1),模拟输出A0引脚无效
驱动代码
Sensor.h
#ifndef _SENSOR_H_
#define _SENSOR_H_
void Sensor_Init(void);
#endif
Sensor.c
#include "stm32f10x.h" // Device header
void Sensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
AD.h
#ifndef __AD_H
#define __AD_H
void AD_Init(void);
uint16_t AD_GetValue(uint8_t ADC_Channel);
#endif
AD.c
#include "stm32f10x.h" // Device header
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
ADC_TempSensorVrefintCmd(ENABLE); //开启内部温度传感器和参照电压ADC通道
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//模式,选择独立模式,即单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不用硬件触发,软件触发
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//连续转换,失能,每转换一次规则组序列后停止
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描模式,失能,只转换规则组的序列1这一个位置
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);//使能ADC1,ADC开始运行
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/**
* 函 数:获取AD转换的值
* 参 数:ADC_Channel 指定AD转换的通道,范围:ADC_Channel_x,其中x可以是0/1/2
* 返 回 值:AD转换的值,范围:0~4095
*/
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_239Cycles5);//在每次转换前,根据函数形参灵活更改规则组的通道1
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发AD转换一次
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待EOC标志位,即等待AD转换结束
return ADC_GetConversionValue(ADC1);//读数据寄存器,得到AD转换的结果
}
main.c
根据需要将模拟量映射到你指定的范围。比如0~3.3,0~100.
数据抖动比较大可以多次测量求平均数滤波。相邻两次测量可加少许延时如:5ms
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "AD.h"
#include "Sensor.h"
#include "Serial.h"
uint16_t Value;
float Voltage;
float temp;
int main(void)
{
Serial_Init();
AD_Init();
Sensor_Init();
while (1)
{
printf("\r\n******************START*****************\r\n");
Value = AD_GetValue(ADC_Channel_0);
printf("ADValue0=%d Voltage=%.2fV\r\n", Value,(float)Value * 3.3 / 4096);
Delay_ms(1000);
Value = AD_GetValue(ADC_Channel_1);
printf("ADValue1=%d Voltage=%.2fV\r\n", Value,(float)Value * 3.3 / 4096);
Delay_ms(1000);
Value = AD_GetValue(ADC_Channel_2);
printf("ADValue2=%d Voltage=%.2fV\r\n", Value,(float)Value * 3.3 / 4096);
Delay_ms(1000);
Value = AD_GetValue(ADC_Channel_3);
printf("ADValue3=%d Voltage=%.2fV\r\n", Value,(float)Value * 3.3 / 4096);
Delay_ms(1000);
Value = AD_GetValue(ADC_Channel_16); //内部温度摄氏度
temp = (1.43-Voltage)/0.0043+25;
printf("ADValue16=%d Voltage=%.2fV\r\n", Value,(float)Value * 3.3 / 4096);
printf("temp=%.2f\r\n", temp);
Delay_ms(1000);
Value = AD_GetValue(ADC_Channel_17); //内部参照电压
printf("ADValue17=%d Voltage=%.2fV\r\n\r\n\r\n", Value,(float)Value * 3.3 / 4096);
Delay_ms(1000);
printf("\r\n******************END*****************\r\n");
}
}