Stm32_标准库_8_ADC_光敏传感器_测量具体光照强度

2023-10-08 20:52

本文主要是介绍Stm32_标准库_8_ADC_光敏传感器_测量具体光照强度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ADC简介

在这里插入图片描述
测量方式

在这里插入图片描述
采用二分法比较数据

IO通道

在这里插入图片描述
ADC基本结构及配置路线

在这里插入图片描述


获取数字变量需要用到用到光敏电阻的AO口,AO端口接在PA0引脚即可
在这里插入图片描述
测得的模拟数据与实际光照强度之间的关系为

光照强度 = 100 - 模拟量 / 40;

代码:

完整朴素代码:

#include "stm32f10x.h"    // Device header
#include "Delay.h"
#include "OLED.h"GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;void AD_Init(void){//初始化ADRCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模块工作时钟 72 / 6 = 12MHZ/*配置GPIO口*/GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);/*在规则组列表第一个位置,写入通道0这个通道*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);/*结构体初始化ADC*/ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//单次转换ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发方式,不使用外部触发,即软件触发ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式为独立模式ADC_InitStruct.ADC_NbrOfChannel = 1;//通道数目ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非扫描ADC_Init(ADC1, &ADC_InitStruct);//开启ADC电源ADC_Cmd(ADC1, ENABLE);/*给ADC校准*/ADC_ResetCalibration(ADC1);//复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回ADC1复位校准状态ADC_StartCalibration(ADC1);//开始校准while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
}uint16_t AD_Getvailue(void){//获取信息ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发转换while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待转换完成return ADC_GetConversionValue(ADC1);//读取数据
}uint16_t Reality_ADLight(uint16_t ADCnum){//获取光照强度return 100 - ADCnum / 40;
}int main(void){OLED_Init();//初始化OLEDAD_Init();while(1){uint16_t num  = AD_Getvailue();uint16_t num1 = Reality_ADLight(num); OLED_ShowString(1, 1, "ADO:");OLED_ShowNum(1, 5, num, 5);OLED_ShowString(2, 1, "LUX:");OLED_ShowNum(2, 5, num1, 3);Delay_ms(300);}
}

效果:

在这里插入图片描述
此代码的不足之处在于每次写入数字都会提前占据固定位置,这个固定位置在整个过程是不能更改的,十分影响观感

所以添加求数字长度的函数,方便随时捕捉并调正所占空间
添加代码:

uint8_t length(uint16_t num){uint8_t length = 0;while(num > 0){num = num / 10;length = length + 1;}return length;
}

完整优化代码1:

#include "stm32f10x.h"    // Device header
#include "Delay.h"
#include "OLED.h"GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;void AD_Init(void){//初始化ADRCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模块工作时钟 72 / 6 = 12MHZ/*配置GPIO口*/GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);/*在规则组列表第一个位置,写入通道0这个通道*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);/*结构体初始化ADC*/ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//单次转换ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发方式,不使用外部触发,即软件触发ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式为独立模式ADC_InitStruct.ADC_NbrOfChannel = 1;//通道数目ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非扫描ADC_Init(ADC1, &ADC_InitStruct);//开启ADC电源ADC_Cmd(ADC1, ENABLE);/*给ADC校准*/ADC_ResetCalibration(ADC1);//复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回ADC1复位校准状态ADC_StartCalibration(ADC1);//开始校准while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
}uint16_t AD_Getvailue(void){//获取信息ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发转换while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待转换完成return ADC_GetConversionValue(ADC1);//读取数据
}
uint8_t length(uint16_t num){uint8_t length = 0;while(num > 0){num = num / 10;length = length + 1;}return length;
}
uint16_t Reality_ADLight(uint16_t ADCnum){//获取光照强度return 100 - ADCnum / 40;
}int main(void){OLED_Init();//初始化OLEDAD_Init();while(1){uint16_t num  = AD_Getvailue();uint16_t num1 = Reality_ADLight(num); OLED_ShowString(1, 1, "ADO:");OLED_ShowNum(1, 5, num, length(num));OLED_ShowString(2, 1, "LUX:");OLED_ShowNum(2, 5, num1, length(num1));Delay_ms(300);OLED_Clear();}
}

效果:在这里插入图片描述

写入数据是采用覆盖制,例如上次写入的数据是1234,本次写入的数据是999,那么此时展现的效果为9994,由于ADO取值范围为[0 ~4095],LUX(光照强度)取值范围为[1, 100],所以为了不影响数据的合理性,所以必须要在每次写入新数据时必须要清理一下OLED

但是由于提供的清屏函数每次都是将全部数据清理掉,所以画面刷新也要从新再全部刷新一次所以整体画面会不连贯

所以我写入了一个只清屏某个部分的函数
添加代码:

/* 直接用清屏函数整体刷新会导致OLED画面不连贯清除行函数:保留本行字符串,清除本行剩余部分row:清除的具体行len:不希望被清除的字符串长度
*/void OLED_LoactionClear(uint8_t row, uint8_t len)
{  uint8_t i, j;for (j = row * 2 - 2; j < row * 2; j++){OLED_SetCursor(j, len * 8);for(i = len * 8; i < 128; i++){OLED_WriteData(0x00);}}
}

放入位置

需要将其copy到OLED.c文件下,并在OLED.h文件内声明一下
在这里插入图片描述
在这里插入图片描述
具体函数使用方法:

OLED_LoactionClear(uint8_t row, uint8_t len);
此函数有两个参数:

其中row指你想要进行清屏操作的具体行,OLED上一共能显示4行
其中len代表row行从左到右len长度区间的字符串将会被保留,row行剩余其他数据将全被清除

完整优化代码2:

#include "stm32f10x.h"    // Device header
#include "Delay.h"
#include "OLED.h"GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;void AD_Init(void){//初始化ADRCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模块工作时钟 72 / 6 = 12MHZ/*配置GPIO口*/GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);/*在规则组列表第一个位置,写入通道0这个通道*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);/*结构体初始化ADC*/ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//单次转换ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发方式,不使用外部触发,即软件触发ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式为独立模式ADC_InitStruct.ADC_NbrOfChannel = 1;//通道数目ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非扫描ADC_Init(ADC1, &ADC_InitStruct);//开启ADC电源ADC_Cmd(ADC1, ENABLE);/*给ADC校准*/ADC_ResetCalibration(ADC1);//复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回ADC1复位校准状态ADC_StartCalibration(ADC1);//开始校准while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
}uint16_t AD_Getvailue(void){//获取信息ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发转换while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待转换完成return ADC_GetConversionValue(ADC1);//读取数据
}
uint8_t length(uint16_t num){uint8_t length = 0;while(num > 0){num = num / 10;length = length + 1;}return length;
}
uint16_t Reality_ADLight(uint16_t ADCnum){//获取光照强度return 100 - ADCnum / 40;
}int main(void){OLED_Init();//初始化OLEDAD_Init();while(1){uint16_t num  = AD_Getvailue();uint16_t num1 = Reality_ADLight(num); OLED_ShowString(1, 1, "ADO:");OLED_LoactionClear(1, length(num) + 3);//"ADO:"长度为3所以要加3OLED_ShowNum(1, 5, num, length(num));OLED_ShowString(2, 1, "LUX:");OLED_LoactionClear(2, length(num1) + 3);OLED_ShowNum(2, 5, num1, length(num1));Delay_ms(300);}
}

效果:

在这里插入图片描述

这篇关于Stm32_标准库_8_ADC_光敏传感器_测量具体光照强度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/167933

相关文章

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

C 标准库 - `<float.h>`

C 标准库 - <float.h> 概述 <float.h> 是 C 标准库中的一个头文件,它定义了与浮点数类型相关的宏。这些宏提供了关于浮点数的属性信息,如精度、最小和最大值、以及舍入误差等。这个头文件对于需要精确控制浮点数行为的程序非常有用,尤其是在数值计算和科学计算领域。 主要宏 <float.h> 中定义了许多宏,下面列举了一些主要的宏: FLT_RADIX:定义了浮点数的基数。

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

《C++标准库》读书笔记/第一天(C++新特性(1))

C++11新特性(1) 以auto完成类型自动推导 auto i=42; //以auto声明的变量,其类型会根据其初值被自动推倒出来,因此一定需要一个初始化操作; static auto a=0.19;//可以用额外限定符修饰 vector<string> v;  auto pos=v.begin();//如果类型很长或类型表达式复杂 auto很有用; auto l=[] (int

笔记本电脑的具体选购步骤流程

2.1 笔记本电脑的具体选购步骤流程   关于笔记本电脑的选购,一直是热点话题。不管是新手还是老前辈,选购前,总是要先上网查一查,汇总一些信息或经验。因为选购一台笔记本电脑,从它的配置、外观到做工等很多方面都需要考量,所以挑一台自己喜欢的、适合自己的笔记本电脑也是一件很费脑筋的事情。本节将一些选购笔记本电脑的经验进行了总结,供广大读者选购笔记本电脑时参考。   笔记本电脑选购流程如下