一:光敏传感器知识分享:
光敏传感器是最常见的传感器之一,它的种类繁多,主要有:光电管、光电倍增管、光敏电阻、光敏三极管、太阳能电池、红外线传感器、紫外线传感器、光纤式光电传感器、色彩传感器、CCD 和 CMOS 图像传感器等。光传感器是目前产量最多、应用最广的传感器之一,它在自动控制和非电量电测技术中占有非常重要的地位。
光敏传感器是利用光敏元件将光信号转换为电信号的传感器,它的敏感波长在可见光波长附近,包括红外线波长和紫外线波长。光传感器不只局限于对光的探测,它还可以作为探测元件组成其他传感器,对许多非电量进行检测,只要将这些非电量转换为光信号的变化即可。STM32F103 精英开发板板载了一个光敏二极管(光敏电阻),作为光敏传感器,它对光的变化非常敏感。光敏二极管也叫光电二极管。光敏二极管与半导体二极管在结构上是类似的,其管芯是一个具有光敏特征的 PN 结,具有单向导电性,因此工作时需加上反向电压。无光照时,有很小的饱和反向漏电流,即暗电流,此时光敏二极管截止。当受到光照时,饱和反向漏电流大大增加,形成光电流,它随入射光强度的变化而变化。当光线照射 PN 结时,可以使 PN 结中产生电子一空穴对,使少数载流子的密度增加。这些载流子在反向电压下漂移,使反向电流增加。因此可以利用光照强弱来改变电路中的电流。
利用这个电流变化,我们串接一个电阻,就可以转换成电压的变化,从而通过 ADC 读取电压值,判断外部光线的强弱。本章,我们利用 ADC3 的通道6(PF8)来读取光敏二极管电压的变化,从而得到环境光线的变化,并将得到的光线强度,通过串口1发送到PC端进行监视。
对于STM32的ADC知识在之前的帖子里已经介绍过,这里就不再重复介绍;
二:设计要点:
通过 ADC3 的通道6(PF8)读取光敏传感器(LS1)的电压值,并转换为 0~100 的光线强度值,显示在 LCD 模块上面。光线越亮,值越大:光线越暗,值越小。大家可以用手指遮挡LS1和用手电筒照射 LS1,来查看光强变化。LED0闪烁用于提示程序正在运行。
三:STM32 cube MX 软件配置如下所示:
四:软件代码:
4.1 配置通道:
void adc3_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime) { ADC_ChannelConfTypeDef adc_ch_conf; adc_ch_conf.Channel = ch; /* 通道 */ adc_ch_conf.Rank = rank; /* 序列 */ adc_ch_conf.SamplingTime = stime; /* 采样时间 */ HAL_ADC_ConfigChannel(adc_handle, &adc_ch_conf); /* 通道配置 */ }
4.2 读取ADC转换后的数据
/** * @brief 获得ADC转换后的结果 * @param ch: 通道值 0~17,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_17 * @retval 无 */ uint32_t adc3_get_result(uint32_t ch) { adc3_channel_set(&hadc3 , ch, ADC_REGULAR_RANK_1, ADC_SAMPLETIME_239CYCLES_5); /* 设置通道,序列和采样时间 */ HAL_ADC_Start(&hadc3); /* 开启ADC */ HAL_ADC_PollForConversion(&hadc3, 10); /* 轮询转换 */ return (uint16_t)HAL_ADC_GetValue(&hadc3); /* 返回最近一次ADC1规则组的转换结果 */ }
4.3 对采集到的数据进行取平均值处理
uint32_t adc3_get_result_average(uint32_t ch, uint8_t times) { uint32_t temp_val = 0; uint8_t t; for (t = 0; t < times; t++) /* 获取times次数据 */ { temp_val += adc3_get_result(ch); HAL_Delay(5); } return temp_val / times; /* 返回平均值 */ }
4.4 将ADC数据,转换成光照强度:
/** * @brief 读取光敏传感器值 * @param 无 * @retval 0~100:0,最暗;100,最亮 */ uint8_t lsens_get_val(void) { uint32_t temp_val = 0; temp_val = adc3_get_result_average(ADC_CHANNEL_6, 10); /* 读取平均值 */ temp_val /= 40; if (temp_val > 100)temp_val = 100; return (uint8_t)(100 - temp_val); }
4.5 进行数据输出:
void task_1000ms(void) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); adcData1 = lsens_get_val(); printf("adcData1 =%5d\r\n",adcData1); }
五:实物测试图如下所示: