STM32学习笔记(二十三)光敏传感器实验

本文详细介绍了使用STM32F103ZET6进行光敏传感器实验的过程,包括ADC原理、配置步骤和程序实现。通过库函数版本操作ADC,实现了光强的测量和显示,并提供了ADC模数转换、内部温度传感器和光敏传感器的代码示例。实验结果显示了光敏传感器获取的光强值,并在LCD上实时显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STM32F103ZET6之光敏传感器实验



前言

对于STM32的学习可分为3个版本。
1.寄存器版本
2.库函数版本
3.HAL库版本
由于个人原因,选择库函数版本来进行STM32的学习。


提示:软件安装等问题,不进行讲解!!!

一、原理

1.简介

光敏传感器是最常见的传感器之一,它的种类繁多,主要有:光电管、光电倍增管、光敏电阻、光敏三极管、太阳能电池、红外线传感器、紫外线传感器、光纤式光电传感器、色彩传感器、CCD和CMOS图像传感器等。光传感器是目前产量最多、应用最广的传感器之一,它在自动控制和非电量电测技术中占有非常重要的地位。

2.ADC通道与引脚关系

在这里插入图片描述

3.原理图

在这里插入图片描述

二、相关配置

1.相关寄存器

ADC 控制寄存器(ADC_CR1 和 ADC_CR2)
ADC 采样事件寄存器(ADC_SMPR1 和 ADC_SMPR2)
ADC 规则序列寄存器(ADC_SQR1~3)
ADC 寄存器为 ADC 状态寄存器(ADC_SR)

2.电压与温度关系

在这里插入图片描述

3.配置步骤(类似)

在这里插入图片描述

三、程序源码

1.adc.h

代码如下:

#ifndef __ADC_H
#define __ADC_H

#include "sys.h"

void Adc_Init(void);//ADC模数转换
u16 Get_Adc(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);

void T_Adc_Init(void);//内部温度传感器
short Get_Temperate(void);

void Lsenes_Init(void);//光敏传感器
void Adc3_Init(void);
u16 Get_Adc3(u8 ch);
u8 Lsenes_Get_Val(void);

#endif

2.adc.c

代码如下:

#include "adc.h"
#include "stm32f10x.h"
#include "delay.h"

void Adc_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	ADC_InitTypeDef ADC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE);//使能PA时钟和ADC1时钟
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;//模拟输入
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	ADC_DeInit(ADC1);//复位ADC
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72M/6<14M 分频因子
	
	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//连续模式
  ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//对齐设置
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//硬件触发
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//设置为独立模式
	ADC_InitStruct.ADC_NbrOfChannel=1;//顺序进行规则转换的ADC 通道的数目
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;
	ADC_Init(ADC1, &ADC_InitStruct);
	
	ADC_Cmd(ADC1, ENABLE);//使能ADC1
	
	ADC_ResetCalibration(ADC1);//开启复位校准
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);//开启AD校准
	while(ADC_GetCalibrationStatus(ADC1));
}

u16 Get_Adc(u8 ch)
{
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5);//配置规则通道
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//开启软件转换
	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;
}

void T_Adc_Init(void)
{
	ADC_InitTypeDef ADC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE);//使能PA时钟和ADC1时钟
	
	ADC_DeInit(ADC1);//复位ADC
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72M/6<14M 分频因子
	
	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//独立模式
  ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//对齐设置
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//硬件触发
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//设置为独立模式
	ADC_InitStruct.ADC_NbrOfChannel=1;//顺序进行规则转换的ADC 通道的数目
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;
	ADC_Init(ADC1, &ADC_InitStruct);
	
	ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度传感器
	ADC_Cmd(ADC1, ENABLE);//使能ADC1
	
	ADC_ResetCalibration(ADC1);//开启复位校准
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);//开启AD校准
	while(ADC_GetCalibrationStatus(ADC1));
}

short Get_Temperate(void)
{
	u32 adcx;
	short result;
	double temperate;
	adcx=Get_Adc_Average(ADC_Channel_16,20);
	temperate=(float)adcx*(3.3/4096);//电压值
	temperate=(1.43-temperate)/0.0043+25;//转换为温度值
	result=temperate*100;
	return result;
}

void Adc3_Init(void)
{
  ADC_InitTypeDef ADC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);//ADC3时钟
	
	ADC_DeInit(ADC3);//复位ADC
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72M/6<14M 分频因子
	
	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//独立模式
  ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//对齐设置
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//硬件触发
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//设置为独立模式
	ADC_InitStruct.ADC_NbrOfChannel=1;//顺序进行规则转换的ADC 通道的数目
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;
	ADC_Init(ADC3, &ADC_InitStruct);
	
	ADC_Cmd(ADC3, ENABLE);//使能ADC3
	
	ADC_ResetCalibration(ADC1);//开启复位校准
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);//开启AD校准
	while(ADC_GetCalibrationStatus(ADC1));
}
void Lsenes_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOF, &GPIO_InitStruct);
	Adc3_Init();
}
u16 Get_Adc3(u8 ch)
{
	ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_239Cycles5);//配置规则通道
	ADC_SoftwareStartConvCmd(ADC3, ENABLE);//开启软件转换
	while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC));//等待转换完成
	return ADC_GetConversionValue(ADC3);
}
u8 Lsenes_Get_Val(void)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<10;t++)
	{
		temp_val+=Get_Adc3(ADC_Channel_6);
		delay_ms(5);
	}
	temp_val/=10;
	if(temp_val>4000) temp_val=4000;
	return (u8)(100-(temp_val/40));
}

3.main.c

代码如下:

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

 int main(void)
 {	 
	u8 adcx;
	 
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
 	LED_Init();			     //LED端口初始化
	LCD_Init();
	Lsenes_Init();
	 
	POINT_COLOR=RED;//设置字体为红色
	LCD_ShowString(60,50,200,16,16,"chen");
	//显示提示信息
	POINT_COLOR=BLUE;//设置字体为蓝色
	LCD_ShowString(30,140,200,16,16,"LSENS_VAL:");	
	 
	while(1)
	{
        adcx=Lsenes_Get_Val();
		LCD_ShowxNum(30+10*8,140,adcx,3,16,0);
		LED0=!LED0;
		delay_ms(250);
	}
}

实验结果

adc.c与adc.h为ADC模数转换,内部温度传感器,光敏传感器三合一
通过 Lsens_Get_Val 获取光敏传感器得到的光强值(0~100),并显示在 TFTLCD 上面(注意计算过程)
在这里插入图片描述


总结

1.看完视频,一定自己写一遍程序。
2.烧写程序前,对程序进行分析,推理实验现象。
3.若实验现象与推理不一致,一定要认真分析程序。

### STM32F103ZET6 光敏电阻与串口通信配置 #### 硬件连接说明 STM32F103ZET6 的 GPIO 可用于读取光敏电阻的模拟信号。通过 ADC 转换模块获取光敏电阻的电压值,并将其发送到 PC 或其他设备,利用 USART 进行串口通信。 硬件连接如下: - 将光敏电阻的一端接到电源 (VCC),另一端接地 (GND) 并串联一个固定电阻形成分压电路。 - 使用 STM32 的 ADC 输入引脚(例如 PA0)来检测光敏电阻上的电压变化。 - 配置 USART 引脚(例如 PA9 和 PA10),分别作为 TX 和 RX 用于串口通信[^1]。 --- #### 初始化代码示例 以下是基于 HAL 库的初始化代码: ```c #include "stm32f1xx_hal.h" // 定义全局变量 uint16_t adcValue; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_USART1_UART_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); // 初始化GPIO、ADC和USART MX_GPIO_Init(); MX_ADC1_Init(); MX_USART1_UART_Init(); while (1) { HAL_ADC_Start(&hadc1); // 启动ADC转换 HAL_ADC_PollForConversion(&hadc1, 100); // 等待转换完成 adcValue = HAL_ADC_GetValue(&hadc1); // 获取ADC值 char buffer[50]; sprintf(buffer, "Light Value: %d\r\n", adcValue); // 格式化数据 HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 100); // 发送数据至串口 HAL_Delay(500); // 延时500ms } } /** * @brief ADC1 Initialization Function */ static void MX_ADC1_Init(void) { hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = DISABLE; // 单通道模式 hadc1.Init.ContinuousConvMode = DISABLE; // 关闭连续转换 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐 hadc1.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); // 错误处理函数 } // 配置ADC通道 ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = ADC_CHANNEL_0; // 使用PA0作为输入 sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } /** * @brief USART1 Initialization Function */ static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; // 波特率设置为115200 huart1.Init.WordLength = UART_WORDLENGTH_8B;// 字符长度为8位 huart1.Init.StopBits = UART_STOPBITS_1; // 停止位为1 huart1.Init.Parity = UART_PARITY_NONE; // 无校验 huart1.Init.Mode = UART_MODE_TX_RX; // 收发模式 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;// 不启用流控 huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } ``` --- #### 参数解释 上述代码实现了以下功能: 1. **ADC 模块**:从光敏电阻采集模拟信号并转化为数字量 `adcValue`。 2. **UART 模块**:将采集的数据通过串口发送给外部设备。 3. **定时器延时**:每间隔 500 ms 执行一次采样和传输操作。 --- #### 注意事项 - 在实际应用中需注意光敏电阻的阻值范围以及供电电压的选择,以确保其工作在线性区域内。 - 如果使用更高分辨率的 ADC,则可能需要调整采样时间参数。 - 若波特率过高可能导致数据丢失,请根据具体应用场景合理选择波特率。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小白正在努力

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

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

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

打赏作者

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

抵扣说明:

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

余额充值