这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【原创】光敏传感器控制LED灯强度--from业

共3条 1/1 1 跳转至

【原创】光敏传感器控制LED灯强度--from业

工程师
2024-07-18 23:05:14     打赏

光敏传感器介绍

图片1.png

产品接线说明:VCC 接电源正极 3.3-5VGND 接电源负极DO TTL 开关信号输出 (配置为输出模式)AO 模拟信号输出(ADC采样通道)

光敏传感器主要用于检测周围的光照强度,光照强度发生变化那么ADC采样的值也会发送变化。

光敏传感器工作原理和原理图

图片2.png

spacer.gif光敏传感器的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出.

ADC对光敏传感器的原理

在使用STM32微控制器时,是通过配置ADC的输入通道、采样频率等参数来实现对光敏传感器信号的采集。

单片机内置的ADC通过将光敏电阻输出的模拟信号转换成为数字信号,从而使得单片机快速的识别并处理光信号,从而实现光敏电阻来控制其他器件。

同时还需要注意ADC的引脚定义和通道,每个引脚都有定义的专用通道,ADC的引脚定义及所对应的通道有如下10种:

1721314858735079.png

STM32F103C8T6开发板、光敏传感器、LED灯、OLED显示屏、杜邦线若干

1721314914610519.png


编写代码

配置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);

}   

}

1721314960311190.png

1721315012897306.png



助工
2024-07-19 10:21:47     打赏
2楼

言简意赅,现在的学生真幸福。


工程师
2024-07-19 14:12:26     打赏
3楼

666666


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]