STM32第十一课:ADC采集光照

文章目录

  • 需求
  • 一、ADC概要
  • 二、实现流程
    • 1.开时钟,分频,配IO
    • 2.配置ADC工作模式
    • 3.配置通道
    • 4.复位校准
    • 5.数值的获取
  • 三、需求的实现
  • 总结


需求

通过ADC转换实现光照亮度的数字化测量,最后将实时测量的结果打印在串口上。
`


一、ADC概要

   ADC全称是Analog-to-Digital Converter模数转换器,一般我们把模拟信号(Analog signal) 用A来进行简写,数字信号(digital signal) 用D来表示。
  自然界中绝大部分都是模拟信号,例如压力或温度的测量,为了方便储存,处理和传输,我们会通过ADC把模拟信号转化成数字形式给计算机处理。将模拟转换成数字的形式有两个步骤:采样和量化。
  本例中就是将光照亮度这种模拟量转换为具体的数字量。

本次使用的ADC:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、实现流程

1.开时钟,分频,配IO

先打开原理图,找到该光敏电阻的位置。
在这里插入图片描述
由该电路可知VAL测量的是该光敏电阻的分压,而随着光照的变化,该光敏电阻的电压也会发生实时的波动。
此时我们就利于该光敏电压的变化来实现需求。
先找到CPU上对应的引脚
在这里插入图片描述
由上图可知该模块对应的引脚为PA5,ADC为ADC12_IN5,代表该引脚PA5是ADC1/2的通道5。
此时我们就开GPIOA的时钟和ADC1的通道(1,2都行,无所谓)
代码如下:

	RCC->APB2ENR |= 0x01<<9;//ADC1通道RCC->APB2ENR |= 0x01<<2;//使能GPIOA

下面就要进行分频了,由于本次使用的ADC的特征为12分辨率,而APB2所传输的频率为72M,所以此时我们要进行6分频(72 ÷ 6 = 12)
在这里插入图片描述
在这里插入图片描述

	RCC->CFGR &= ~(0x03<<14);RCC->CFGR |= (0x02<<14);//6分频

最后进行PA5引脚的模式配置,由于要获得该引脚的电压值,而该电压值为动态变化的模拟量,所以此处要将模式置为模拟输入模式(0000)

GPIOA->CRL &= ~(0x0F<<20);//配置成模拟输入

2.配置ADC工作模式

首先打开手册找ADC1的控制寄存器(CR1,CR2),一个一个查看,看是否需要配置。
在这里插入图片描述
一般常用的是第8位扫描模式
在这里插入图片描述
不过此处只传输光照一个变量,所以可以不开置零就行。
在这里插入图片描述
双模式选择也是必要的,此处选独立模式就行,因为只用这一个ADC1。
到这里ADC1的CR1寄存器的基本配置就算完成了。
下面来看ADC1的CR2寄存器。
在这里插入图片描述
在这里插入图片描述
先来看第20位规则通道的外部触发转换模式。规则通道组每转换一次,代表着ADC1把数据传输到DR规则组通道数据寄存器上,该寄存器为16位,并且每传输一次,数据就会被覆盖一次。
此处我们选择开启1:使用外部时间启动转换
在这里插入图片描述
再来看19-17位,规则通道组转换的外部触发条件。
我们这里选择111:SWSTART(软件触发)因为是通过软件代码置位来触发。
在这里插入图片描述
第十一位数据对齐的模式要选择为右对齐,方便后续操作。
在这里插入图片描述
第一位的连续转换可开可关,因为只有光照一个量。
在这里插入图片描述
最后使能一下第0位:开启ADC并启动转换。

	//3、配置ADC的工作模式ADC1->CR1 &= ~(0x0F<<16);//独立模式ADC1->CR1 &= ~(0x01<<8);//不开扫描ADC1->CR2 |= 0x01<<20;//选择开启外部触发ADC1->CR2 |= 0x07<<17;//触发方式swsatrt(软件触发)ADC1->CR2 &= ~(0x01<<11);//选择数据右对齐ADC1->CR2 &= ~(0x01<<1);//关闭连续转换ADC1->CR2 |= 0x01<<0;//ADC使能

3.配置通道

由于该引脚PA5对应的是ADC12_IN5,所以我们只需要配置通道5即可。
配置通道在ADC规则序列寄存器和ADC采样时间寄存器中。
先找到SQR1寄存器
在这里插入图片描述
在这里插入图片描述
ADC规则序列寄存器负责通道数量的选择,共有16个,由于我们只用通道5,所以此时我们将L配置成0000,只配只配一个通道。
在这里插入图片描述
接下来配置我们选的SQ1通道,将其配成通道0x05。
在这里插入图片描述
最后配置一下采样周期,周期越大越准,所以我选择了111:239.5周期。

	//配置一个通道:通道5,第一个转换,采样周期最大(239.5)ADC1->SQR1 &= ~(0x0F<<20);//规则组通道只转换一个(配置通道数量)//具体某个通道的配置ADC1->SQR3 &= ~(0x1F<<0);//0-5位清0ADC1->SQR3 |= 0x05<<0;//选择第一个转换通道5ADC1->SMPR2 |= 0x07<<15;//采样周期最大(239.5)

4.复位校准

复位校准可有可无,不过为了更加保险,我还是加上了。
总共校准了两次,校准位在CR2寄存器的第三位。
在这里插入图片描述
每次校准后会自动置位0,所以此处while(1)等待非0,若为1就等待,为0就校准完成,继续往下执行。

	ADC1->CR2 |= 0x01<<3;//启动复位校准//等待复位校准结束while((ADC1->CR2&(0x01<<3))!=0)//判断寄存器的位3是不是等于1{}ADC1->CR2 |= 0x01<<2;//启动AD校准//等待AD校准结束while((ADC1->CR2&(0x01<<2))!=0)//判断寄存器的位2是不是等于1,是1就等待{}

5.数值的获取

对于数值的获取,我是单独写了个函数来执行,放便主函数调用并发送给串口。
想要获取数据,就要让ADC的CR2寄存器的第22位置1转换一下。
在这里插入图片描述
每转换一次,就代表着ADC1把数据传输到DR规则组通道数据寄存器上,该寄存器为16位,并且每传输一次,数据就会被覆盖一次。
所以此时我们让ADC的CR2寄存器的第22位置为1

那么什么时候代表转换完了?此时就要查看ADC的状态寄存器SR了
在这里插入图片描述
在这里插入图片描述
可以看到,每一次转换结束时,ADC_SR寄存器的第一位就会置1,并且不用我们去清零,每当我们去ADC_DR读取数据时,就会自动清除。
那么此时我们就可判断转换结束位的0,1来进行数据的读取了。
最后,将读取到的光照强度数据打印即可。(之前已经给printf重定向了,会自动打印到串口中)

void GetLightValue()
{uint16_t Light=0;//让规则通道转换一次ADC1->CR2 |= 0x01<<22;while((ADC1->SR&(0x01<<1))==0)//判断寄存器的位2是不是等于1,是0就等待转换完成{}Light = ADC1->DR; //读规则组通道数据寄存器printf("光照强度参数 = %d \r\n",Light);
}

三、需求的实现

关键代码如下:
main.c

#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"
#include "delay.h"
#include "string.h"
#include "pwm.h"
#include "adc.h"int main()
{NVIC_SetPriorityGrouping(5);//两位抢占两位次级Usart1_Config(); SysTick_Config(72000);RGBpwm_Config();uint8_t cai_count=0;uint16_t cont=0;Adc_Config();while(1){	if(ledcnt[0]>=ledcnt[1]){//过去500msledcnt[0]=0;GetLightValue();}}
}

adc.c

#include "ADC.h"void Adc_Config(void)
{//PA5//1、设置ADC的时钟(开时钟和时钟分频6分频)RCC->APB2ENR |= 0x01<<9;//ADC1通道RCC->APB2ENR |= 0x01<<2;//使能GPIOARCC->CFGR &= ~(0x03<<14);RCC->CFGR |= (0x02<<14);//6分频//2、配置IO模式(模拟输入)GPIOA->CRL &= ~(0x0F<<20);//配置成模拟输入//3、配置ADC的工作模式ADC1->CR1 &= ~(0x0F<<16);//独立模式ADC1->CR1 &= ~(0x01<<8);//不开扫描ADC1->CR2 |= 0x01<<20;//选择开启外部触发ADC1->CR2 |= 0x07<<17;//触发方式swsatrt(软件触发)ADC1->CR2 &= ~(0x01<<11);//选择数据右对齐ADC1->CR2 &= ~(0x01<<1);//关闭连续转换ADC1->CR2 |= 0x01<<0;//ADC使能//配置一个通道:通道5,第一个转换,采样周期最大(239.5)ADC1->SQR1 &= ~(0x0F<<20);//规则组通道只转换一个(配置通道数量)//具体某个通道的配置ADC1->SQR3 &= ~(0x1F<<0);//0-5位清0ADC1->SQR3 |= 0x05<<0;//选择第一个转换通道5ADC1->SMPR2 |= 0x07<<15;//采样周期最大(239.5)ADC1->CR2 |= 0x01<<3;//启动复位校准//等待复位校准结束while((ADC1->CR2&(0x01<<3))!=0)//判断寄存器的位3是不是等于1{}ADC1->CR2 |= 0x01<<2;//启动AD校准//等待AD校准结束while((ADC1->CR2&(0x01<<2))!=0)//判断寄存器的位2是不是等于1,是1就等待{}
}void GetLightValue()
{uint16_t Light=0;//让规则通道转换一次ADC1->CR2 |= 0x01<<22;while((ADC1->SR&(0x01<<1))==0)//判断寄存器的位2是不是等于1,是0就等待转换完成{}Light = ADC1->DR; //读规则组通道数据寄存器printf("光照强度参数 = %d \r\n",Light);
}

adc.h

#ifndef _ADC_H_
#define _ADC_H_
#include "stm32f10x.h"
#include "stdio.h"
void GetLightValue();void Adc_Config(void);
#endif

delay.c

#include "stm32f10x.h"
#include "delay.h"uint32_t systicktime=0;uint16_t ledcnt[2]={0,1000};//500ms   每个任务执行的时间
uint16_t led2cnt[2]={0,2000};//700ms
uint16_t keycnt[2]={0,10};//10ms检测一次
void SysTick_Handler(void)//1ms调用一次
{//不需要清中断挂起位systicktime++;ledcnt[0]++;led2cnt[0]++;keycnt[0]++;
}void Delay_ms(uint32_t time)
{uint32_t nowtime = systicktime;while(systicktime < time+nowtime);
}void Delay_nus(uint32_t time)
{uint32_t i=0;for(i=0;i<time;i++){delay1us();}    
}void Delay_nms(uint32_t time)
{uint32_t i=0;for(i=0;i<time;i++){Delay_nus(1000);//延时1ms}    
}

delay.h

#ifndef _DELAY_H_
#define _DELAY_H_
#include "stm32f10x.h"#define delay1us() {__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();}extern uint16_t ledcnt[2];
extern uint16_t led2cnt[2];
extern uint16_t keycnt[2];		void Delay_nus(uint32_t time);
void Delay_ms(uint32_t time);
void Delay_nms(uint32_t time);
#endif

总结

1.先看该光敏电阻的电路图,分析如何获取光照的数值。
2.想到可以通过ADC转换得到光照的树数值,开始学习ADC的知识。
3.先看ADC的功能描述,然后开时钟,分频,配IO。
4.看手册中的ADC的控制寄存器,一个一个查看,看看究竟需要配置那些。
5.看该引脚的ADC是那个通道的,开始配置通道。
6.都配置完后进行复位校准和数据获取函数的编写。
7.最后在主函数按照需求调用即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/37503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手机数据恢复篇:如何在Android手机上查找和恢复已删除的文件

移动设备中的回收站已成为 Android 用户的一项基本功能&#xff0c;它提供了防止意外删除的安全网。与计算机一样&#xff0c;移动回收站会临时存储已删除的文件&#xff0c;允许用户在需要时检索它们。此功能在当今的数字时代特别有用&#xff0c;因为只需轻轻一按&#xff0c…

SEO与AI的结合:如何用ChatGPT生成符合搜索引擎优化的内容

在当今数字时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已成为每个网站和内容创作者都必须掌握的一项技能。SEO的主要目标是通过优化内容&#xff0c;使其在搜索引擎结果页面&#xff08;SERP&#xff09;中排名更高&#xff0c;从而吸引更多的流量。然而&#xf…

硬件实用技巧:刚挠板pcb是什么

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140060334 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

elasticsearch导出和导入数据

这里我使用的是离线操作的方式&#xff0c; 前提&#xff1a;安装了node, 安装elasticdump命令&#xff1a; npm install elasticdump -g 安装成功后进入elasticdump所在的目录&#xff1a; cd /usr/local/nodejs/lib/node_modules/elasticdump/bin 导出目标索引的映射结构…

深入浅出:npm 常用命令详解与实践

在现代的前端开发流程中&#xff0c;npm&#xff08;Node Package Manager&#xff09;已经成为了不可或缺的一部分。它不仅帮助我们有效地管理项目中的依赖包&#xff0c;还提供了一系列强大的命令来优化开发体验。在这篇博客中&#xff0c;我们将深入探讨 npm 的常用命令&…

高频面试题基本总结回顾1(含笔试高频算法整理)

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…

【FFmpeg】avformat_write_header函数

FFmpeg相关记录&#xff1a; 示例工程&#xff1a; 【FFmpeg】调用ffmpeg库实现264软编 【FFmpeg】调用ffmpeg库实现264软解 【FFmpeg】调用ffmpeg库进行RTMP推流和拉流 【FFmpeg】调用ffmpeg库进行SDL2解码后渲染 流程分析&#xff1a; 【FFmpeg】编码链路上主要函数的简单分…

GPT-4o首次引入!全新图像自动评估基准发布!

目录 01 什么是DreamBench&#xff1f; 02 与人类对齐的自动化评估 03 更全面的个性化数据集 04 实验结果 面对层出不穷的个性化图像生成技术&#xff0c;一个新问题摆在眼前&#xff1a;缺乏统一标准来衡量这些生成的图片是否符合人们的喜好。 对此&#xff0c;来自清华大…

sql server启动、连接 与 navicat连接sql server

一、sql server 启动 1.搜索cmd->以管理员身份运行 2.输入以下命令 net start mssqlserver 3.服务器启动成功 二、sql server连接 1.打开ssms&#xff0c;输入&#xff0c;连接 2.右键&#xff0c;属性 3.连接&#xff0c;勾选允许远程连接到此服务器 三、navicat连接sq…

Python实现无头浏览器采集应用的反爬虫与反检测功能解析与应对策略

Python实现无头浏览器采集应用的反爬虫与反检测功能解析与应对策略 随着网络数据的快速增长&#xff0c;爬虫技术在数据采集、信息分析和业务发展中扮演着重要的角色。然而&#xff0c;随之而来的反爬虫技术也在不断升级&#xff0c;给爬虫应用的开发和维护带来了挑战。为了应…

媒体宣发套餐的概述及推广方法-华媒舍

在今天的数字化时代&#xff0c;对于产品和服务的宣传已经变得不可或缺。媒体宣发套餐作为一种高效的宣传方式&#xff0c;在帮助企业塑造品牌形象、扩大影响力方面扮演着重要角色。本文将揭秘媒体宣发套餐&#xff0c;为您呈现一条通往成功的路。 1. 媒体宣发套餐的概述 媒体…

MySQL中的存储引擎

介绍 存储引擎就是存储数据&#xff0c;建立索引&#xff0c;更新/查询数据等技术的实现方式。存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;所以存储引擎也可以称为表类型&#xff08;即一个数据库下的表可以选择不同的存储引擎&#xff09;。 1. 如何查看一个…

day57---面试专题(框架篇)

框架篇 1. Spring refresh 流程 要求 掌握 refresh 的 12 个步骤Spring refresh 概述 refresh 是 AbstractApplicationContext 中的一个方法,负责初始化 ApplicationContext 容器,容器必须调用 refresh 才能正常工作。它的内部主要会调用 12 个方法,我们把它们称为 refre…

收银系统源码-千呼新零售【手机端收银】

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

风风火火的新造车,或正在酝酿下一个乐视系,造车就是个大坑

随着国内新能源汽车占新车市场的比例突破五成&#xff0c;燃油车发起了猛烈的反击&#xff0c;5月份燃油车猛烈反弹&#xff0c;前五名之中就有5款是燃油车&#xff0c;燃油车到了背水一战的时候&#xff0c;随着电动汽车和燃油车的较量达到白热化&#xff0c;新造车被淘汰一部…

无视OpenAI限制:智创聚合API的稳定服务承诺

近期OpenAI的一则消息——终止对中国提供API服务&#xff0c;无疑给许多依赖其技术的企业和开发者带来了不小的困扰。但别担心&#xff0c;智创聚合API平台始终在这里&#xff0c;为您提供稳定、可靠且经济的AI服务。 稳定服务&#xff0c;不受限制 智创聚合API平台的服务器设在…

kafka(一)原理(2)组件

一、broker 1、介绍 kafka服务器的官方名字&#xff0c;一个集群由多个broker组成&#xff0c;一个broker可以容纳多个topic。 2、工作流程 3、重要参数 参数名称 描述 replica.lag.time.max.ms ISR中&#xff0c;如果Follower长时间未向Leader发送通信请求或同步数据&a…

MessageBox的作用与用法

在C# &#xff08; Windows Forms &#xff09;中&#xff0c;MessageBox 的所有常用用法如下&#xff1a; 1. 显示一个简单的消息框 MessageBox.Show("这是一个简单的消息框。");2. 显示带标题的消息框 MessageBox.Show("这是一个带标题的消息框。", &…

脉冲同步器(快到慢)

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 sig_a 是 clka&#xff08;300M&#xff09;时钟域的一个单时钟脉冲信号&#xff08;高电平持续一个时钟clka周期&#xff09;&#xff0c;请设计脉冲同步电路&#xff0c;将sig_a信号同步到时钟域 cl…