第20章 光敏传感器实验
第二十章 光敏传感器实验
1. 硬件设计
本实验用到的硬件资源有:
-
指示灯DS0
-
TFTLCD模块
-
ADC
-
光敏传感器
前三个之前均有介绍,光敏传感器与 STM32F4 的连接如图所示:
图中, LS1 是光敏二极管(实物在开发板摄像头接口右侧), R58 为其提供反向电压,当环境光线变化时, LS1 两端的电压也会随之改变,从而通过 ADC3_IN5 通道,读取LIGHT_SENSOR(PF7)上面的电压,即可得到环境光线的强弱。光线越强,电压越低,光线越暗,电压越高。
2. 软件设计
2.1 ADC初始化
ADC_HandleTypeDef ADC3_Handler;//ADC句柄
// 初始化ADC
// ch: ADC_channels
// 通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
void Adc3_Init(void)
{
ADC3_Handler.Instance=ADC3;
ADC3_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4; // 4分频,ADCCLK=PCLK2/4=84/4=21MHZ
ADC3_Handler.Init.Resolution=ADC_RESOLUTION_12B; // 12位模式
ADC3_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT; // 右对齐
ADC3_Handler.Init.ScanConvMode=DISABLE; // 非扫描模式
ADC3_Handler.Init.EOCSelection=DISABLE; // 关闭EOC中断
ADC3_Handler.Init.ContinuousConvMode=DISABLE; // 关闭连续转换
ADC3_Handler.Init.NbrOfConversion=1; // 1个转换在规则序列中 也就是只转换规则序列1
ADC3_Handler.Init.DiscontinuousConvMode=DISABLE; // 禁止不连续采样模式
ADC3_Handler.Init.NbrOfDiscConversion=0; // 不连续采样通道数为0
ADC3_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START; // 软件触发
ADC3_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;// 使用软件触发
ADC3_Handler.Init.DMAContinuousRequests=DISABLE; // 关闭DMA请求
HAL_ADC_Init(&ADC3_Handler); // 初始化
}
2.2 采集ADC值
// ADC底层驱动,引脚配置,时钟使能
// 此函数会被HAL_ADC_Init()调用
// hadc:ADC句柄
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
__HAL_RCC_ADC3_CLK_ENABLE(); // 使能ADC3时钟
}
// 获得ADC值
// ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
// 返回值:转换结果
u16 Get_Adc3(u32 ch)
{
ADC_ChannelConfTypeDef ADC1_ChanConf;
ADC1_ChanConf.Channel=ch; // 通道
ADC1_ChanConf.Rank=1; // 1个序列
ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; // 采样时间
ADC1_ChanConf.Offset=0; // 偏移量为0
HAL_ADC_ConfigChannel(&ADC3_Handler,&ADC1_ChanConf); // 通道配置
HAL_ADC_Start(&ADC3_Handler); // 开启ADC
HAL_ADC_PollForConversion(&ADC3_Handler,10); // 轮询转换
return (u16)HAL_ADC_GetValue(&ADC3_Handler); // 返回最近一次ADC1规则组的转换结果
}
2.3 初始化光敏传感器
//初始化光敏传感器
void Lsens_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOF_CLK_ENABLE(); // 开启GPIOF时钟
GPIO_Initure.Pin=GPIO_PIN_7; // PF7
GPIO_Initure.Mode=GPIO_MODE_ANALOG; // 模拟
GPIO_Initure.Pull=GPIO_NOPULL; // 不带上下拉
HAL_GPIO_Init(GPIOF,&GPIO_Initure);
Adc3_Init();//初始化ADC3
}
2.4 获取光亮值
//读取Light Sens的值
//0~100:0,最暗;100,最亮
u8 Lsens_Get_Val(void)
{
u32 temp_val=0;
u8 t;
for(t=0;t<LSENS_READ_TIMES;t++)
{
temp_val+=Get_Adc3(ADC_CHANNEL_5); //读取ADC值,通道5
delay_ms(5);
}
temp_val/=LSENS_READ_TIMES;//得到平均值
if(temp_val>4000)temp_val=4000;
return (u8)(100-(temp_val/40));
}
2.5 主函数
int main(void)
{
u8 adcx;
HAL_Init(); // 初始化HAL库
Stm32_Clock_Init(336,8,2,7); // 设置时钟,168Mhz
delay_init(168); // 初始化延时函数
uart_init(115200); // 初始化USART
usmart_dev.init(84); // 初始化USMART
LED_Init(); // 初始化LED
KEY_Init(); // 初始化KEY
LCD_Init(); // 初始化LCD
Lsens_Init(); // 初始化光敏传感器
POINT_COLOR = RED; // 设置字体为红色
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"LSENS TEST");
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(30,130,200,16,16,"LSENS_VAL:");
while(1)
{
adcx = Lsens_Get_Val(); // 获取光敏传感器的值
LCD_ShowxNum(30+10*8,130,adcx,3,16,0);//显示ADC的值
LED0=!LED0;
delay_ms(250);
}
}
3. 小结
本章主要还是在学习ADC采集电压,不过这次我们接入了一个光敏传感器,不同光亮程度电压不同,ADC所采集的值也就不同了。下面我们来回顾一下:
硬件连接
- 光敏传感器(LDR):将光敏传感器的一个引脚连接到 STM32 的 ADC 输入引脚,另一个引脚接地。
- 电源:为光敏传感器提供适当的电源(一般为 3.3V 或 5V,具体取决于你使用的传感器)。
- ADC 输入:选择合适的 ADC 通道连接到光敏传感器。
示例代码
#include "main.h" // 包含 STM32 库的主头文件
// ADC 句柄和 UART 句柄的声明
ADC_HandleTypeDef hadc1;
UART_HandleTypeDef huart1;
// 函数原型声明
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 库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化 GPIO、ADC 和 USART
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
while (1) {
// 启动 ADC 转换
HAL_ADC_Start(&hadc1);
// 等待 ADC 转换完成
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
// 读取 ADC 转换值
uint32_t adcValue = HAL_ADC_GetValue(&hadc1);
// 计算光敏传感器的输出电压
// 假设 Vref = 3.3V, 分辨率为 12 位
float voltage = (3.3f * adcValue) / 4095.0f; // 将 ADC 值转换为电压值
// 将电压值格式化为字符串,准备发送
char buffer[50]; // 缓冲区用于存储输出字符串
snprintf(buffer, sizeof(buffer), "LDR Voltage: %.2f V\r\n", voltage);
// 通过串口发送电压值
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
// 延时1秒
HAL_Delay(1000); // 等待 1 秒以便下次读取
}
}
// ADC 初始化函数
static void MX_ADC1_Init(void) {
// 配置 ADC 通道
ADC_ChannelConfTypeDef sConfig = {0}; // 创建一个 ADC 通道配置结构体
__HAL_RCC_ADC1_CLK_ENABLE(); // 启用 ADC1 的时钟
// 配置 ADC 的基本参数
hadc1.Instance = ADC1; // 选择 ADC1 实例
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // ADC 时钟预分频
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12 位分辨率
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 禁用扫描模式
hadc1.Init.ContinuousConvMode = ENABLE; // 启用连续转换模式
hadc1.Init.DiscontinuousConvMode = DISABLE; // 禁用不连续模式
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发转换
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据对齐方式
hadc1.Init.NbrOfConversion = 1; // 只进行一次转换
HAL_ADC_Init(&hadc1); // 初始化 ADC1
// 配置光敏传感器通道
sConfig.Channel = ADC_CHANNEL_0; // 设置通道为 ADC_CH0 (请根据实际情况选择)
sConfig.Rank = ADC_REGULAR_RANK_1; // 设置为常规通道的第一个
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; // 采样时间设置为 3 个时钟周期
HAL_ADC_ConfigChannel(&hadc1, &sConfig); // 配置 ADC 通道
}
// USART 和 GPIO 的初始化代码省略
static void MX_USART1_UART_Init(void) {
// 配置 UART 参数
huart1.Instance = USART1; // 选择 USART1 实例
huart1.Init.BaudRate = 9600; // 设置波特率为 9600
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; // 16 倍过采样
HAL_UART_Init(&huart1); // 初始化 USART1
}
// GPIO 初始化函数
static void MX_GPIO_Init(void) {
// GPIO 初始化代码根据具体需求进行配置
}
// 系统时钟配置函数
void SystemClock_Config(void) {
// 系统时钟配置代码,设置主时钟源、分频器等
}