【STM32多路温控—第三章】ADC多通道采样,及数据上报

2023-10-12 20:39

本文主要是介绍【STM32多路温控—第三章】ADC多通道采样,及数据上报,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 头文件定义

/* Define to prevent recursive inclusion ----------------------------------------------------------------*/
#ifndef __ADC1_TRANS_H__
#define __ADC1_TRANS_H__/*********************************************************************************************************/
/* 包含头文件 -------------------------------------------------------------------------------------------*/
#include "application.h"/* 宏定义 -----------------------------------------------------------------------------------------------*/\
#define   ChannelNum                   13 
#define   SampNum                      10        //采样次数,使用平均滤波,采样10次取均值
#define   ArrayNum                     130        //缓存
#define   B                              3435           //B值,温度系数
#define   TN                             292.5         //额定温度(绝对温度加常温:273.15+25)
#define   RN                             10           //额定阻值(绝对温度下时的电阻值10K)
#define   R2                             100         //分压电阻100K
#define   BaseVol                        3.281        //ADC基准电压#define ad1  0
#define ad2  1
#define ad3  2
#define ad4  3 
#define ad5  4 
#define ad6  5 
#define ad7  6
#define ad8  7
#define ad9  8
#define ad10  9 
#define ad11  10 
#define ad12  11
#define ad13  12
#define ad14  13extern int16_t *adctmpcontrol;                        // 定义数组指针变量
extern float *adctmparray;
/* 函数声明 ---------------------------------------------------------------------------------------------*/
void ADC1_Init(void);
void Adc_Handle(void);
uint16_t Get_Tempture_Value(uint16_t chx);
void Output_Tempture(void); 
void Get_Bus_Current(void);/* 扩展变量 ---------------------------------------------------------------------------------------------*/#endif 

c文件定义

定义一系列数组存放数据

static uint32_t  AdcArrayLib[ArrayNum]={0};           // 13个ADC通道的10次采样缓存
static uint32_t  Adc2dArray[SampNum][ChannelNum];     // AD转换结果缓存,10行6列
static uint16_t  AdcFilterArray[ChannelNum];          // 滤波数组
static float     AdcVoltArray[ChannelNum];            // 用于保存转换计算后的电压值		

定义温度数组以及数组指针

static float     AdcTmpArray[ChannelNum];             // 用于保存转换计算后的温度值
float *adctmparray = AdcTmpArray;                     // 定义数组指针变量static int16_t   AdcTmpControl[ChannelNum];
int16_t *adctmpcontrol = AdcTmpControl;               // 定义数组指针变量

封装ADC初始化

void ADC1_Init(void)
{MX_ADC1_Init();
//   HAL_ADCEx_Calibration_Start(&hadc1);//ADC初始化后要进行校准,开启后不准确HAL_ADC_Start_DMA(&hadc1, AdcArrayLib, ArrayNum); 
}

处理DMA采集的数据

void Adc_Handle(void)
{uint8_t i,j,n,m;int sum = 0;float RT;for(n = 0; n < SampNum; n++){for(m = 0; m < ChannelNum; m++){Adc2dArray[n][m] = AdcArrayLib[n*ChannelNum+m]; }            }      for(i = 0; i < ChannelNum; i++){for(j = 0; j < SampNum; j++){sum += Adc2dArray[j][i];}AdcFilterArray[i] = sum/SampNum;sum = 0;}for(i = 0; i < ChannelNum; i++){AdcVoltArray[i] = (double)(AdcFilterArray[i] & 0xFFF) * BaseVol / 4096; // NTC电压RT = AdcVoltArray[i] * 100 / (BaseVol-AdcVoltArray[i]); // 求出当前温度下的阻值,由串联分压得AdcTmpArray[i] = 1 / (1 / TN + (log(RT / RN) / B)) - 273.15; // RT=RN*exp*B(1/T-1/TN)-273.5AdcTmpControl[i]=ROUND_TO_INT16_1(AdcTmpArray[i]);}    
}

输出温度值

我们利用上位机对MCU发送指令,意图就是根据发送的指令数值改变其中的参数值,或者执行相关函数。因此接收字节的处理这部分也是值得研究和学习的。

首先对数据结构进行确定。数据类型我们依然可以使用结构体进行定义。

typedef union {char Ch[2]; uint16_t Int;
}Format_UnionTypedef;typedef struct {__IO uint8_t  Code;  	__IO Format_UnionTypedef data[13];//数据帧有13个参数
}MSG_TypeDef;

我们首先定义一个结构体,该结构体里面有两个数据类型,一个是具有13个参数的共同体数组,另一个是一个字节的参数Code,使用来存放帧头,帧尾和校验和。13个参数对应的是要发送的13个16位的温度值,也就是占用两个字节。可以考到这个数据串共占用3+13*2=29个字节。

我们在定义一个共同体,我们再了解一下共同体的区别。

结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。

基于上述的数据类型的建成,我们就开始讨论一下对接收和发送数据的编排构建了。

首先将数据长度的数组进行填充覆盖,就是将定义的发送数据帧长度的数组进行填充,我们这里填充值是FILL_VALUE = 0x00。

填充完毕后再利用定义的数据规则对上述填充后的数组进行原位覆盖,我们要用到将之前定义的数据结构体变量,那么我们就要声明一个新的结构体变量。

MSG_TypeDef Msg;

  Msg.data[0].Int = Get_Tempture_Value(0);//ad1

我们将数据的第一位,转化成16进制数据存入uint16-t的数据类型中。

  sendBuffer[2] = Msg.data[0].Ch[0];
  sendBuffer[3] = Msg.data[0].Ch[1]; 

并将其拆分为一个低位和一个高位,装入输入的第2和第3位发送出去。

  sendBuffer[0] = FRAME_START;   // 帧头
  sendBuffer[1] = 0x80|0x08; // 指令码

帧头和指令码各占用一位。

sendBuffer[FRAME_CHECKSUM] = CheckSum((uint8_t*)&sendBuffer[FRAME_CHECK_BEGIN],FRAME_CHECK_NUM);  // 计算校验和
sendBuffer[FRAME_LENTH-1] = FRAME_END;   // 加入帧尾


HAL_UART_Transmit(&huart3,(uint8_t *)&sendBuffer,FRAME_LENTH,0xffff); // 发送数据帧

void Transmit_Feedback(void)
{uint8_t i = 0;for(i=0;i<FRAME_LENTH;i++){sendBuffer[i] = FILL_VALUE;  // 参数填充 0x00}Msg.data[0].Int = Get_Tempture_Value(0);//ad1Msg.data[1].Int = Get_Tempture_Value(1);//ad2  sendBuffer[0] = FRAME_START;   // 帧头sendBuffer[1] = 0x80|0x08; // 指令码sendBuffer[2] = Msg.data[0].Ch[0];sendBuffer[3] = Msg.data[0].Ch[1]; sendBuffer[FRAME_CHECKSUM] = CheckSum((uint8_t*)&sendBuffer[FRAME_CHECK_BEGIN],FRAME_CHECK_NUM);  // 计算校验和sendBuffer[FRAME_LENTH-1] = FRAME_END;   // 加入帧尾HAL_UART_Transmit(&huart3,(uint8_t *)&sendBuffer,FRAME_LENTH,0xffff); // 发送数据帧
}
uint16_t Get_Tempture_Value(uint16_t adx)
{switch(adx){case ad1:return ROUND_TO_INT16_10(AdcTmpArray[0]);case ad2:return ROUND_TO_INT16_10(AdcTmpArray[1]);case ad3:return ROUND_TO_INT16_10(AdcTmpArray[2]);default:break; 	}return 0;
}

输出

void Output_Tempture(void) 
{Adc_Handle();
#if     NOUSECOM == 0Transmit_Feedback();
#else   uint8_t i;      for(i = 0; i < ChannelNum; i++){    
//            printf("通道%d value = %d -> %fV -> %f℃\n",i,AdcFilterArray[i]&0xFFF,AdcVoltArray[i],AdcTmpArray[i]);printf("%d=%f\n;",i,AdcTmpArray[i]); 
//          printf("当前电压为=%f, 母线电流为=%f;",AdcVoltArray[6],BusCurrent);       }  
#endif
}

这篇关于【STM32多路温控—第三章】ADC多通道采样,及数据上报的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

使用SpringBoot+InfluxDB实现高效数据存储与查询

《使用SpringBoot+InfluxDB实现高效数据存储与查询》InfluxDB是一个开源的时间序列数据库,特别适合处理带有时间戳的监控数据、指标数据等,下面详细介绍如何在SpringBoot项目... 目录1、项目介绍2、 InfluxDB 介绍3、Spring Boot 配置 InfluxDB4、I

Java整合Protocol Buffers实现高效数据序列化实践

《Java整合ProtocolBuffers实现高效数据序列化实践》ProtocolBuffers是Google开发的一种语言中立、平台中立、可扩展的结构化数据序列化机制,类似于XML但更小、更快... 目录一、Protocol Buffers简介1.1 什么是Protocol Buffers1.2 Pro

Python实现数据可视化图表生成(适合新手入门)

《Python实现数据可视化图表生成(适合新手入门)》在数据科学和数据分析的新时代,高效、直观的数据可视化工具显得尤为重要,下面:本文主要介绍Python实现数据可视化图表生成的相关资料,文中通过... 目录前言为什么需要数据可视化准备工作基本图表绘制折线图柱状图散点图使用Seaborn创建高级图表箱线图热

MySQL数据脱敏的实现方法

《MySQL数据脱敏的实现方法》本文主要介绍了MySQL数据脱敏的实现方法,包括字符替换、加密等方法,通过工具类和数据库服务整合,确保敏感信息在查询结果中被掩码处理,感兴趣的可以了解一下... 目录一. 数据脱敏的方法二. 字符替换脱敏1. 创建数据脱敏工具类三. 整合到数据库操作1. 创建服务类进行数据库

MySQL中处理数据的并发一致性的实现示例

《MySQL中处理数据的并发一致性的实现示例》在MySQL中处理数据的并发一致性是确保多个用户或应用程序同时访问和修改数据库时,不会导致数据冲突、数据丢失或数据不一致,MySQL通过事务和锁机制来管理... 目录一、事务(Transactions)1. 事务控制语句二、锁(Locks)1. 锁类型2. 锁粒