【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  13


extern 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.5
      AdcTmpControl[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);//ad1
  Msg.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 == 0
        Transmit_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
}

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米杰的声音

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值