zerorobert 发表于 2025-1-10 21:39

PH传感器的电压是如何转换为pH数值

PH传感器的电压转换为pH数值的代码?要求有试剂验证过程的,加上温度修正的。

51xlf 发表于 2025-1-10 22:09

/*!
* @file DFRobot_PH.cpp
* @brief Arduino library for Gravity: Analog pH Sensor / Meter Kit V2, SKU: SEN0161-V2
*
* @CopyRight   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
* @license   The MIT License (MIT)
* @author (jiawei.zhang@dfrobot.com)
* @versionV1.0
* @date2018-11-06
* @url https://github.com/DFRobot/DFRobot_PH
*/


#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "DFRobot_PH.h"
#include <EEPROM.h>

#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp);}
#define EEPROM_read(address, p){int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp=EEPROM.read(address+i);}

#define PHVALUEADDR 0x00    //the start address of the pH calibration parameters stored in the EEPROM

char* DFRobot_PH::strupr(char* str) {
    if (str == NULL) return NULL;
    char *ptr = str;
    while (*ptr != ' ') {
      *ptr = toupper((unsigned char)*ptr);
      ptr++;
    }
    return str;
}

DFRobot_PH::DFRobot_PH()
{
    this->_temperature    = 25.0;
    this->_phValue      = 7.0;
    this->_acidVoltage    = 2032.44;    //buffer solution 4.0 at 25C
    this->_neutralVoltage = 1500.0;   //buffer solution 7.0 at 25C
    this->_voltage      = 1500.0;
}

DFRobot_PH::~DFRobot_PH()
{

}

void DFRobot_PH::begin()
{
    EEPROM_read(PHVALUEADDR, this->_neutralVoltage);//load the neutral (pH = 7.0)voltage of the pH board from the EEPROM
    //Serial.print("_neutralVoltage:");
    //Serial.println(this->_neutralVoltage);
    if(EEPROM.read(PHVALUEADDR)==0xFF && EEPROM.read(PHVALUEADDR+1)==0xFF && EEPROM.read(PHVALUEADDR+2)==0xFF && EEPROM.read(PHVALUEADDR+3)==0xFF){
      this->_neutralVoltage = 1500.0;// new EEPROM, write typical voltage
      EEPROM_write(PHVALUEADDR, this->_neutralVoltage);
    }
    EEPROM_read(PHVALUEADDR+4, this->_acidVoltage);//load the acid (pH = 4.0) voltage of the pH board from the EEPROM
    //Serial.print("_acidVoltage:");
    //Serial.println(this->_acidVoltage);
    if(EEPROM.read(PHVALUEADDR+4)==0xFF && EEPROM.read(PHVALUEADDR+5)==0xFF && EEPROM.read(PHVALUEADDR+6)==0xFF && EEPROM.read(PHVALUEADDR+7)==0xFF){
      this->_acidVoltage = 2032.44;// new EEPROM, write typical voltage
      EEPROM_write(PHVALUEADDR+4, this->_acidVoltage);
    }
}

float DFRobot_PH::readPH(float voltage, float temperature)
{
    float slope = (7.0-4.0)/((this->_neutralVoltage-1500.0)/3.0 - (this->_acidVoltage-1500.0)/3.0);// two point: (_neutralVoltage,7.0),(_acidVoltage,4.0)
    float intercept =7.0 - slope*(this->_neutralVoltage-1500.0)/3.0;
    //Serial.print("slope:");
    //Serial.print(slope);
    //Serial.print(",intercept:");
    //Serial.println(intercept);
    this->_phValue = slope*(voltage-1500.0)/3.0+intercept;//y = k*x + b
    return _phValue;
}


void DFRobot_PH::calibration(float voltage, float temperature,char* cmd)
{
    this->_voltage = voltage;
    this->_temperature = temperature;
    String sCmd = String(cmd);
    sCmd.toUpperCase();
    phCalibration(cmdParse(sCmd.c_str()));// if received Serial CMD from the serial monitor, enter into the calibration mode
}

void DFRobot_PH::calibration(float voltage, float temperature)
{
    this->_voltage = voltage;
    this->_temperature = temperature;
    if(cmdSerialDataAvailable() > 0){
      phCalibration(cmdParse());// if received Serial CMD from the serial monitor, enter into the calibration mode
    }
}

boolean DFRobot_PH::cmdSerialDataAvailable()
{
    char cmdReceivedChar;
    static unsigned long cmdReceivedTimeOut = millis();
    while(Serial.available()>0){
      if(millis() - cmdReceivedTimeOut > 500U){
            this->_cmdReceivedBufferIndex = 0;
            memset(this->_cmdReceivedBuffer,0,(ReceivedBufferLength));
      }
      cmdReceivedTimeOut = millis();
      cmdReceivedChar = Serial.read();
      if (cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex==ReceivedBufferLength-1){
            this->_cmdReceivedBufferIndex = 0;
            strupr(this->_cmdReceivedBuffer);
            return true;
      }else{
            this->_cmdReceivedBuffer = cmdReceivedChar;
            this->_cmdReceivedBufferIndex++;
      }
    }
    return false;
}

byte DFRobot_PH::cmdParse(const char* cmd)
{
    byte modeIndex = 0;
    if(strstr(cmd, "ENTERPH")      != NULL){
      modeIndex = 1;
    }else if(strstr(cmd, "EXITPH") != NULL){
      modeIndex = 3;
    }else if(strstr(cmd, "CALPH")!= NULL){
      modeIndex = 2;
    }
    return modeIndex;
}

byte DFRobot_PH::cmdParse()
{
    byte modeIndex = 0;
    if(strstr(this->_cmdReceivedBuffer, "ENTERPH")      != NULL){
      modeIndex = 1;
    }else if(strstr(this->_cmdReceivedBuffer, "EXITPH") != NULL){
      modeIndex = 3;
    }else if(strstr(this->_cmdReceivedBuffer, "CALPH")!= NULL){
      modeIndex = 2;
    }
    return modeIndex;
}

void DFRobot_PH::phCalibration(byte mode)
{
    char *receivedBufferPtr;
    static boolean phCalibrationFinish= 0;
    static boolean enterCalibrationFlag = 0;
    switch(mode){
      case 0:
      if(enterCalibrationFlag){
            Serial.println(F(">>>Command Error<<<"));
      }
      break;

      case 1:
      enterCalibrationFlag = 1;
      phCalibrationFinish= 0;
      Serial.println();
      Serial.println(F(">>>Enter PH Calibration Mode<<<"));
      Serial.println(F(">>>Please put the probe into the 4.0 or 7.0 standard buffer solution<<<"));
      Serial.println();
      break;

      case 2:
      if(enterCalibrationFlag){
            if((this->_voltage>1322)&&(this->_voltage<1678)){      // buffer solution:7.0{
                Serial.println();
                Serial.print(F(">>>Buffer Solution:7.0"));
                this->_neutralVoltage =this->_voltage;
                Serial.println(F(",Send EXITPH to Save and Exit<<<"));
                Serial.println();
                phCalibrationFinish = 1;
            }else if((this->_voltage>1854)&&(this->_voltage<2210)){//buffer solution:4.0
                Serial.println();
                Serial.print(F(">>>Buffer Solution:4.0"));
                this->_acidVoltage =this->_voltage;
                Serial.println(F(",Send EXITPH to Save and Exit<<<"));
                Serial.println();
                phCalibrationFinish = 1;
            }else{
                Serial.println();
                Serial.print(F(">>>Buffer Solution Error Try Again<<<"));
                Serial.println();                                    // not buffer solution or faulty operation
                phCalibrationFinish = 0;
            }
      }
      break;

      case 3:
      if(enterCalibrationFlag){
            Serial.println();
            if(phCalibrationFinish){
                if((this->_voltage>1322)&&(this->_voltage<1678)){

                  EEPROM_write(PHVALUEADDR, this->_neutralVoltage);
                }else if((this->_voltage>1854)&&(this->_voltage<2210)){
                  EEPROM_write(PHVALUEADDR+4, this->_acidVoltage);
                }
                Serial.print(F(">>>Calibration Successful"));
            }else{
                Serial.print(F(">>>Calibration Failed"));
            }
            Serial.println(F(",Exit PH Calibration Mode<<<"));
            Serial.println();
            phCalibrationFinish= 0;
            enterCalibrationFlag = 0;
      }
      break;
    }
}

lsc501 发表于 2025-2-14 11:12

PH传感器的电压是如何转换为pH数值

/******************************************************************************
* Copyright (C) 2018, Huada Semiconductor Co.,Ltd All rights reserved.
*
* This software is owned and published by:
* Huada Semiconductor Co.,Ltd ("HDSC").
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with HDSC
* components. This software is licensed by HDSC to be adapted only
* for use in systems utilizing HDSC components. HDSC shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. HDSC is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* Disclaimer:
* HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
* REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS),
* ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
* WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
* WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
* WARRANTY OF NONINFRINGEMENT.
* HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
* NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
* LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
* INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
* SAVINGS OR PROFITS,
* EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
* INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
* FROM, THE SOFTWARE.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/
/******************************************************************************/
/** \file main.c
**
** A detailed description is available at
** @link Sample Group Some description @endlink
**
**   - 2024-09-06 v3 修改温补计算
**
******************************************************************************/

/******************************************************************************
* Include files
******************************************************************************/
#include <stdio.h>
#include <math.h>
#include "wdt.h"
#include "adc.h"
#include "ddl.h"
#include "hdiv.h"
#include "bt.h"
#include "uart.h"
#include "gpio.h"
#include "sysctrl.h"
#include "flash.h"
#include "bgr.h"
#include "modbus_reg.h"
/******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
#define Firmware 3               //固件版本号
#define Hardware 1                  //硬件版本号

#define SECTOR_SIZE 0x200

//修改批次号或sn
#define PASS_LO ('i'*256+'t')
#define PASS_HI ('e'*256+'d')

//恢复出厂
#define PASS_UN_LO ('i'*256+'n')
#define PASS_UN_HI ('u'*256+'n')

#define PASS_IN_LO ('i'*256+'t')
#define PASS_IN_HI ('i'*256+'n')

#define u32Addr 0xFE00UL

#define PH_4_CAL       4.0f
#define PH_7_CAL       7.0f
#define PH_10_01_CAL 10.01f

//数组0也要参与计算
#define SAMPLE_PERIOD 0.1// 采样间隔
/******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/

/******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
typedef struct
{
    float f_pHt;
    float f_ph_offset;
    float f_ph_zero;
    float f_ph_step;
    float f_t_offset;
    uint8_t modbus_id;
    uint32_t Baud_rate;
    uint16_t manual_t;
    uint16_t auto_com;
    uint16_t sn;
    uint16_t cn;
    float f_ph_zero_bak;
    float f_ph_step_bak;
} save_data_type;

/*---------------------------*/
/*映射flash空间的公共体      */
/*---------------------------*/
typedef union
{
    unsigned char save;
    save_data_type save_data;
} flash;

/******************************************************************************
* Local function prototypes ('static')
* 局部函数原型(“静态”)
******************************************************************************/
static void Error_Handle()
{
    while(1);
}
/******************************************************************************
* Local variable definitions ('static')                                    *
******************************************************************************/
flash ee;
volatile int adc_n = 0;
volatile unsigned long u32AdcRestult0;
volatile unsigned long u32AdcRestult2;
volatile unsigned long u32AdcRestult3;
volatile unsigned long u32AdcRestult4;
volatile unsigned long u32AdcRestult5;
uint16_t u16AdcRestult;
volatile uint16_t tx_crc16 = 0xFFFF;

static uint8_t u8TxCnt=0,u8Txmax=0;
volatile uint8_t u8RxData;
volatile uint8_t u8TxData;
volatile uint8_t u8RxCnt=0;
volatile uint16_t modbus_4000_reg;
volatile signed short modbus_3000x_reg;

unsigned char uart_delay = 0;        //串口的timeout定时计数
uint8_t addess = 0;
uint8_t command = 0xFF;
uint16_t data_leng = 0;
uint16_t data_address = 0;
boolean_t b_modbus_rx_ok = FALSE;
boolean_t b_modbus_command_16 = FALSE;                //modbus功能字16一次设置完成
boolean_t Broadcast_address = FALSE;                  //广播地址
volatile uint16_t crc = 0xFFFF;
boolean_t b_adc_busy = FALSE;
/*****************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
void read_ad(void);
void Uart1_Rx(void);
void Uart1_Tx(void);
void send(uint8_t UARTx,int tx_leng);
void calccrc(uint8_t crcbuf);
void bubbleSort(float arr[], int size);
//void App_ClkInit(void);
void App_Rch4MHzTo24MHz(void);
//void App_Timer0Cfg(uint16_t u16Period);
void tx_calccrc(uint8_t crcbuf);
static void GIO_Init(void);
void App_AdcPortInit(void);
void App_AdcInit(void);
//void App_AdcJqrCfg(void);
void App_AdcSQRCfg(void);//< ADC 顺序扫描 功能配置
boolean_t init_data(void);
void IapProgram(unsigned char dat[]);
static void App_WdtInit(void);
void App_UartCfg(void);
void App_PortInit(void);

/**
******************************************************************************
** \briefMain function of project
**
** \return uint32_t return value, if needed
**
** This sample
**
******************************************************************************/
int main(void)
{
    static long i = 0;
    en_result_t enRc = Ok;
    float vin = 0,pH = 7.0,f_pH_t = 25.0;
    volatile int I16_ph;
    volatile float f_t = 0.0;
    stc_div_unsigned_result_t stcDivResult;
    FloatToUint fu4;
    U16ToU8 Byte2;
    volatile static int edit_n = 0;
    float pH_zero = 768.0f,pH_step = 88.5f;//放大1.5后的理论值
    float pH1 = 7.0f,pH2 = 7.0f;
    float U1 = 1536.0f,U2 = 1536.0f;
    volatile charcal_n = 0;
    uint32_t u32_adc_acc = 0u;
    float pH_buf = {7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
    float t_buf = {25.0};
    volatile uint8_t buf_n = 0;
    float sort_arr;
    float t_sort_buf;
    float ubuf;
    volatile uint8_t ubuf_n = 0;
    volatile uint8_t t_sort_n = 0;
    volatile uint8_t u_sort_n = 0;
    float u_sort_buf;
    volatile double d_u500mv=0.0,d_u1000mv=0.0;
    volatile double d_utmv = 0.0,d_itma;
    volatile double d_ptn = 1000.0;
    unsigned long u32_ut = 0u;

    GIO_Init();

    Gpio_ClrIO(STK_WR_PORT, STK_WR_PIN);

    ///< ADC采样端口初始化
    App_AdcPortInit();

    App_Rch4MHzTo24MHz();

    for(i = 0; i < SECTOR_SIZE; i++)
    {
      if(0xFF != *(volatile uint8_t *)(u32Addr + i))
      {
            break;
      }
    }
    if(i==SECTOR_SIZE)
    {
      ee.save_data.modbus_id = addess = 1;
      ee.save_data.f_ph_zero = pH_zero;
      ee.save_data.f_ph_step = pH_step;
      ee.save_data.Baud_rate = 9600;
      ee.save_data.f_pHt = 25.0;
      ee.save_data.manual_t = 25.0;

      IapProgram(&ee.save);
    }

    init_data();

    addess = ee.save_data.modbus_id;
    pH_zero = ee.save_data.f_ph_zero;
    pH_step = ee.save_data.f_ph_step;

    modbus_4000_reg= (uint16_t)Hardware;
    modbus_4000_reg= (uint16_t)Firmware;
    modbus_4000_reg= (uint16_t)addess;
    modbus_4000_reg = (uint16_t)ee.save_data.Baud_rate;
    modbus_4000_reg = modbus_4000_reg = 0x0000;
    modbus_4000_reg = modbus_4000_reg = 0x0000;
    modbus_4000_reg = modbus_4000_reg = 0x0000;
    modbus_4000_reg = modbus_4000_reg = 0x0000;
    modbus_4000_reg = modbus_4000_reg = 0x0000;
    modbus_4000_reg = 0x0000;
    modbus_4000_reg = 0x0000;
    modbus_4000_reg = 0x0000;
    modbus_4000_reg = ee.save_data.sn;
    modbus_4000_reg = ee.save_data.cn;

    modbus_4000_reg = ee.save_data.manual_t;
    if(ee.save_data.auto_com==0x00AA)
    {
      //自动温度补偿
      modbus_4000_reg = 0x00AA;
    }
    else
    {
      //手动温度补偿
      modbus_4000_reg = 0x0055;
      ee.save_data.auto_com = 0x0055 ;
    }

    fu4.f_data = ee.save_data.f_ph_zero_bak;
    modbus_4000_reg = fu4.u16_data;
    modbus_4000_reg = fu4.u16_data;
    fu4.f_data = ee.save_data.f_ph_step_bak;
    modbus_4000_reg = fu4.u16_data;
    modbus_4000_reg = fu4.u16_data;

    //去除零点放大和偏置,放大了1.5倍,在原始信号中有512mV偏置
    fu4.f_data = pH_zero / 1.5 - 512.0;
    modbus_4000_reg = fu4.u16_data;
    modbus_4000_reg = fu4.u16_data;
    fu4.f_data = pH_step / 1.5;
    modbus_4000_reg = fu4.u16_data;
    modbus_4000_reg = fu4.u16_data;
    fu4.f_data = ee.save_data.f_ph_offset;
    modbus_4000_reg = fu4.u16_data;
    modbus_4000_reg = fu4.u16_data;

    fu4.f_data = ee.save_data.f_t_offset;
    modbus_4000_reg = fu4.u16_data;
    modbus_4000_reg = fu4.u16_data;

    fu4.f_data = ee.save_data.f_pHt;
    modbus_4000_reg = fu4.u16_data;
    modbus_4000_reg = fu4.u16_data;

    //< ADC模块 初始化
    App_AdcInit();
//    App_Timer0Cfg(8000);   //Timer0配置初始化(周期 = 8000*(1/48M)*256 = 256ms)
//    Bt_M0_Run(TIM0);      //TIM0 运行。
    //串口引脚配置
    App_PortInit();

    //串口配置
    App_UartCfg();

    //< 除法器
    Sysctrl_SetPeripheralGate(SysctrlPeripheralDiv,TRUE);

    //看门狗配置
    App_WdtInit();

    modbus_4000_reg = 0;
    modbus_4000_reg = 1;
    ///< ADC 顺序扫描 功能配置
    App_AdcSQRCfg();
#if 0
    for(i=0;i<60;i++)
    {
            u8TxData = *(volatile uint8_t*)(u32Addr+i);
    }
    send(0,60);
    delay1ms(1000);////?????????????????
#endif

    while(1)
    {
            if(!b_adc_busy)
            {
                    b_adc_busy = TRUE;
      ///< 启动顺序扫描采样
      Adc_SQR_Start();
            }
      ///ad采样256次
      if(adc_n>=256)
      {
////对1000mV电压进行计算
            u32_adc_acc = 0;
            for(i=0; i<256; i++)
            {
                u32_adc_acc += u16AdcRestult;
            }
            enRc = Hdiv_Unsigned(u32_adc_acc,255,&stcDivResult);

            if(Ok == enRc)
            {
                u32AdcRestult3 = stcDivResult.Quotient;
                if(stcDivResult.Remainder>127)
                {
                  u32AdcRestult3++;
                }
            }
            else
            {
                Error_Handle();
            }
            d_u1000mv = (((double)u32AdcRestult3) / 4096.0) * 1500.0;
            fu4.f_data = (float)d_u1000mv;
            modbus_4000_reg = fu4.u16_data;
            modbus_4000_reg = fu4.u16_data;
            ///1000mv---end--------
            ////对500mV电压进行计算
            u32_adc_acc = 0;
            for(i=0; i<256; i++)
            {
                u32_adc_acc += u16AdcRestult;
            }
            enRc = Hdiv_Unsigned(u32_adc_acc,255,&stcDivResult);

            if(Ok == enRc)
            {
                u32AdcRestult4 = stcDivResult.Quotient;
                if(stcDivResult.Remainder>127)
                {
                  u32AdcRestult4++;
                }
            }
            else
            {
                Error_Handle();
            }
            d_u500mv = (((double)u32AdcRestult4) / 4096.0) * 1500.0;
            fu4.f_data = (((float)u32AdcRestult4) / 4096.0) * 1500.0;
            modbus_4000_reg = fu4.u16_data;
            modbus_4000_reg = fu4.u16_data;

            fu4.f_data = pH_zero / 1.5 - d_u500mv;
            modbus_4000_reg = fu4.u16_data;
            modbus_4000_reg = fu4.u16_data;
            ///500mv---end
            ///温度---------------------
            ////对温度电压进行计算
            u32_adc_acc = 0;
            for(i=0; i<256; i++)
            {
                u32_adc_acc += u16AdcRestult;
            }
            enRc = Hdiv_Unsigned(u32_adc_acc,255,&stcDivResult);

            if(Ok == enRc)
            {
                u32AdcRestult2 = stcDivResult.Quotient;
                if(stcDivResult.Remainder>127)
                {
                  u32AdcRestult2++;
                }
            }
            else
            {
                Error_Handle();
            }
            fu4.u32_data = u32_ut = u32AdcRestult2;
            modbus_4000_reg = fu4.u16_data;
            modbus_4000_reg = fu4.u16_data;
            ////对utn电压进行计算
            u32_adc_acc = 0;
            for(i=0; i<256; i++)
            {
                u32_adc_acc += u16AdcRestult;
            }
            enRc = Hdiv_Unsigned(u32_adc_acc,255,&stcDivResult);

            if(Ok == enRc)
            {
                u32AdcRestult5 = stcDivResult.Quotient;
                if(stcDivResult.Remainder>127)
                {
                  u32AdcRestult5++;
                }
            }
            else
            {
                Error_Handle();
            }
            fu4.u32_data = u32AdcRestult5;
            modbus_4000_reg = fu4.u16_data;
            modbus_4000_reg = fu4.u16_data;

            u32AdcRestult2 = u32_ut - u32AdcRestult5;

            d_utmv = ((double)u32AdcRestult2 * 1500.0) / 4096.0;
            d_itma = (d_u1000mv - (d_utmv / 34.0 + d_u500mv)) / 1000.0;
            d_ptn = (d_utmv / 34.0 + d_u500mv) / d_itma;
            f_t = (-3.9083 + sqrt((3.9083 * 3.9083) - (4.0 * (-0.0005775) * (1000-d_ptn))))
                  / (2.0 * (-0.0005775));
            //缓存数组
            for(i=0; i<14; i++)
            {
                t_buf = t_buf;
            }
            t_buf = f_t;
            //把缓存复制到排序数组
            for(i=0; i<15; i++)
            {
                sort_arr = t_buf;
            }
            //进行排序
            bubbleSort(sort_arr,15);
            //取中值
            t_sort_buf = sort_arr;
            if(t_sort_n>14)
            {
                f_t = 0;
                for(i=0; i<t_sort_n; i++)
                {
                  f_t += t_sort_buf;
                }
                //进行中值平均计算
                f_t = f_t / i;

                t_sort_n = 0;
            }
///温度--end
            ///ph-------------------------
            u32_adc_acc = 0;
            ////计算电压的累计和
            for(i=0; i<256; i++)
            {
                u32_adc_acc += u16AdcRestult;
            }
            ////硬件进行除法计算,求平均值
            enRc = Hdiv_Unsigned(u32_adc_acc,255,&stcDivResult);

            if(Ok == enRc)
            {
                u32AdcRestult0 = stcDivResult.Quotient;
                ////根据平均值的余数进行四舍五入计算
                if(stcDivResult.Remainder>127)
                {
                  u32AdcRestult0++;
                }
            }
            else
            {
                Error_Handle();
            }
            ////求ph电极电压
            vin = (((float)u32AdcRestult0) / 4096.0) * 1500.0;
            //IIR
            //vin = iirFilter(vin, &outputPrev);
            //if(ubuf_n<15)
            if(ubuf_n<5)
            {
                ubuf = vin;
            }
            else
            {
                ubuf_n = 0;
                //for(i=0; i<15; i++)
                for(i=0; i<5; i++)
                {
                  sort_arr = ubuf;
                }
                //进行排序
                //bubbleSort(sort_arr,15);
                bubbleSort(sort_arr,5);
                //取中值
                //u_sort_buf = sort_arr;
                u_sort_buf = sort_arr;
                //if(u_sort_n>14)
                if(u_sort_n>4)
                {
                  vin = 0;
                  for(i=0; i<u_sort_n; i++)
                  {
                        vin += u_sort_buf;
                  }
                  vin /= u_sort_n;//中值平均数计算
                  //求pH电极原始电压,放大1.5倍,加偏置512mV
                  fu4.f_data = vin / 1.5 - d_u500mv;/////--2024-05-13---512.0;
                  modbus_4000_reg = fu4.u16_data;
                  modbus_4000_reg = fu4.u16_data;
                  u_sort_n = 0;
                  pH_zero = ee.save_data.f_ph_zero;
                  pH_step = ee.save_data.f_ph_step;
                  //计算pH值
                  pH = 7 - (vin - pH_zero) / pH_step;
#if 1
                  if(buf_n<15)
                  {
                        pH_buf = pH;
                        pH = 0;
                        for(i=0; i<buf_n; i++)
                        {
                            pH += pH_buf;
                        }
                        pH = pH / i;
                  }
                  else
                  {
                        //pH缓存数组
                        for(i=0; i<14; i++)
                        {
                            pH_buf = pH_buf;
                        }
                        pH_buf = pH;
                        pH = 0;
                        for(i=0; i<15; i++)
                        {
                            pH += pH_buf;
                        }
                        pH = pH / i;
                  }
#endif
                  fu4.f_data = pH;
                  modbus_4000_reg = fu4.u16_data;
                  modbus_4000_reg = fu4.u16_data;

                  ///ph温度补-----------------------------------------
                  //ph温度补偿计算
                  if(ee.save_data.auto_com==0x00AA)
                  {
                        fu4.f_data = f_t + ee.save_data.f_t_offset;

                        f_pH_t = pH - ((f_t-ee.save_data.f_pHt) * fabs(pH-7) * 0.003);
#if 0
                        //-----2024-09-06----根据梅德勒电极修改温补
                        vin = vin / 1.5 - d_u500mv;//去掉1.5倍放大和512mv偏置
                        pH_zero = pH_zero / 1.5 - d_u500mv;
                        f_pH_t = (vin / (pH_zero - 0.198 * (fu4.f_data + 273.15))) + 7.0;
#endif
                        modbus_4000_reg = fu4.u16_data;
                        modbus_4000_reg = fu4.u16_data;
                  }
                  else if(ee.save_data.auto_com==0x0055)
                  {
                        f_pH_t = pH - (((float)ee.save_data.manual_t - ee.save_data.f_pHt) \
                                       * fabs(pH-7) * 0.003);
                        fu4.f_data = (float)ee.save_data.manual_t;
                        modbus_4000_reg = fu4.u16_data;
                        modbus_4000_reg = fu4.u16_data;
                  }
                  else
                  {
                        f_pH_t = pH;
                  }

                  f_pH_t += ee.save_data.f_ph_offset;

                  if(f_pH_t<0.001)
                  {
                        f_pH_t = 0.0;
                  }
                  else if(f_pH_t>14.0)
                  {
                        f_pH_t = 14.0f;
                  }
                  ///ph温度补---end-----------------
                  I16_ph = (int)((f_pH_t + 0.005) * 100.0);
                  fu4.f_data = (float)I16_ph / 100.0;
                  modbus_4000_reg = fu4.u16_data;
                  modbus_4000_reg = fu4.u16_data;
                }
            }
            ///ph---end-----------------
            adc_n = 0;
      }
      if(b_modbus_rx_ok)
      {
            switch(command)
            {
            case 3:
                u8TxData = addess;
                u8TxData = 0x03;
                u8TxData = 2 * data_leng;
                for(i=0; i<data_leng; i++)
                {
                  Byte2.u16_i = modbus_4000_reg;
                  u8TxData = Byte2.u8_c;
                  u8TxData = Byte2.u8_c;
                }
                tx_crc16 = 0xFFFF;
                for (i = 0; i < (u8TxData+3); i++)
                {
                  tx_calccrc(u8TxData);
                }
                Byte2.u16_i = tx_crc16;
                u8TxData = Byte2.u8_c;
                u8TxData = Byte2.u8_c;
                send(0,i);
                break;
            case 6:   //modbus接收到06命令
                //修改modbus id或者串口波特率
                if((addess!=(uint8_t)(modbus_4000_reg&0x00FF)) \
                        ||(ee.save_data.Baud_rate != (uint32_t)modbus_4000_reg))
                {
                  ee.save_data.modbus_id = (uint8_t)(modbus_4000_reg&0x00FF);
                  addess = ee.save_data.modbus_id;
                  ee.save_data.Baud_rate = (uint32_t)modbus_4000_reg;
                }
                ////接收过一次编辑密码
                if(edit_n>=1)
                {
                  edit_n = 0;
                  ee.save_data.sn = modbus_4000_reg;
                  ee.save_data.cn = modbus_4000_reg;
                }
                ee.save_data.manual_t = modbus_4000_reg;
                if(modbus_4000_reg==0x00AA)
                {
                  ee.save_data.auto_com = 0x00AA;
                }
                else
                {
                  ee.save_data.auto_com = 0x0055;
                }
                IapProgram(&ee.save);//数据写入flash

                ///< 启动 WDT,为了重启arm
                Wdt_Start();
                break;
            }
            b_modbus_rx_ok = FALSE;
      }
      //modbus接收到16命令
      if(b_modbus_command_16)
      {
            FloatToUint fu4_cal;
            b_modbus_command_16 = FALSE;
            if(modbus_4000_reg!=0x0000)
            {
                ////收到编辑密码
                if((modbus_4000_reg==PASS_LO)        \
                        &&(modbus_4000_reg==PASS_HI))
                {
                  edit_n++;
                  goto LOOP;
                }
                ////收到恢复出厂设置密码
                if((modbus_4000_reg==PASS_UN_LO)        \
                        &&(modbus_4000_reg==PASS_UN_HI))
                {
                  pH_zero = (ee.save_data.f_ph_zero_bak + 512.0) * 1.5;
                  pH_step = ee.save_data.f_ph_step_bak * 1.5;
                  ee.save_data.f_ph_zero = pH_zero;
                  ee.save_data.f_ph_step = pH_step;
                  modbus_4000_reg = modbus_4000_reg;
                  modbus_4000_reg = modbus_4000_reg;

                  modbus_4000_reg = modbus_4000_reg;
                  modbus_4000_reg = modbus_4000_reg;
                  IapProgram(&ee.save);//数据写入flash
                  ///< 启动 WDT
                  Wdt_Start();
                }
                ////收到出厂设置密码
                if((modbus_4000_reg==PASS_IN_LO)        \
                        &&(modbus_4000_reg==PASS_IN_HI))
                {
                  fu4.u16_data = modbus_4000_reg;
                  fu4.u16_data = modbus_4000_reg;
                  ee.save_data.f_ph_zero_bak = fu4.f_data;
                  fu4.u16_data = modbus_4000_reg;
                  fu4.u16_data = modbus_4000_reg;
                  ee.save_data.f_ph_step_bak = fu4.f_data;
                }
                modbus_4000_reg = 0x0000;
                modbus_4000_reg = 0x0000;
            }
            ////收到校准数据
            if((modbus_4000_reg!=0x0000)        \
                  ||(modbus_4000_reg!=0x0000))
            {
                fu4.u16_data = modbus_4000_reg;
                fu4.u16_data = modbus_4000_reg;
                if(fabs(fu4.f_data - PH_7_CAL)<1.0)
                {
                  cal_n++;/////校准次数记录
                  if(cal_n==1)//////第一次校准
                  {
                        pH1 = fu4.f_data;
                        U1 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - d_u500mv;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0001;
                        modbus_4000_reg = modbus_4000_reg = 0x0000;
                        goto LOOP;
                  }
                  else if(cal_n==2)//////第二次校准
                  {
                        pH2 = fu4.f_data;
                        U2 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - d_u500mv;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0201;
                  }
                }
                                                                /*
                else if(fabs(fu4.f_data - PH_6_86_CAL)<1.0)
                {
                  cal_n++;
                  if(cal_n==1)
                  {
                        pH1 = PH_6_86_CAL;
                        U1 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - 512.0;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0001;
                        modbus_4000_reg = modbus_4000_reg = 0x0000;
                        goto LOOP;
                  }
                  else if(cal_n==2)
                  {
                        pH2 = PH_6_86_CAL;
                        U2 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - 512.0;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0201;
                  }
                }
                                                                */
                else if(fabs(fu4.f_data - PH_4_CAL)<1.0)
                {
                  cal_n++;
                  if(cal_n==1)
                  {
                        pH1 = fu4.f_data;
                        U1 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - d_u500mv;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0001;
                        modbus_4000_reg = modbus_4000_reg = 0x0000;
                        goto LOOP;
                  }
                  else if(cal_n==2)
                  {
                        pH2 = fu4.f_data;
                        U2 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - d_u500mv;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0201;
                  }
                }
                                                                /*
                else if(fabs(fu4.f_data - PH_4_01_CAL)<1.0)
                {
                  cal_n++;
                  if(cal_n==1)
                  {
                        pH1 = PH_4_01_CAL;
                        U1 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - 512.0;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0001;
                        modbus_4000_reg = modbus_4000_reg = 0x0000;
                        goto LOOP;
                  }
                  else if(cal_n==2)
                  {
                        pH2 = PH_4_01_CAL;
                        U2 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - 512.0;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0201;
                  }
                }
                else if(fu4.f_data == PH_9_18_CAL)
                {
                  cal_n++;
                  if(cal_n==1)
                  {
                        pH1 = PH_9_18_CAL;
                        U1 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - 512.0;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0001;
                        modbus_4000_reg = modbus_4000_reg = 0x0000;
                        goto LOOP;
                  }
                  else if(cal_n==2)
                  {
                        pH2 = PH_9_18_CAL;
                        U2 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - 512.0;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0201;
                  }
                }
                                                                */
                else if(fabs(fu4.f_data - PH_10_01_CAL)<1.0)
                {
                  cal_n++;
                  if(cal_n==1)
                  {
                        pH1 = fu4.f_data;
                        U1 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - d_u500mv;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0001;
                        modbus_4000_reg = modbus_4000_reg = 0x0000;
                        goto LOOP;
                  }
                  else if(cal_n==2)
                  {
                        pH2 = fu4.f_data;
                        U2 = vin;
                        modbus_4000_reg = modbus_4000_reg;
                        modbus_4000_reg = modbus_4000_reg;
                        fu4_cal.f_data = (vin / 1.5) - d_u500mv;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = fu4_cal.u16_data;
                        modbus_4000_reg = 0x0201;
                  }
                }
                ////接收到两次校准数据,开始计算零点和斜率
                if(cal_n>=2)
                {
                  pH_zero = ((7.0f-pH1)*U2 - (7.0f-pH2)*U1)/(pH2-pH1);
                  pH_step = (U1 - pH_zero) / (7.0f - pH1);

                  modbus_4000_reg = 0x0000;
                  modbus_4000_reg = 0x0000;
                  fu4.f_data = ee.save_data.f_ph_zero = pH_zero;
                  fu4.f_data = fu4.f_data / 1.5 -d_u500mv;
                  modbus_4000_reg = fu4.u16_data;
                  modbus_4000_reg = fu4.u16_data;
                  fu4.f_data = ee.save_data.f_ph_step = pH_step;
                  fu4.f_data = fu4.f_data / 1.5;
                  modbus_4000_reg = fu4.u16_data;
                  modbus_4000_reg = fu4.u16_data;
                  ee.save_data.f_pHt = f_t + ee.save_data.f_t_offset;
                  fu4.f_data = ee.save_data.f_pHt;
                  modbus_4000_reg = fu4.u16_data;
                  modbus_4000_reg = fu4.u16_data;
                  cal_n = 0;
                }
                modbus_4000_reg = modbus_4000_reg = 0x0000;
            }
            else
            {
                fu4.u16_data = modbus_4000_reg;
                fu4.u16_data = modbus_4000_reg;
                ee.save_data.f_ph_offset = fu4.f_data;
                ee.save_data.modbus_id = (uint8_t)(modbus_4000_reg&0x00FF);
                addess = ee.save_data.modbus_id;
                ee.save_data.Baud_rate = (uint32_t)modbus_4000_reg;
#if 1
                fu4.f_data = pH_zero / 1.5 - 512.0;
                modbus_4000_reg = fu4.u16_data;
                modbus_4000_reg = fu4.u16_data;
                fu4.f_data = pH_step / 1.5;
                modbus_4000_reg = fu4.u16_data;
                modbus_4000_reg = fu4.u16_data;
#else
                fu4.u16_data = modbus_4000_reg;
                fu4.u16_data = modbus_4000_reg;
                ee.save_data.f_ph_zero = pH_zero = fu4.f_data;
                fu4.u16_data = modbus_4000_reg;
                fu4.u16_data = modbus_4000_reg;
                ee.save_data.f_ph_step = pH_step = fu4.f_data;
#endif
                fu4.u16_data = modbus_4000_reg;
                fu4.u16_data = modbus_4000_reg;
                ee.save_data.f_t_offset = fu4.f_data;

                fu4.u16_data = modbus_4000_reg;
                fu4.u16_data = modbus_4000_reg;
                ee.save_data.f_pHt = fu4.f_data;
                ee.save_data.manual_t = modbus_4000_reg;
                if(modbus_4000_reg==0x00AA)
                {
                  ee.save_data.auto_com = 0x00AA;
                }
                else
                {
                  ee.save_data.auto_com = 0x0055;
                }
            }
            //保存设置
            IapProgram(&ee.save);//数据写入flash
            ///< 启动 WDT
            ///Wdt_Start();
      }
LOOP:
      ;
    }
}

static void GIO_Init(void)
{
        stc_gpio_config_t stcGpioCfg;

    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    ///< 端口方向配置->输出
    stcGpioCfg.enDir = GpioDirOut;
    ///< 端口驱动能力配置->高驱动能力
    stcGpioCfg.enDrv = GpioDrvH;
    ///< 端口上下拉配置->无上下拉
    stcGpioCfg.enPuPd = GpioPu;
    ///< 端口开漏输出配置->开漏输出关闭
    stcGpioCfg.enOD = GpioOdDisable;
    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    stcGpioCfg.enCtrlMode = GpioAHB;
    ///< GPIO IO LED端口初始化
    Gpio_Init(STK_WR_PORT, STK_WR_PIN, &stcGpioCfg);
}

//将时钟从RCH4MHz切换至RCH24MHz,
void App_Rch4MHzTo24MHz(void)
{
    ///<============== 将时钟从RCH4MHz切换至RCH24MHz ==============================
    ///< RCH时钟不同频率的切换,需要先将时钟切换到RCL,设置好频率后再切回RCH
    Sysctrl_SetRCLTrim(SysctrlRclFreq32768);
    Sysctrl_ClkSourceEnable(SysctrlClkRCL, TRUE);
    Sysctrl_SysClkSwitch(SysctrlClkRCL);

    ///< 加载目标频率的RCH的TRIM值
    Sysctrl_SetRCHTrim(SysctrlRchFreq8MHz);//(SysctrlRchFreq24MHz);
    ///< 使能RCH
    Sysctrl_ClkSourceEnable(SysctrlClkRCH, TRUE);
    ///< 时钟切换到RCH
    Sysctrl_SysClkSwitch(SysctrlClkRCH);
    ///< 关闭RCL时钟
    ///Sysctrl_ClkSourceEnable(SysctrlClkRCL, FALSE);
}

void IapProgram(unsigned char dat[])
{
    ///< STEP-1: 确保初始化正确执行后方能进行FLASH编程操作,FLASH初始化(编程时间,休眠模式配置)
    while(Ok != Flash_Init(NULL,2, TRUE));

   //< ==> 8位编程
    ///< STEP-3 FLASH目标扇区擦除
    while(Ok != Flash_SectorErase(u32Addr))
    {
            ;
    }
    ///< STEP-4 FLASH 字节写、校验
        //while(Ok!= Flash_WriteByteS(u32Addr, dat,SECTOR_SIZE));
        Flash_WriteByteS(u32Addr, dat,SECTOR_SIZE);
    ///< FLASH 读模式
}

//初始化参数
boolean_t init_data(void)
{
    uint16_t i;

    for(i = 0; i < SECTOR_SIZE; i++)
    {
      ee.save = *(volatile uint8_t *)(u32Addr + i);
    }

    return Ok;
}

static void App_WdtInit(void)
{
        stc_wdt_config_t StcWdtCfg;

    ///< 开启WDT外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralWdt,TRUE);
    StcWdtCfg.enResetEnable = WRESET_EN;
    StcWdtCfg.pfnWdtIrqCb = NULL;
    StcWdtCfg.u8LoadValue = 3;
    ///< WDT 初始化
    Wdt_Init(&StcWdtCfg);
}

void bubbleSort(float arr[], int size)
{
    for (int i = 0; i < size - 1; i++)
    {
      for (int j = 0; j < size - i - 1; j++)
      {
            if (arr > arr)
            {
                // 交换arr和arr
                float temp = arr;
                arr = arr;
                arr = temp;
            }
      }
    }
}

///< ADC 顺序扫描 功能配置
void App_AdcSQRCfg(void)
{
        stc_adc_cfg_t          stcAdcCfg;

    DDL_ZERO_STRUCT(stcAdcCfg);

    ///< 顺序扫描模式功能及通道配置
    ///< 注意:扫描模式下,当配置转换次数为n时,转换通道的配置范围必须为
    stcAdcCfg.enAdcOpMode = AdcSCanMode;
    stcAdcCfg.bAdcInBufEn = TRUE;
    stcAdcCfg.enAdcClkDiv = AdcClkSysTDiv1;
    stcAdcCfg.enAdcRefVolSel = RefVolSelInBgr1p5;
    stcAdcCfg.enAdcSampTimeSel = AdcSampTime12Clk;
#if 0
    stcAdcSqrCfg.bSqrDmaTrig = FALSE;
    stcAdcSqrCfg.enResultAcc = AdcResultAccDisable;//AdcResultAccEnable;
    stcAdcSqrCfg.u8SqrCnt    = 5;
    Adc_SqrModeCfg(&stcAdcSqrCfg);
#endif

    Adc_ConfigSqrChannel(CH0MUX, AdcExInputCH2);
    Adc_ConfigSqrChannel(CH1MUX, AdcExInputCH4);
    Adc_ConfigSqrChannel(CH2MUX, AdcExInputCH5);
    Adc_ConfigSqrChannel(CH3MUX, AdcExInputCH6);
    Adc_ConfigSqrChannel(CH4MUX, AdcExInputCH7);

    Adc_ConfigSqrMode(&stcAdcCfg,5,FALSE);
    ///< ADC 中断使能
    Adc_EnableIrq();
    EnableNvic(ADC_IRQn, IrqLevel3, TRUE);

    ///< 启动顺序扫描采样
    Adc_SQR_Start();
}

///< ADC模块 初始化
void App_AdcInit(void)
{
        stc_adc_cfg_t          stcAdcCfg;
        DDL_ZERO_STRUCT(stcAdcCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);
    Bgr_BgrEnable();      ///< 开启BGR
    delay10us(2);

        ///< 顺序扫描模式功能及通道配置
        ///< 注意:扫描模式下,当配置转换次数为n时,转换通道的配置范围必须为
        stcAdcCfg.enAdcOpMode = AdcSCanMode;
        stcAdcCfg.bAdcInBufEn = TRUE;
        stcAdcCfg.enAdcClkDiv = AdcClkSysTDiv1;
        stcAdcCfg.enAdcRefVolSel = RefVolSelInBgr1p5;
        stcAdcCfg.enAdcSampTimeSel = AdcSampTime12Clk;

    //Bgr_TempSensorEnable(); ///温度传感器使能(需要先开启BGR)
    ///< ADC 初始化配置
    //stcAdcCfg.enInRef         = AdcMskInRefEnable;       ///<内部参考电压使能
    //stcAdcCfg.enAdcAlign      = AdcAlignRight;               ///<转换结果对齐方式-右
    stc_adc_irq_calbakfn_pt_t StcAdIrqCB;
    stc_adc_irq_t StcAdIrq;
    StcAdIrq.bAdcHhtCmp = FALSE;
        StcAdIrq.bAdcIrq = FALSE;
        StcAdIrq.bAdcJQRIrq = FALSE;
        StcAdIrq.bAdcLltCmp = FALSE;
        StcAdIrq.bAdcRegCmp = FALSE;
        StcAdIrq.bAdcSQRIrq = TRUE;

        StcAdIrqCB.pfnAdcHhtIrq = NULL;
        StcAdIrqCB.pfnAdcIrq = NULL;
        StcAdIrqCB.pfnAdcJQRIrq = NULL;
        StcAdIrqCB.pfnAdcLltIrq = NULL;
        StcAdIrqCB.pfnAdcRegIrq = NULL;
        StcAdIrqCB.pfnAdcSQRIrq = read_ad;
    Adc_ConfigIrq(&StcAdIrq,&StcAdIrqCB);
    Adc_Init(&stcAdcCfg);
    Adc_Enable();
}

///< ADC 采样端口初始化
void App_AdcPortInit(void)
{
    ///< 开启ADC/BGR GPIO外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    //    Gpio_SetAnalogMode(GpioPortA, GpioPin0);      //PA00 (AIN0)
    Gpio_SetAnalogMode(GpioPortA, GpioPin2);      //PA02 (AIN2)
    Gpio_SetAnalogMode(GpioPortA, GpioPin4);      //PA04 (AIN4)
    Gpio_SetAnalogMode(GpioPortA, GpioPin5);      //PA02 (AIN5)
    Gpio_SetAnalogMode(GpioPortA, GpioPin6);      //PA04 (AIN6)
    Gpio_SetAnalogMode(GpioPortA, GpioPin7);      //PA04 (AIN7)
}

//---------------------------------------------------------------------------------------------------------
void tx_calccrc(uint8_t crcbuf)
{
    uint8_t jj;
    boolean_t TT;

    tx_crc16 = tx_crc16 ^ (unsigned int)(crcbuf & 0x00FF);
    for(jj = 0; jj < 8; jj++)
    {
      if(tx_crc16 & 0x01)
      {
            TT = TRUE;
      }
      else
      {
            TT = FALSE;
      }
      tx_crc16 = tx_crc16 >> 1;
      tx_crc16 = tx_crc16 & 0x7FFF;
      if (TT)
      {
            tx_crc16 = tx_crc16 ^ 0xA001;
      }
    }
}

void calccrc(uint8_t crcbuf)
{
    uint8_t jj;
    boolean_t TT;

    crc = crc ^ ((uint16_t)crcbuf & 0x00FF);
    for(jj = 0; jj < 8; jj++)
    {
      if(crc & 0x0001)
      {
            TT = TRUE;
      }
      else
      {
            TT = FALSE;
      }
      crc = crc >> 1;
      crc = crc & 0x7FFF;
      if (TT)
      {
            crc = crc ^ 0xA001;
      }
    }
}

//串口引脚配置
void App_PortInit(void)
{
        stc_gpio_config_t stcGpioCfg;

    DDL_ZERO_STRUCT(stcGpioCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //使能GPIO模块时钟

    ///<TX
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(GpioPortA, GpioPin9, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin9, GpioAf1);          //配置PA02 端口为URART1_TX

    ///<RX
    stcGpioCfg.enDir = GpioDirIn;
    Gpio_Init(GpioPortA, GpioPin10, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin10, GpioAf1);          //配置PA03 端口为URART1_RX
}

//串口配置
void App_UartCfg(void)
{
        stc_uart_config_t    stcCfg;

    DDL_ZERO_STRUCT(stcCfg);

    ///< 开启外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);///<使能uart1模块时钟
/*
    en_uart_mode_t       enRunMode;      ///< 四种模式配置
    en_uart_stop_t       enStopBit;      ///<停止位长度
    stc_uart_multimode_t* pstcMultiMode; ///<多主机模式配置
    stc_uart_irq_cb_t*pstcIrqCb;       ///<中断服务函数
    boolean_t         bTouchNvic;      ///<NVIC中断使能
* */
    ///<UART Init
    stcCfg.enRunMode      = UartMode1;          ///<模式1
    stcCfg.enStopBit      = Uart1bit;         ///<1bit停止位
    stcCfg.pstcMultiMode->enMulti_mode = UartNormal;
    stcCfg.bTouchNvic = TRUE;
    /*
    func_ptr_t pfnTxIrqCb;    ///<发送中断服务函数
    func_ptr_t pfnRxFEIrqCb;///<接收帧错误中断服务函数
    func_ptr_t pfnRxIrqCb;    ///<接收中断服务函数
    func_ptr_t pfnCtsIrqCb;   ///<CTS信号翻转中断服务函数
    func_ptr_t pfnPEIrqCb;    ///<奇偶校验错误中断服务函数
   * */
    stc_uart_irq_cb_t StcUartIrqCB;

        StcUartIrqCB.pfnCtsIrqCb = NULL;
    StcUartIrqCB.pfnPEIrqCb= NULL;
    StcUartIrqCB.pfnRxFEIrqCb = NULL;
    StcUartIrqCB.pfnRxIrqCb = Uart1_Rx;
    StcUartIrqCB.pfnTxIrqCb = Uart1_Tx;
    stcCfg.pstcIrqCb = &StcUartIrqCB;
    //stcCfg.enMmdorCk      = UartDataOrAddr;
    stc_uart_baud_t StcUartBaud;
    StcUartBaud.enRunMode = UartMode1;
    StcUartBaud.u32Pclk = Sysctrl_GetPClkFreq(); ///<获得外设时钟(PCLK)频率值
    if(modbus_4000_reg==19200)
    {
            StcUartBaud.u32Baud = 19200UL;       ///<波特率19200
    }
    else
    {
            StcUartBaud.u32Baud = 9600UL;       ///<波特率9600
    }

//    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;       ///<通道采样分频配置
    Uart_SetBaud(0,Uart_CalScnt(0,&StcUartBaud));
    Uart_EnableFunc(0,UartRx);
    Uart_Init(0, &stcCfg);                   ///<串口初始化
    ///<UART中断使能
    Uart_ClrStatus(0,UartRC);                ///<清接收请求
    Uart_ClrStatus(0,UartTC);                ///<清接收请求
    Uart_EnableIrq(0,UartRxIrq);             ///<使能串口接收中断
    Uart_EnableIrq(0,UartTxIrq);             ///<使能串口接收中断
    EnableNvic(UART0_IRQn, IrqLevel3, TRUE);       ///<系统中断使能
}

void Uart1_Rx(void)
{
    volatile uint8_t k,i,n;
    volatile uint16_t rx_crc, temp0_i16, temp1_i16;
    U16ToU8 uart_temporary;

      k = Uart_ReceiveData(0);   //接收数据字节
      uart_delay = 0;

      if((k == addess) && (u8RxCnt == 0))// || (k == 0)
      {
            u8RxData = addess;
            u8RxCnt++;
            if(k==0)
            {
                Broadcast_address = TRUE;
            }
            return;
      }
      else if((u8RxCnt == 1) && ((k == 3) || (k == 4) || (k == 6) || (k == 16))        \
                && (u8RxData == addess))
      {
            u8RxData = k;
            return;
      }
      else if((u8RxData == addess) && ((u8RxData == 3)||(u8RxData == 4)||(u8RxData == 6)))
      {
            u8RxData = k;
            if(u8RxCnt > 7)
            {
                uart_temporary.u8_c = u8RxData;
                uart_temporary.u8_c = u8RxData;
                rx_crc = uart_temporary.u16_i;

                crc = 0xFFFF;
                for (i = 0; i < 6; i++)
                {
                  calccrc(u8RxData);
                }
                if(crc == rx_crc)
                {
                  uart_temporary.u8_c = u8RxData;
                  uart_temporary.u8_c = u8RxData;
                  data_address = uart_temporary.u16_i; //数据起始地址
                  uart_temporary.u8_c = u8RxData;
                  uart_temporary.u8_c = u8RxData;
                  data_leng = uart_temporary.u16_i;//数据长度

                  if(u8RxData == 0x06)
                  {
                                                modbus_4000_reg = data_leng;
                  }
                  command = u8RxData;
                  b_modbus_rx_ok = TRUE;
                }
                u8RxCnt = 0;
            }
            return;
      }
      else if((u8RxData == addess) && (u8RxData == 16))
      {
            u8RxData = k;
            if((u8RxCnt==5)&&(u8RxData>0))
            {
                u8RxCnt = 0;
                u8RxData = 0xFF;
                return;
            }
            else if((u8RxCnt==6)&&(u8RxData>127))
            {
                u8RxCnt = 0;
                u8RxData = 0xFF;
                return;
            }
            else if((u8RxCnt==7)&&(u8RxData!=(u8RxData*2)))
            {
                u8RxCnt = 0;
                u8RxData = 0xFF;
                return;
            }
            else
            {
                if(u8RxCnt > 8)
                {
                  n = 8 + u8RxData;
                  if(n>MODBUS_REG_LENG)
                  {
                        u8RxCnt = 0;
                        u8RxData = 0xFF;
                        return;
                  }
                  if(u8RxCnt > n)
                  {
                        uart_temporary.u8_c = u8RxData;
                        n--;
                        uart_temporary.u8_c = u8RxData;
                        rx_crc = uart_temporary.u16_i;
                        crc = 0xFFFF;
                        for (i = 0; i < n; i++)
                        {
                            calccrc(u8RxData);
                        }
                        if((crc == rx_crc)||(Broadcast_address))
                        {
                            uart_temporary.u8_c = u8RxData;
                            uart_temporary.u8_c = u8RxData;
                            temp0_i16 = uart_temporary.u16_i; //数据起始地址
                            uart_temporary.u8_c = u8RxData;
                            uart_temporary.u8_c = u8RxData;
                            temp1_i16 = uart_temporary.u16_i;//数据长度
                            if((temp0_i16+temp1_i16)<MODBUS_REG_LENG)
                            {
                              for(i = 0; i < 6; i++)
                              {
                                    u8TxData = u8RxData;
                              }
                              crc = 0xFFFF;
                              for (i = 0; i < 6; i++)
                              {
                                    calccrc(u8TxData);
                              }

                              uart_temporary.u16_i = crc;
                              u8TxData = uart_temporary.u8_c;
                              u8TxData = uart_temporary.u8_c;
                              send(0,8);
                              u8RxCnt = 0;
                              u8RxData = 0xFF;

                              for(i=0; i<temp1_i16; i++)
                              {
                                    uart_temporary.u8_c = u8RxData;
                                    uart_temporary.u8_c = u8RxData;
                                    modbus_4000_reg = uart_temporary.u16_i;
                              }
                              b_modbus_command_16 = TRUE;
                              Broadcast_address = FALSE;
                            }
                            u8RxCnt = 0;
                            u8RxData = 0xFF;
                        }
                        else
                        {
                            u8RxCnt = 0;
                            u8RxData = 0xFF;
                        }
                  }
                  return;
                }
            }
      }
      else
      {
            u8RxCnt = 0;
            u8RxData = 0xFF;
            return;
      }
}

void Uart1_Tx(void)
{
      if(u8TxCnt<u8Txmax)
      {
              M0P_UART0->SBUF_f.DATA = u8TxData;
      }
      else
      {
            u8TxCnt = 0;
            u8Txmax = 0;
            Gpio_ClrIO(STK_WR_PORT, STK_WR_PIN);
      }
}

void send(uint8_t UARTx,int tx_leng)
{
    while(!Uart_GetStatus(UARTx,UartTxe));
    u8Txmax=tx_leng;
    Gpio_SetIO(STK_WR_PORT, STK_WR_PIN);
        M0P_UART0->SBUF_f.DATA = u8TxData;
//    Uart_SendData(UARTx, u8TxData); //启动UART1发送第一个字节
}

void read_ad(void)
{
      Adc_GetSqrResult(&u16AdcRestult,CH0MUX);//获取顺序扫描通道0
      Adc_GetSqrResult(&u16AdcRestult,CH1MUX);//获取顺序扫描通道1
      Adc_GetSqrResult(&u16AdcRestult,CH2MUX);
      Adc_GetSqrResult(&u16AdcRestult,CH3MUX);
      Adc_GetSqrResult(&u16AdcRestult,CH4MUX);
      adc_n++;
      Adc_SQR_Stop();
      b_adc_busy = FALSE;
}
#if 0
/*******************************************************************************
* TIM0中断服务函数
******************************************************************************/
void Tim0_IRQHandler(void)
{
    //Timer0 模式0 溢出中断
    if(TRUE == Bt_GetIntFlag(TIM0, BtUevIrq))
    {
      Bt_ClearIntFlag(TIM0,BtUevIrq); //中断标志清零
    }
}

//Timer0配置初始化
void App_Timer0Cfg(uint16_t u16Period)
{
    uint16_t                  u16ArrValue;
    uint16_t                  u16CntValue;
    stc_bt_mode0_cfg_t   stcBtBaseCfg;

    DDL_ZERO_STRUCT(stcBtBaseCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能

    stcBtBaseCfg.enWorkMode = BtWorkMode0;                  //定时器模式
    stcBtBaseCfg.enCT       = BtTimer;                      //定时器功能,计数时钟为内部PCLK
    stcBtBaseCfg.enPRS      = BtPCLKDiv256;               //PCLK/256
    stcBtBaseCfg.enCntMode= Bt16bitArrMode;               //自动重载16位计数器/定时器
    stcBtBaseCfg.bEnTog   = FALSE;
    stcBtBaseCfg.bEnGate    = FALSE;
    stcBtBaseCfg.enGateP    = BtGatePositive;
    Bt_Mode0_Init(TIM0, &stcBtBaseCfg);                     //TIM0 的模式0功能初始化

    u16ArrValue = 0x10000 - u16Period;
    Bt_M0_ARRSet(TIM0, u16ArrValue);                        //设置重载值(ARR = 0x10000 - 周期)

    u16CntValue = 0x10000 - u16Period;
    Bt_M0_Cnt16Set(TIM0, u16CntValue);                      //设置计数初值

    Bt_ClearIntFlag(TIM0,BtUevIrq);                         //清中断标志
    Bt_Mode0_EnableIrq(TIM0);                               //使能TIM0中断(模式0时只有一个中断)
    EnableNvic(TIM0_IRQn, IrqLevel3, TRUE);               //TIM0中断使能
}

// 数字积分函数
float numericalIntegration(float* input, int numSamples) {
    float integral = 0.0;
    for (int i = 1; i < numSamples; i++) {
      integral += (input + input) * SAMPLE_PERIOD / 2.0;
    }
    return integral;
}

// IIR滤波函数
float iirFilter(float input, float* outputPrev) {
    float output = A_COEFF * input + B_COEFF * (*outputPrev);
    *outputPrev = output;
    return output;
}
#endif
/******************************************************************************
* EOF (not truncated)
******************************************************************************/


页: [1]
查看完整版本: PH传感器的电压是如何转换为pH数值