直流有刷驱动板电流电压采集

news2024/11/22 23:40:24

直流有刷驱动板电流电压采集

电流采集会涉及到电流环的使用。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include "./adc/bsp_adc.h"
#include ".\motor_control\bsp_motor_control.h"
#include "./led/bsp_led.h" 
#include "./usart/bsp_debug_usart.h"

__IO uint16_t ADC_ConvertedValue;
DMA_HandleTypeDef DMA_Init_Handle;
ADC_HandleTypeDef ADC_Handle;

static uint16_t adc_buff[ADC_NUM_MAX];    // 电压采集缓冲区
static uint16_t vbus_adc_mean = 0;        // 电源电压 ACD 采样结果平均值
static uint32_t adc_mean_sum = 0;        // 平均值累加
static uint32_t adc_mean_count = 0;      // 累加计数

/**
  * @brief  ADC 通道引脚初始化
  * @param  无
  * @retval 无
  */
static void ADC_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    // 使能 GPIO 时钟
    CURR_ADC_GPIO_CLK_ENABLE();
    VBUS_GPIO_CLK_ENABLE();
    // 配置 IO
    GPIO_InitStructure.Pin = CURR_ADC_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;	    
    GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉
    HAL_GPIO_Init(CURR_ADC_GPIO_PORT, &GPIO_InitStructure);	

    GPIO_InitStructure.Pin = VBUS_GPIO_PIN;
    HAL_GPIO_Init(VBUS_GPIO_PORT, &GPIO_InitStructure);	
}

void adc_dma_init(void)
{
    // ------------------DMA Init 结构体参数 初始化--------------------------
    // ADC1使用DMA2,数据流0,通道0,这个是手册固定死的
    // 开启DMA时钟
    CURR_ADC_DMA_CLK_ENABLE();
    // 数据传输通道
    DMA_Init_Handle.Instance = CURR_ADC_DMA_STREAM;
    // 数据传输方向为外设到存储器	
    DMA_Init_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
    // 外设寄存器只有一个,地址不用递增
    DMA_Init_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
    // 存储器地址固定
    DMA_Init_Handle.Init.MemInc = DMA_MINC_ENABLE;
    // 外设数据大小为半字,即两个字节
    DMA_Init_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    //	存储器数据大小也为半字,跟外设数据大小相同
    DMA_Init_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;	
    // 循环传输模式
    DMA_Init_Handle.Init.Mode = DMA_CIRCULAR;
    // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
    DMA_Init_Handle.Init.Priority = DMA_PRIORITY_HIGH;
    // 禁止DMA FIFO	,使用直连模式
    DMA_Init_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;  
    // FIFO 大小,FIFO模式禁止时,这个不用配置
    DMA_Init_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
    DMA_Init_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
    DMA_Init_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;  
    // 选择 DMA 通道,通道存在于流中
    DMA_Init_Handle.Init.Channel = CURR_ADC_DMA_CHANNEL; 
    //初始化DMA流,流相当于一个大的管道,管道里面有很多通道
    HAL_DMA_Init(&DMA_Init_Handle); 

    __HAL_LINKDMA(&ADC_Handle,DMA_Handle,DMA_Init_Handle);
}

/**
  * @brief  ADC 和 DMA 初始化
  * @param  无
  * @retval 无
  */
static void ADC_Mode_Config(void)
{
    // 开启ADC时钟
    CURR_ADC_CLK_ENABLE();
    // -------------------ADC Init 结构体 参数 初始化------------------------
    // ADC1
    ADC_Handle.Instance = CURR_ADC;
    // 时钟为fpclk 4分频	
    ADC_Handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
    // ADC 分辨率
    ADC_Handle.Init.Resolution = ADC_RESOLUTION_12B;
    // 禁止扫描模式,多通道采集才需要	
    ADC_Handle.Init.ScanConvMode = ENABLE; 
    // 连续转换	
    ADC_Handle.Init.ContinuousConvMode = ENABLE;
    // 非连续转换	
    ADC_Handle.Init.DiscontinuousConvMode = DISABLE;
    // 非连续转换个数
    ADC_Handle.Init.NbrOfDiscConversion   = 0;
    //禁止外部边沿触发    
    ADC_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    //使用软件触发
    ADC_Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    //数据右对齐
    ADC_Handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    //转换通道 2个
    ADC_Handle.Init.NbrOfConversion = 2;
    //使能连续转换请求
    ADC_Handle.Init.DMAContinuousRequests = ENABLE;
    //转换完成标志
    ADC_Handle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;    
    // 初始化ADC	                          
    HAL_ADC_Init(&ADC_Handle);
    
    //---------------------------------------------------------------------------
    ADC_ChannelConfTypeDef ADC_Config;
    
    ADC_Config.Channel      = CURR_ADC_CHANNEL;
    ADC_Config.Rank         = 1;
    // 采样时间间隔	
    ADC_Config.SamplingTime = ADC_SAMPLETIME_3CYCLES;
    ADC_Config.Offset       = 0;
    // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期
    HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config);
    
    /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
    ADC_Config.Channel = VBUS_ADC_CHANNEL;
    ADC_Config.Rank = 2;
    // 采样时间间隔	
    ADC_Config.SamplingTime = ADC_SAMPLETIME_3CYCLES;
    ADC_Config.Offset       = 0;
    if (HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config) != HAL_OK)
    {
      while(1);
    }
    
    // 外设中断优先级配置和使能中断配置
    HAL_NVIC_SetPriority(ADC_DMA_IRQ, 1, 1);
    HAL_NVIC_EnableIRQ(ADC_DMA_IRQ);

    HAL_ADC_Start_DMA(&ADC_Handle, (uint32_t*)&adc_buff, ADC_NUM_MAX);
}

/**
  * @brief  电流采集初始化
  * @param  无
  * @retval 无
  */
void ADC_Init(void)
{
	ADC_GPIO_Config();
  adc_dma_init();
	ADC_Mode_Config();
}

/**
  * @brief  常规转换在非阻塞模式下完成回调
  * @param  hadc: ADC  句柄.
  * @retval 无
  */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  uint32_t adc_mean = 0;

  HAL_ADC_Stop_DMA(hadc);       // 停止 ADC 采样,处理完一次数据在继续采样
  
  /* 计算电流通道采样的平均值 */
  for(uint32_t count = 0; count < ADC_NUM_MAX; count+=2)
  {
    adc_mean += (uint32_t)adc_buff[count];
  }
  
  adc_mean_sum += adc_mean / (ADC_NUM_MAX / 2);    // 累加电压
  adc_mean_count++;
  
#if 1
  
  adc_mean = 0;
  
  /* 计算电压通道采样的平均值 */
  for(uint32_t count = 1; count < ADC_NUM_MAX; count+=2)
  {
    adc_mean += (uint32_t)adc_buff[count];
  }
  
  vbus_adc_mean = adc_mean / (ADC_NUM_MAX / 2);    // 保存平均值
  
#else
  vbus_adc_mean = adc_buff[1];
#endif
  
  HAL_ADC_Start_DMA(&ADC_Handle, (uint32_t*)&adc_buff, ADC_NUM_MAX);    // 开始 ADC 采样
}

/**
  * @brief  获取电流值
  * @param  无
  * @retval 转换得到的电流值
  */
int32_t get_curr_val(void)
{
  static uint8_t flag = 0;
  static uint32_t adc_offset = 0;    // 偏置电压
  int16_t curr_adc_mean = 0;         // 电流 ACD 采样结果平均值
  
  curr_adc_mean = adc_mean_sum / adc_mean_count;    // 保存平均值
  

    adc_mean_count = 0;
    adc_mean_sum = 0;
    
    if (flag < 17)
    {
      adc_offset = curr_adc_mean;    // 多次记录偏置电压,待系统稳定偏置电压才为有效值
      flag += 1;
    }
    if(curr_adc_mean>=adc_offset)
	{
		curr_adc_mean -= adc_offset;                     // 减去偏置电压
	}else
	{
		curr_adc_mean=0;
	}


  float vdc = GET_ADC_VDC_VAL(curr_adc_mean);      // 获取电压值
  
  return GET_ADC_CURR_VAL(vdc);
}

/**
  * @brief  获取电源电压值
  * @param  无
  * @retval 转换得到的电流值
  */
float get_vbus_val(void)
{
  float vdc = GET_ADC_VDC_VAL(vbus_adc_mean);      // 获取电压值
  
  return GET_VBUS_VAL(vdc);
}

/*********************************** END OF FILE *********************************************/

#ifndef __BSP_ADC_H
#define	__BSP_ADC_H

#include "stm32f4xx.h"

// ADC 序号宏定义
#define CURR_ADC                        ADC1
#define CURR_ADC_CLK_ENABLE()           __ADC1_CLK_ENABLE()

#define ADC_VBUS_IRQ                    ADC_IRQn
#define ADC_VBUS_IRQHandler             ADC_IRQHandler

#define VREF                            3.3f     // 参考电压,理论上是3.3,可通过实际测量得3.258
#define ADC_NUM_MAX                     2048       // ADC 转换结果缓冲区最大值

#define GET_ADC_VDC_VAL(val)            ((float)val/(float)4096.0f*VREF)          // 得到电压值
  
/*********************** 电流采集 ******************/
// ADC GPIO 宏定义
#define CURR_ADC_GPIO_PORT              GPIOB
#define CURR_ADC_GPIO_PIN               GPIO_PIN_1
#define CURR_ADC_GPIO_CLK_ENABLE()      __GPIOB_CLK_ENABLE()

#define CURR_ADC_CHANNEL                ADC_CHANNEL_9

// ADC DR寄存器宏定义,ADC转换后的数字值则存放在这里
#define CURR_ADC_DR_ADDR                ((uint32_t)ADC1+0x4c)

// ADC DMA 通道宏定义,这里我们使用DMA传输
#define CURR_ADC_DMA_CLK_ENABLE()       __DMA2_CLK_ENABLE()
#define CURR_ADC_DMA_CHANNEL            DMA_CHANNEL_0
#define CURR_ADC_DMA_STREAM             DMA2_Stream0

#define ADC_DMA_IRQ                     DMA2_Stream0_IRQn
#define ADC_DMA_IRQ_Handler             DMA2_Stream0_IRQHandler

#define GET_ADC_CURR_VAL(val)           (((float)val)/(float)8.0/(float)0.02*(float)1000.0)          // 得到电流值,电压放大8倍,0.02是采样电阻,单位mA。

/*********************** 电源电压采集 ******************/

#define VBUS_GPIO_PORT                  GPIOB
#define VBUS_GPIO_PIN                   GPIO_PIN_0
#define VBUS_GPIO_CLK_ENABLE()          __GPIOB_CLK_ENABLE()

#define VBUS_ADC_CHANNEL                ADC_CHANNEL_8

#define GET_VBUS_VAL(val)               (((float)val-(float)1.24) * (float)37.0)      // 电压最大值(测量电压是电源电压的1/37)

extern DMA_HandleTypeDef DMA_Init_Handle;
extern ADC_HandleTypeDef ADC_Handle;

void ADC_Init(void);
int32_t get_curr_val(void);
float get_vbus_val(void);
 
#endif /* __BSP_ADC_H */

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

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

相关文章

vue-element-admin深入系列-数据Mock

本文介绍 vue-element-admin 如何使用 MockJS 实现数据Mock,毕竟对于一个合格的前端来讲,自己能Mock数据是必须的: 自给自足,不用依赖服务端接口。毕竟环境问题是个大问题,更何况环境不稳定是常态,再加上偶尔服务端的数据格式变化,问题就更复杂。 数据复杂,页面复杂时。…

HackTheBox - 学院【CPTS】复习6 - Active Directory

ACTIVE DIRECTORY ENUMERATION & ATTACKS 这个模块其实与thm的AD教程相比&#xff0c;还是thm更适合刚开始接触AD以及学习从枚举到持久化的全阶段&#xff08;红队&#xff09;。而htb学院这个模块更注重于枚举和各种攻击手段&#xff0c;有点纯渗透的风格&#xff0c;弱化…

通过动态IP解决网络数据采集问题

动态地址的作用 说到Python网络爬虫&#xff0c;很多人都会遇到困难。最常见的就是爬取过程中IP地址被屏蔽。虽然大部分都是几个小时内自动解封的&#xff0c;但这对于分秒必争的python网络爬虫来说&#xff0c;是一个关键性的打击&#xff01;当一个爬虫被阻塞时&#xff0c;…

Java内部类笔记

1.为什么使用内部类? 使用内部类最吸引人的原因是&#xff1a;每个内部类都能独立地继承一个&#xff08;接口的&#xff09;实现&#xff0c;所以无论外围类是否已经继承了某个&#xff08;接口的&#xff09;实现&#xff0c; 对于内部类都没有影响 1.1.使用内部类最大的优点…

TCP/IP基础知识笔记

应用层&#xff1a;为用户提供应用功能&#xff0c;比如 HTTP、FTP、Telnet、DNS、SMTP等。 应用层是工作在操作系统中的用户态&#xff0c;传输层及以下则工作在内核态。 传输层&#xff1a;为应用层提供网络支持。 *TCP包含众多特性比如流量控制、超时重传、拥塞控制等因此可…

pytorch深度学习逻辑回归 logistic regression

# logistic regression 二分类 # 导入pytorch 和 torchvision import numpy as np import torch import torchvision from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import matplotlib.pyplot as …

(简单)剑指Offer II 056. 二叉搜索树中两个节点的和 Java

方法一&#xff1a;深度优先搜索哈希表 使用深度优先搜索的方式遍历整棵树&#xff0c;用哈希表记录遍历过的节点的值 对于一个值为x的节点&#xff0c;检查哈希表中是否存在k-x即可。如果存在对应的元素&#xff0c;那么我们就可以在该树上找到两个节点的和为k&#xff1b;否…

河流垃圾检测Y8S

【免费】河流垃圾检测Y8M&#xff0c;只需要OPENCV资源-CSDN文库 采用YOLOV8训练&#xff0c;得到PT模型&#xff0c;然后直接转ONNX&#xff0c;使用OPENCV的DNN&#xff0c;不需要其他依赖&#xff0c;支持C/PYTHON

Hadoop 之 分布式集群配置与使用(三)

Hadoop 之 分布式集群 一.集群实例创建二.配置1.创建三个虚拟机&#xff08;Anolis&#xff09;1.修改 HostName2.配置免密登录&#xff0c;配置前 2.配置命名节点1.在 nd1 / nd2 部署 hadoop2.配置 3.查看集群信息 三.测试 一.集群实例创建 以三个 Hadoop 实例创建集群&#…

对战五子棋——网页版

目录 一、项目简介 二、用户模块 1、创建用户实体类 2、编写userMapper接口文件 3、实现userMapper.xml文件 4、对用户密码进行加密 5、实现用户登录功能 6、实现用户注册功能 三、实现用户匹配模块 1、展示用户个人信息 2、匹配请求类 3、匹配响应类 4、创…

郭东白的架构课学习笔笔记(1)

1.架构师的品质 自信和勇气&#xff08;正确的废话&#xff09;拥有战略意图&#xff0c;所谓战略意图&#xff0c;就是拥有与其资源和能力极不相称的雄心壮志。使用演绎法寻找架构原理&#xff0c;而不是归纳法。 2.如何提升自己的架构能力 向身边比自己厉害的优秀架构师或…

【网络安全带你练爬虫-100练】第14练:文件内容的读取、取出

目录 一、目标1&#xff1a;把文件内容遍历取出 二、目标2&#xff1a;把文件内容全部取出 三、网络安全O 一、目标1&#xff1a;把文件内容遍历取出 &#xff08;1&#xff09;如果文件脚本在不同目录 file_path "path/to/your/file.txt" # 替换为你的文件路径…

【Gradle】Gradle之JVM进程详解

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…

【机密计算组织】机密计算联盟

一、简介 1.1 机密计算联盟与成员 2019年8月22日&#xff0c;Linux基金会宣布多家巨头企业组建“机密计算联盟”&#xff08;Confidential Computing Consortium&#xff09;&#xff0c;该基金将负责对联盟活动进行监督。机密计算联盟专门针对云服务及硬件生态&#xff0c;致…

SpringBoot中注入ServletFilterListener

1.基本介绍 文档&#xff1a;SpringBoot中注入Servlet&Filter&Listener 考虑到实际开发业务非常复杂和兼容问题&#xff0c;SpringBoot支持将Servlet、Filter、Listener注入spring容器中&#xff0c;成为Spring Bean也就是说&#xff0c;SpringBoot开放了和原生WEB组件…

关于初识MySQL数据库以及MySQL的基本使用

文章目录 什么是数据库什么是MySQL为什么要有数据库 MySQL基本使用连接mysql查看当前服务器对应的数据库创建数据库进入某个数据库建立一张表向表中插入数据查询表中的数据 服务器&#xff0c;数据库&#xff0c;表之间的关系数据逻辑存储MySQL架构SQL语句分类存储引擎 什么是数…

vue-cesium的基本使用【一】

最近的项目中用到了cesium,也了解了一点关于cesium的知识&#xff0c;打点、 标绘、等等基础的功能点&#xff0c;但是在开发过程中使用原生的cesium编写对于初学者还是有点难度&#xff0c;为此&#xff0c;找到关于对cesium进行二次封装的开源项目vue-cesium,本次文章主要记录…

Git原理与基本操作(含安装教程)

Git Git初识Git安装Linux-centosLinux-ubuntu Git基本操作git int配置Git 认识⼯作区、暂存区、版本库添加⽂件--场景⼀git add、git commitgit log 查看.git⽂件git cat-file 添加⽂件--场景⼆修改⽂件git statusgit diff [file]、git diff HEAD -- [file] 版本回退git resetg…

聊一下2023前端状况

2023已过大半&#xff0c;也是疫情后开放的第一年&#xff0c;想必大家都能感受到 各行各业一定程度上都在萎缩&#xff0c;线下一些工厂招聘&#xff0c;喊着90年以前的&#xff0c;可以回家了的 今年出现频率最高的一词就是裁员&#xff0c;失业&#xff0c;大学生慢就业 互联…

【从零开始学习Linux】背景知识与获取环境

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 本期给大家带来的是 Linux 操作系统的简介&#xff0c;以及如何获取一个Linux 的环境&#xff0c;作为Linux 章节起始篇&#xff0c;如果不妥之处&#xff0c;欢迎批评指正~ 本期收录于博主…