光敏传感器介绍
产品接线说明:VCC 接电源正极 3.3-5VGND 接电源负极DO TTL 开关信号输出 (配置为输出模式)AO 模拟信号输出(ADC采样通道)
光敏传感器主要用于检测周围的光照强度,光照强度发生变化那么ADC采样的值也会发送变化。
光敏传感器工作原理和原理图
光敏传感器的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出.
ADC对光敏传感器的原理
在使用STM32微控制器时,是通过配置ADC的输入通道、采样频率等参数来实现对光敏传感器信号的采集。
单片机内置的ADC通过将光敏电阻输出的模拟信号转换成为数字信号,从而使得单片机快速的识别并处理光信号,从而实现光敏电阻来控制其他器件。
同时还需要注意ADC的引脚定义和通道,每个引脚都有定义的专用通道,ADC的引脚定义及所对应的通道有如下10种:
STM32F103C8T6开发板、光敏传感器、LED灯、OLED显示屏、杜邦线若干
编写代码
配置ADC代码:
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*设置ADC时钟,选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz */
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
/*GPIO初始化,将PA3引脚初始化为模拟输入*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*规则组通道配置,规则组序列1的位置,配置为通道3*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_55Cycles5);
/*ADC初始化,将结构体变量交给ADC_Init,配置ADC1*/
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);
/*使能ADC1,ADC开始运行 */
ADC_Cmd(ADC1, ENABLE);
/*ADC校准,内部有电路会自动执行校准*/
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/**获取AD转换的值,AD转换的值,范围:0~4095*/
uint16_t AD_GetValue3(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发AD转换一次
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //等待EOC标志位,即等待AD转换结束
return ADC_GetConversionValue(ADC1); //读数据寄存器,得到AD转换的结果
}
配置PWM代码:
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化,将PA0引脚初始化为复用推挽输出,受外设控制的引脚,均需要配置为复用模式*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //LED的引脚接口,目的是将两者联系起来
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*配置时钟源,选择TIM2为内部时钟*/
TIM_InternalClockConfig(TIM2);
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,我们选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
//计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;//预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
/*输出比较初始化*/
TIM_OCInitTypeDef TIM_OCInitStructure; //定义结构体变量
TIM_OCStructInit(&TIM_OCInitStructure); //结构体初始化,若结构体没有完整赋值则最好执行此函数,给结构体所有成员都赋一个默认值避免结构体初值不确定的问题
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出比较模式,选择PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性,选择为高,若选择极性为低,则输出高低电平取反
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //初始的CCR值
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //配置TIM2的输出比较通道为1
/*使能TIM2,定时器开始运行*/
TIM_Cmd(TIM2, ENABLE);
}
/**PWM设置CCR,定义Compare要写入的CCR的值,范围:0~100,同时CCR和ARR共同决定占空比。此函数仅设置CCR的值,并不直接是占空比,占空比Duty = CCR / (ARR + 1) */
void PWM_SetCompare1(uint16_t Compare) //相当于设置占空比
{
TIM_SetCompare1(TIM2, Compare);
}
主函数代码:
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "AD.h"
#include "PWM.h"
#include "LED.h"
uint16_t ADValue,Compare;
float Voltage;
int main(void)
{
OLED_Init();
PWM_Init();
AD_Init();
OLED_ShowString(1,1,"Num:0.00V");
while(1)
{
ADValue = AD_GetValue3(); //获取AD转换的值
Voltage = (float)ADValue / 4095 * 3.3; //转化成电压值
Compare = Voltage * 30; //电压值转换成占空比的ARR
OLED_ShowNum(1,5,Voltage,1); //小数点前的数
OLED_ShowNum(1,7,(uint32_t)(Voltage*100)%100,2); //小数点后的数
PWM_SetCompare1(Compare);
}
}