智能时钟 part 3
- 6 光强传感器
- 6.1 光敏电阻介绍
- 6.2 电路图介绍
- 7 ADC模块
- 7.1 ADC模块介绍
- 7.2 adc 转化流程
- 7.3 规则通道和注入通道
- 7.4 DMA 搬运
- 7.5 TIM触发ADC和DMA搬运数据的原理
- 8 代码
- 8.1 配置头文件
- 8.2 初始化ADC 和DMA
- 8.3 创建线程读取 值
- 8.4 演示效果
由于丢失温湿度传感器 DHT11,临时加成光强检测,检测结果用湿度指示器来显示。
6 光强传感器
6.1 光敏电阻介绍
光敏电阻(photoresistor或light-dependent resistor,缩写为LDR)是一种基于内光电效应的半导体元件,其阻值依赖于入射光强的变化。当入射光强增加时,光敏电阻的阻值减小;反之,入射光强减弱时,其阻值增大。光敏电阻没有极性,使用时在其两端施加一个任意方向的外加电压,通过测量回路中的电流大小可以反映入射光的强弱。
工作原理
光敏电阻的工作原理基于半导体的内光电效应。在黑暗条件下,光敏电阻内部的大部分电子是不能自由移动的价带电子,此时光敏电阻的阻值很高。当存在波长合适的光照时,光敏电阻内的价带电子会吸收光子能量跃迁到导带,成为可以导电的自由电子,并在价带中留下一个空穴。光强越大,激发的电子-空穴对数量越多,光敏电阻的阻值也就越低。当光被移除时,导带电子与价带空穴重新结合,光敏电阻的阻值增加。
应用领域
光敏电阻具有灵敏度高、响应速度快、稳定性好的优点,因此广泛应用于光的测量、光的控制和光电转换等领域。常见的应用包括紫外线探测器、红外线探测器、自动调光系统、烟雾报警器等。
6.2 电路图介绍
对应IO口: PF7口
7 ADC模块
7.1 ADC模块介绍
ADC是英文Analog Digital Converter,直译的意思就是模数转换器.它是一种能将一定范围内的模拟电压量转换为数字信号量的设备。stm32单片机内部内置了ADC
任何测量仪器都有测量范围。单片机内置的ADC测量范围是0-Vref。Vref一般可以是一个引脚。这里Vref直接接在了VDD上,因此测量范围0-3v3。
7.2 adc 转化流程
单次转换模式的规则通道
- 转换数据被储存在ADC_DR寄存器中
- EOC(转换结束)标志位被标志
- 如果设置了EOCIE,则产生中断
单次转换模式的注入通道
- 存储特定的ADC_DRJx寄存器中(每一个通道单独分配了一个寄存器)
- 转换结束的标志位为JEOC
- 中断标志位为JEOCIE
循环转换模式
循环转换模式则在这一次转换结束后立马启动下一次转换
7.3 规则通道和注入通道
规则通道:用于常规的数据采集,通常用于采集主要的输入信号
注入通道:是一种特殊的输入通道,比规则通道有着更高的优先级
7.4 DMA 搬运
DMA(Direct Memory Access)控制器可以在不占用CPU资源的情况下,在外设和内存之间搬运数据。使用DMA来搬运ADC数据有以下优点:
减轻CPU负担:CPU无需介入每次数据传输,可以专注于其他任务。
提高数据传输效率:DMA可以以更快的速度搬运数据,适合高速采样的应用。
减少延迟:DMA传输数据时延更低,适合实时性要求高的场合。
以下是一些适合使用DMA的情况:
需要频繁和大批量的数据采集和传输。
CPU需要执行其他高优先级任务,不适合频繁处理中断。
系统需要高实时性,低延迟的数据处理。
7.5 TIM触发ADC和DMA搬运数据的原理
STM32F103的TIM、ADC和DMA之间可以通过事件控制器(Event Controller)建立联系。当TIM的输出比较事件发生时,可以产生一个触发信号,这个信号可以用来启动ADC的转换过程。然后,DMA控制器可以将ADC转换后的数据搬运到内存中。具体流程如下:
配置TIM,使其在特定时间间隔生成输出比较事件。
配置ADC,使其在接收到TIM的触发信号后开始采集。
配置DMA,使其在ADC采集到数据后将数据搬运到内存。
8 代码
8.1 配置头文件
#ifndef __ADC_H
#define __ADC_H#include "stm32f4xx.h"#define ADCx_CLK RCC_APB2Periph_ADC3#define ADCx_CHANNEL_GPIO_CLK RCC_AHB1Periph_GPIOF#define GPIO_PIN GPIO_Pin_7#define GPIO_PORT GPIOF#define DMA_CHANNELx DMA_Channel_2#define ADCx_DR_ADDRESS (&ADC3->DR)#define DMA_STREAMx DMA2_Stream1#define ADCx ADC3#define ADC_CHANNEL ADC_Channel_5void ADC_Config(void);extern __IO uint16_t uhADCxConvertedValue;#endif
8.2 初始化ADC 和DMA
__IO uint16_t uhADCxConvertedValue = 0;
__IO uint32_t uwADCxConvertedVoltage = 0;static void ADC_Config(void)
{ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;DMA_InitTypeDef DMA_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;/* Enable ADCx, DMA and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);RCC_AHB1PeriphClockCmd(ADCx_CHANNEL_GPIO_CLK, ENABLE); RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);/* DMA2 Stream0 channel2 configuration **************************************/DMA_InitStructure.DMA_Channel = DMA_CHANNELx; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADCx_DR_ADDRESS;DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADCxConvertedValue;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;DMA_InitStructure.DMA_BufferSize = 1;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_Init(DMA_STREAMx, &DMA_InitStructure);DMA_Cmd(DMA_STREAMx, ENABLE);/* Configure ADC3 Channel7 pin as analog input ******************************/GPIO_InitStructure.GPIO_Pin = GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;GPIO_Init(GPIO_PORT, &GPIO_InitStructure);/* ADC Common Init **********************************************************/ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;ADC_CommonInit(&ADC_CommonInitStructure);/* ADC3 Init ****************************************************************/ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;ADC_InitStructure.ADC_ScanConvMode = DISABLE;ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;ADC_InitStructure.ADC_NbrOfConversion = 1;ADC_Init(ADCx, &ADC_InitStructure);/* ADC3 regular channel7 configuration **************************************/ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_3Cycles);/* Enable DMA request after last transfer (Single-ADC mode) */ADC_DMARequestAfterLastTransferCmd(ADCx, ENABLE);/* Enable ADC3 DMA */ADC_DMACmd(ADCx, ENABLE);/* Enable ADC3 */ADC_Cmd(ADCx, ENABLE);
}
8.3 创建线程读取 值
void update_humi(uint32_t humi)
{uint32_t value=0;value=humi*100/4096;lv_meter_set_indicator_value(meter_humi, indic_humi, value);}ALIGN(RT_ALIGN_SIZE)
static char thread3_stack[512];
static struct rt_thread thread3;
/* 线程1入口函数 */
static void thread3_recv_event(void *param)
{ ADC_SoftwareStartConv(ADCx);while(1){rt_mutex_take(&lvgl_mutex,RT_WAITING_FOREVER);update_humi(uhADCxConvertedValue);rt_mutex_release(&lvgl_mutex);rt_thread_mdelay(500); /* sleep for 10 ms */}
} // 创建第三个线程,检测光强rt_thread_init(&thread3,"thread3",thread3_recv_event,RT_NULL,&thread3_stack[0],sizeof(thread3_stack),THREAD_PRIORITY - 1, THREAD_TIMESLICE);rt_thread_startup(&thread3);
8.4 演示效果
ADC 模块