高精度数字电容传感芯片-MDC04

news2024/9/25 21:19:00

高精度数字电容传感芯片-MDC04

  • 简介
  • 引脚说明
  • PCBA板
  • 寄存器说明
  • 代码实现
    • 单总线通讯时序代码
    • 单总线通讯时序代码头文件
    • MDC04驱动代码
    • MDC04驱动代码头文件
    • 用户APP调用函数
    • main主程序

简介

MDC04以低成本等优势,可用于智能小家电液位、水箱液位、油液液位、水浸传感、食品/土壤水分含量、冰霜检测、位移传感等应用场景。

引脚说明

引脚名称说明
1RSTN复位,输入;低电平有效
2MODE通讯接口模式选择,输入。0 时,PIN12 为 I²C 的 SDA;1 时,PIN12 为 1-wire 的 DQ。
3VSS电源地
4C4_OUT电容 C4 接入,模拟输出
5C4_IN电容 C4 接入,模拟输入
6C1_IN电容 C1 接入,模拟输入
7C1_OUT电容 C1 接入,模拟输出
8C2_IN电容 C2 接入,模拟输入
9C2_OUT电容 C2 接入,模拟输出
10C3_IN电容 C3 接入,模拟输入
11C3_OUT电容 C3 接入,模拟输出
12SDA/DQI²C 数据线或单总线数据线,I/O
13ADDRI²C 通讯地址选择线,输入,不可悬空。0 时,I²C 地址为 0x44;1 时,I²C 地址为 0x45。注意:选择单总线通讯模式时,ADDR 需要接地。
14NC-
15SCLI²C 时钟线;I/O,不可悬空。注意:选择单总线通讯模式时,SCL 需要接地。
16NC-
17NC-
18NC-
19NC-
20VDD电源,输入

PCBA板

在某创商城平台上购买的PCBA板子,具体如下示意图
在这里插入图片描述
MDC04PCB 共有 4 路电容测试通道,使用的时候可以根据实际应用并配合 MDC04 不同的配置选择单通道或多通道使用。

MDC04PCB 有两种工作模式,分别是单总线通信和 I2C 通信。通过上图 MODE 焊盘短接高/低电平选择不同的模式:
A. 单总线:MODE 焊盘仅能和图中左侧 + 焊盘短接或者焊接 0Ω电阻。通过下方VDD-SDA-GND 三个 PIN 通信;
B. I2C 通信:MODE 焊盘仅能和图中上测 – 焊盘短接或者焊接 0Ω电阻。通过下方VDD-SDA-GND-SCL 四个 PIN 通信;

为了简单调用就使用单线通讯,这里还需要在PCBA板上焊接一个SDA上拉电阻即可。

下图为多级连接方式,类似于DS18B20温度传感器一样,也有对应的器件地址
在这里插入图片描述
MDC04 单总线接口方式的系统应用如上图,端口 DQ 连接到上位机处理器的 GPIO 上,通过上拉电阻 Rp连到 VDD,通过上位机软件来实现各节点芯片的读写控制。根据实际应用,可以串联 1-100 多个节点,通过 ID 号来寻址与访问,各节点芯片的 MODE 管脚接 VDD。

寄存器说明

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

整体功能指令
在这里插入图片描述
在这里插入图片描述

代码实现

使用STM32的标准库,串口方式输出数据,连接MDC04芯片为单总线通讯方式,引脚连接为PC7也可以自己进行修改

单总线通讯时序代码

MY_ow.c

/* Includes ------------------------------------------------------------------*/
#include "MY_ow.h"
#include "stm32f10x.h"
#include "bsp_SysTick.h"



/******One-wire communication timing requirements*******/
//SPON: <=10 us. Time to Strong Pullup On.
//tSLOT: >=60 us, <=120us. Time Slot
//tREC: >=1 us. Recovery Time.
//tLOW0: >=60 us, <=120us. Write 0 Low Time.
//tLOW1: >=1 us, <=15us. Write 1 Low Time.
//tRDV: <=15 us. Read Data Valid.
//tRSTH: >=480 us. Reset Time High.
//tRSTL: >=480 us. Reset Time Low.
//PDHIGH: >=15 us, <=60us. Presence-Detect High.
//tPDLOW: >=60 us, <=240us. Presence-Detect Low.

/*Time delays in us for GPIO simulated master One-wire communication*/
#define     tSlot          60    /*us*/
#define     tRecover        10    /*us*/
#define     tInitSlot        3     /*us*/
#define     tLow_Write_1      tInitSlot
#define     tHigh_Write_1      tSlot
#define     tLow_Write_0      53    
#define     tHigh_Write_0      tRecover   
#define     tLow_Read        tInitSlot     
#define     tSample_Read      10       /*us*/
#define     tComplement_Read    55
#define     tLow_Reset       480    /*us*/
#define     tHigh_Reset       480    /*us*/
#define     tSample_Presence    80    /*us*/
#define     tComplement_Presence  (tHigh_Reset-tSample_Presence)
//---------------------------------------------------------------------------

void OW_Init(void)
{
  GPIO_InitTypeDef gpioinitstruct;

  RCC_APB2PeriphClockCmd(GPIOOW_DQ_BUSCLK, ENABLE);

  gpioinitstruct.GPIO_Pin 	= GPIOOW_DQ_PIN;
  gpioinitstruct.GPIO_Speed = GPIO_Speed_10MHz;
  gpioinitstruct.GPIO_Mode 	= GPIO_Mode_Out_OD;
  GPIO_Init(GPIOOW_DQ_GPIO_PORT, &gpioinitstruct);

	ow_DQ_set();

}


// OW 'RESET+PRESENSE' timming sequence
//
//      |     >=480us   |        >=480us             |
//------                 --------\                ------------
//      |               /        |              /
//      | (>480us)	    |	15-60us|   60-240us   |
//      |_ _ _ _ _ _ _ _|        | _ _ _ _ _ _ _|

void OW_Reset(void)
{
	ow_DQ_reset(); 	// Drive DQ low
	ow_Delay_us(tLow_Reset);
	ow_DQ_set(); 		// Release DQ
}

bool OW_Presence(void)
{
 uint8_t dq;int count=0;
 
 ow_Delay_us(tSample_Presence);
 dq = ow_DQ_get();  // Get presence pulse from slave
  while(dq&&(count<17))
  {
    Delay_us(10);
    dq = ow_DQ_get();
    count++;
  } 
 ow_Delay_us(tComplement_Presence); // Complete the reset sequence recovery
 
 return (dq ? FALSE : TRUE);     
}

bool OW_ResetPresence(void)
{
 uint8_t dq;int count=0;
 
 ow_DQ_reset();  // Drive DQ low
 ow_Delay_us(tLow_Reset); 
 ow_DQ_set();   // Release DQ 
 ow_Delay_us(tSample_Presence);//After detecting the rising edge on the DQ pin, 
                               //the M601 waits for 15~60 us and then transmits 
                               //the presence pulse (a low signal for 60~240us).
 dq = ow_DQ_get();          // Get presence pulse from slave
 while(dq&&(count<17))
  {
    Delay_us(10);
    dq = ow_DQ_get();
    count++;
  } 
 ow_Delay_us(tComplement_Presence);  // Complete the reset-presensce
 
 return (dq ? FALSE : TRUE); 
}

//---------------------------------------------------------------------------
//   MASTER WRITE 0 and WRITE 1 SLOT=70us.
//   |>1us|       60<Tx0<120us         |1us<tRec|         
//    ----                              ----------
//  /     |                            /     
//  |     |        |     45us      |  |   
//  |_ _ _|_ _ _ _______ _ _ _ _____ __|  
//      |   15us  | Slave samples | 

//   |>1us|       60<Tx1<120us         |            
//    ----       ---------------------------------
//  /     |     /                   |      
//  |     |>1us |   |     45us      | 
//  |_ _ _|_ __ | _______ _ _ _ ___ |  
//    |   15us  | Slave samples | 

// Send a bit to DQ. Provide 10us recovery time.
void OW_WriteBit(uint8_t bit)
{
 if (bit)
 {
  // Write '1' to DQ
  ow_DQ_reset();        // Initialte write '1' time slot.
  ow_Delay_us(tLow_Write_1);
  ow_DQ_set();   
  ow_Delay_us(tHigh_Write_1); // Complete the write '1' time slot.
 }
 else
 {
  // Write '0' to DQ
    ow_DQ_reset(); 						// Initialte write '0' time slot
		ow_Delay_us(tLow_Write_0);
		ow_DQ_set();
		ow_Delay_us(tHigh_Write_0); // Complete the write '0' time slot: recovery
	}
}

//---------------------------------------------------------------------------
// Read a bit from DQ. Provide 10us recovery time.
//
int OW_ReadBit(void)
{
	int bit;

	ow_DQ_reset(); 								// Initialte read time slot
	ow_Delay_us(tLow_Read);
	ow_DQ_set();
	ow_Delay_us(tSample_Read);
	bit = ow_DQ_get(); 				 		// Sample DQ to get the bit from the slave
	ow_Delay_us(tComplement_Read); // Complete the read time slot with 10us recovery

	return (bit != 0);
}

/*Send a byte to DQ. LSB first, MSB last.*/
void OW_WriteByte(uint8_t data)
{
	int bit;

	for (bit = 0; bit < 8; bit++)
	{
		OW_WriteBit(data & 0x01);
		data >>= 1;
	}
}
//---------------------------------------------------------------------------
// Read a byte from DQ and return it. LSB first, MSB last.
//
uint8_t OW_ReadByte(void)
{
	uint8_t bit, byte=0;

	for (bit = 0; bit < 8; bit++)
	{
		byte >>= 1;
		if (OW_ReadBit())
			byte |= 0x80;
	}

	return byte;
}

/* Single read time slot for polling slave ready.*/
OW_SLAVESTATUS OW_ReadStatus(void)
{
	int status;

	ow_DQ_reset(); 				         // Initiate read time slot
	ow_Delay_us(tLow_Read);
	ow_DQ_set();
	ow_Delay_us(tSample_Read);
	status = ow_DQ_get();          // Get the status from DQ: '0' busy, '1' idle.
	ow_Delay_us(tComplement_Read); // Complete the read time slot and recovery

	return (status ? READY : BUSY);
}
//---------------------------------------------------------------------------
//Multi-Drop 1-Wire network function: get a bit value and its complement.
//---------------------------------------------------------------------------
uint8_t OW_Read2Bits(void)
{
		uint8_t i, dq, data;
	  data = 0;

		for(i=0; i<2; i++)
		{
			dq = OW_ReadBit();
			data = (data) | (dq<<i);
		}

		return data;
}
//---------------------------------------------------------------------------
// CRC校验.
//

#define POLYNOMIAL 0x131 //100110001

uint8_t CRC8_Cal(uint8_t *serial, uint8_t length) 
{
    uint8_t result = 0x00;
    uint8_t pDataBuf;
    uint8_t i;

    while(length--) {
        pDataBuf = *serial++;
        for(i=0; i<8; i++) {
            if((result^(pDataBuf))&0x01) {
                result ^= 0x18;
                result >>= 1;
                result |= 0x80;
            }
            else {
                result >>= 1;
            }
            pDataBuf >>= 1;
        }
    }
    return result;
}


单总线通讯时序代码头文件

MY_ow.h头文件

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MY_OW_H
#define MY_OW_H

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "MY_stdtype.h"

//***********需要根据用户的延时函数进行相应替换,务必是准确的us级延时!*********//
#define ow_Delay_us			Delay_us
#define ow_Delay_ms(x)  Delay_us(1000*x)
/* Definition of DQ pin for one-wire communication*/

#define GPIOOW_DQ_GPIO_PORT          		GPIOC
#define GPIOOW_DQ_PIN                   GPIO_Pin_7
#define GPIOOW_DQ_BUSCLK             		RCC_APB2Periph_GPIOC
#define GPIOOW_DQ_GPIO_CLK_ENABLE()  		RCC_APB2PeriphClockCmd(GPIOOW_DQ_BUSCLK, ENABLE);

/* Macros for DQ manipulation*/
#define ow_DQ_set()   		{ GPIOOW_DQ_GPIO_PORT->BSRR = GPIOOW_DQ_PIN; }
#define ow_DQ_reset() 		{ GPIOOW_DQ_GPIO_PORT->BRR = GPIOOW_DQ_PIN; }
#define ow_DQ_get()   		( GPIOOW_DQ_GPIO_PORT->IDR & GPIOOW_DQ_PIN )

typedef enum {
  READY       = 0,
  BUSY    		= 1
} OW_SLAVESTATUS;

/* Exported_Functions----------------------------------------------------------*/
OW_SLAVESTATUS OW_ReadStatus(void);
void OW_Init(void);
bool OW_ResetPresence(void);
void OW_WriteByte(uint8_t data);
uint8_t OW_ReadByte(void);
uint8_t OW_Read2Bits(void);
uint8_t CRC8_Cal(uint8_t *serial, uint8_t length);


#endif /* MY_OW_H */

MDC04驱动代码

MDC04_driver.c


/****************************************************************************************/
/*
 *
 * Copyright (C) 2020. Mysentech Inc, unpublished work. This computer
 * program includes Confidential, Proprietary Information and is a Trade Secret of
 * Minyuan Sensing Technology Inc.(Mysentech)  All use, disclosure, and/or reproduction is prohibited
 * unless authorized in writing. All Rights Reserved.
 *
 *  Please contact <sales@mysentech.com> or contributors for further questions.
*/
/****************************************************************************************/

/* Includes ------------------------------------------------------------------*/
//#include "system.h"
#include <math.h>

/* Includes(MDC04驱动头文件) ------------------------------------------------------------------*/
#include "MDC04_driver.h"
#include "bsp_SysTick.h"
#include "MY_ow.h"

/****全局变量:保存和电容配置寄存器对应的偏置电容和量程电容数值****/
float CapCfg_offset, CapCfg_range;
uint8_t CapCfg_ChanMap, CapCfg_Chan;

/****偏置电容和反馈电容阵列权系数****/
static const float COS_Factor[8] = {0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 40.0};
/*Cos= (40.0*q[7]+32.0*q[6]+16.0*q[5]+8.0*q[4]+4.0*q[3]+2.0*q[2]+1.0*q[1]+0.5*q[0])*/
static const struct  {float Cfb0; float Factor[6];} CFB = { 2.0, 2.0, 4.0, 8.0, 16.0, 32.0, 46.0};
/*Cfb =(46*p[5]+32*p[4]+16*p[3]+8*p[2]+4*p[1]+2*p[0]+2)*/

/**
  * @brief  把16位二进制补码表示的温度输出转换为以摄氏度为单位的温度读数
  * @param  out:有符号的16位二进制温度输出
  * @retval 以摄氏度为单位的浮点温度
*/
float MDC04_OutputtoTemp(int16_t out)
{
	return ((float)out/256.0 + 40.0);
}

/**
  * @brief  把以摄氏度为单位的浮点温度值转换为16位二进制补码表示的温度值
  * @param  以摄氏度为单位的浮点温度值
  * @retval 有符号的16位二进制温度值
*/
int16_t MDC04_TemptoOutput(float Temp)
{
	return (int16_t)((Temp-40.0)*256.0);
}

/**
  * @brief  把16位二进制电容输出转换为以pF为单位的电容读数
  * @param  out:无符号的16位二进制电容输出
  * @param  Co:配置的偏置电容数值
  * @param  Cr:配置的范围电容(量程)数值
  * @retval 以pF为单位的浮点电容数值
*/
float MDC04_OutputtoCap(uint16_t out, float Co, float Cr)
{
	return (2.0*(out/65535.0-0.5)*Cr+Co);
}

/**
  * @brief  计算多个字节序列的校验和
  * @param  serial:字节数组指针
  * @param  length:字节数组的长度
  * @retval 校验和(CRC)
*/
#define POLYNOMIAL 	0x131 //100110001
uint8_t MY_OW_CRC8(uint8_t *serial, uint8_t length)
{
    uint8_t result = 0x00;
    uint8_t pDataBuf;
    uint8_t i;

    while(length--) {
        pDataBuf = *serial++;
        for(i=0; i<8; i++) {
            if((result^(pDataBuf))&0x01) {
                result ^= 0x18;
                result >>= 1;
                result |= 0x80;
            }
            else {
                result >>= 1;
            }
            pDataBuf >>= 1;
        }
    }

    return result;
}

bool MDC04_nReadScratchpad_SkipRom(uint8_t *scr, uint8_t size)
{
    int16_t i;

	/*size < sizeof(MDC04_SCRATCHPAD_READ)*/
    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(READ_SCRATCHPAD);

		for(i=0; i<size; i++)
    {
			*scr++ = OW_ReadByte();
		}

    return TRUE;
}
/**
  * @brief  读芯片ROM ID
*/
bool MDC04_ReadROM(uint8_t *scr)
{
    int16_t i;

    if(OW_ResetPresence() == FALSE)
			return FALSE;
		
    OW_WriteByte(READ_ROM);

		for(i=0; i < sizeof(MDC04_ROMCODE); i++)
    {
			*scr++ = OW_ReadByte();
		}

    return TRUE;
}

/**
  * @brief  读芯片寄存器的暂存器组
  * @param  scr:字节数组指针, 长度为 @sizeof(MDC04_SCRATCHPAD_READ)
  * @retval 读状态
*/
bool MDC04_ReadScratchpad_SkipRom(uint8_t *scr)
{
    int16_t i;

	/*size < sizeof(MDC04_SCRATCHPAD_READ)*/
    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(READ_SCRATCHPAD);

		for(i=0; i < sizeof(MDC04_SCRATCHPAD_READ); i++)
    {
			*scr++ = OW_ReadByte();
		}

    return TRUE;
}
/**
  * @brief  写芯片寄存器的暂存器组
  * @param  scr:字节数组指针, 长度为 @sizeof(MDC04_SCRATCHPAD_WRITE)
  * @retval 写状态
**/
bool MDC04_WriteScratchpad_SkipRom(uint8_t *scr)
{
    int16_t i;

    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(WRITE_SCRATCHPAD);

		for(i=0; i < sizeof(MDC04_SCRATCHPAD_WRITE); i++)
    {
			OW_WriteByte(*scr++);
		}

    return TRUE;
}
/**
  * @brief  读芯片寄存器的扩展暂存器组
  * @param  scr:字节数组指针, 长度为 @sizeof(MDC04_SCRATCHPADEXT)
  * @retval 读状态
**/
bool MDC04_ReadScratchpadExt_SkipRom(uint8_t *scr)
{
    int16_t i;

    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(READ_SCRATCHPAD_EXT);

		for(i=0; i< sizeof(MDC04_SCRATCHPADEXT); i++)
    {
			*scr++ = OW_ReadByte();
		}

    return TRUE;
}
/**
  * @brief  写芯片寄存器的扩展暂存器组
  * @param  scr:字节数组指针, 长度为 @sizeof(MDC04_SCRATCHPADEXT)
  * @retval 写状态
**/
bool MDC04_WriteScratchpadExt_SkipRom(uint8_t *scr)
{
    int16_t i;

    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(WRITE_SCRATCHPAD_EXT);

		for(i=0; i<sizeof(MDC04_SCRATCHPADEXT)-1; i++)
    {
			OW_WriteByte(*scr++);
		}

    return TRUE;
}
/**
  * @brief  读电容通道2,3,4测量结果寄存器的内容
  * @param  scr:字节数组指针, 长度为 @sizeof(MDC04_C2C3C4)
  * @retval 写状态
**/
bool MDC04_ReadC2C3C4_SkipRom(uint8_t *scr)
{
    int16_t i;

    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(READ_C2C3C4);

		for(i=0; i < sizeof(MDC04_C2C3C4); i++)
    {
			*scr++ = OW_ReadByte();
		}

    return TRUE;
}
/**
  * @brief  读芯片寄存器的参数组
  * @param  scr:字节数组指针, 长度为 @sizeof(MDC04_SCRPARAMETERS)
  * @retval 读状态
**/
bool MDC04_ReadParameters_SkipRom(uint8_t *scr)
{
    int16_t i;

    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(READ_PARAMETERS);

		for(i=0; i < sizeof(MDC04_SCRPARAMETERS); i++)
    {
			*scr++ = OW_ReadByte();
		}

    return TRUE;
}
/**
  * @brief  写芯片寄存器的参数组
  * @param  scr:字节数组指针, 长度为 @sizeof(MDC04_SCRPARAMETERS)
  * @retval 写状态
**/
bool MDC04_WriteParameters_SkipRom(uint8_t *scr)
{
    int16_t i;

    if(OW_ResetPresence() == FALSE)
			return FALSE;

    OW_WriteByte(SKIP_ROM);
    OW_WriteByte(WRITE_PARAMETERS);

		for(i=0; i < sizeof(MDC04_SCRPARAMETERS); i++)
    {
			OW_WriteByte(*scr++);
		}

    return TRUE;
}

/**
  * @brief  保存暂存器和扩展暂存器的内容到EEPROM的Page0,并等待编程结束
  * @param  无
  * @retval 状态
**/
bool SavetoE2PROMPage0(void)
{
	if(OW_ResetPresence() == FALSE)
		return FALSE;

	OW_WriteByte(SKIP_ROM);
	OW_WriteByte(COPY_PAGE0);

	/*等待擦除和编程完成*/
	ow_Delay_ms(45);

  return TRUE;
}

/**
  * @brief  启动温度测量
  * @param  无
  * @retval 单总线发送状态
*/
bool ConvertTemp(void)
{
	if(OW_ResetPresence() == FALSE)
		return FALSE;

  OW_WriteByte(SKIP_ROM);
  OW_WriteByte(CONVERT_T);

  return TRUE;
}

/**
  * @brief  启动温度和电容通道1同时测量
  * @param  无
  * @retval 单总线发送状态
*/
bool ConvertTC1(void)
{
	if(OW_ResetPresence() == FALSE)
		return FALSE;

  OW_WriteByte(SKIP_ROM);
  OW_WriteByte(CONVERT_TC1);

  return TRUE;
}

/**
  * @brief  启动(多个通道)电容测量
  * @param  无
  * @retval 单总线发送状态
*/
bool ConvertCap(void)
{
	if(OW_ResetPresence() == FALSE)
		return FALSE;

  OW_WriteByte(SKIP_ROM);
  OW_WriteByte(CONVERT_C);

  return TRUE;
}

/**
  * @brief  等待转换结束后读测量结果。和@ConvertTemp联合使用
  * @param  iTemp:返回的16位温度测量结果
  * @retval 读状态
*/
bool ReadTempWaiting(uint16_t *iTemp)
{
	uint8_t scrb[sizeof(MDC04_SCRATCHPAD_READ)];
	MDC04_SCRATCHPAD_READ *scr = (MDC04_SCRATCHPAD_READ *) scrb;

	/*读9个字节。前两个是温度转换结果,最后字节是前8个的校验和--CRC。*/
	if(MDC04_ReadScratchpad_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读寄存器失败*/
	}

	/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
  if(scrb[8] != MY_OW_CRC8(scrb, 8))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	/*将温度测量结果的两个字节合成为16位字。*/
	*iTemp=(uint16_t)scr->T_msb<<8 | scr->T_lsb;

  return TRUE;
}

/**
  * @brief  查询是否转换结束,然后读测量结果。和@ConvertTemp联合使用
  * @param  iTemp:返回的16温度测量结果
  * @retval 读结果状态
*/
bool ReadTempPolling(uint16_t *iTemp)
{ int timeout = 0;

	/*读状态位时隙。如果转换还没结束,芯片以1响应读时隙。如果转换结束,芯片以0响应度时隙。
	前两个字节是温度转换结果,最后字节是前8个的校验和--CRC。*/
	while (OW_ReadStatus() == BUSY )
	{
		ow_Delay_ms(1);
    timeout++;
		if(timeout > 50)
		{
			return FALSE;				/*超时错误*/
		}
	}

	uint8_t scrb[sizeof(MDC04_SCRATCHPAD_READ)];
	MDC04_SCRATCHPAD_READ *scr = (MDC04_SCRATCHPAD_READ *) scrb;

	/*读9个字节。前两个是温度转换结果,最后字节是前8个的校验和--CRC。*/
	if(MDC04_ReadScratchpad_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*I2C地址头应答为NACK*/
	}

	/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
  if(scrb[8] != MY_OW_CRC8(scrb, 8))
  {
		return FALSE;  /*CRC验证未通过*/
  }
	/*将温度测量结果的两个字节合成为16位字。*/
	*iTemp=(uint16_t)scr->T_msb<<8 | scr->T_lsb;

  return TRUE;
}

/**
  * @brief  等待转换结束后读测量结果。和@ConvertTC1联合使用
  * @param  iTemp:返回的16位温度测量结果
  * @param  iCap1:返回的16位电容通道1测量结果
  * @retval 读结果状态
*/
bool ReadTempCap1(uint16_t *iTemp, uint16_t *iCap1)
{
	uint8_t scrb[sizeof(MDC04_SCRATCHPAD_READ)];
	MDC04_SCRATCHPAD_READ *scr = (MDC04_SCRATCHPAD_READ *) scrb;

	/*读9个字节。前两个是温度转换结果,最后字节是前8个的校验和--CRC。*/
	if(MDC04_ReadScratchpad_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读寄存器失败*/
	}

	/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
  if(scrb[8] != MY_OW_CRC8(scrb, 8))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	*iTemp=(uint16_t)scr->T_msb<<8 | scr->T_lsb;
	*iCap1=(uint16_t)scr->C1_msb<<8 | scr->C1_lsb;

  return TRUE;
}

/**
  * @brief  查询是否转换结束,然后读测量结果。和 @ConvertTC1联合使用
  * @param  iTemp:返回的16温度测量结果
  * @param  iCap1:返回的16电容1测量结果
  * @retval 读结果状态
*/
bool ReadTempCap1Polling(uint16_t *iTemp, uint16_t *iCap1)
{ int timeout=0;

	/*读状态位时隙。如果转换还没结束,芯片以1响应读时隙。如果转换结束,芯片以0响应度时隙。
	前两个字节是温度转换结果,最后字节是前8个的校验和--CRC。*/
	while (OW_ReadStatus() == BUSY )
	{
		ow_Delay_ms(1);
    timeout++;
		if(timeout > 50)
		{
			return FALSE;				/*超时错误*/
		}
	}

	uint8_t scrb[sizeof(MDC04_SCRATCHPAD_READ)];
	MDC04_SCRATCHPAD_READ *scr = (MDC04_SCRATCHPAD_READ *) scrb;

	/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
	if(MDC04_ReadScratchpad_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*I2C地址头应答为NACK*/
	}

	/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
  if(scrb[8] != MY_OW_CRC8(scrb, 8))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	*iTemp=(uint16_t)scr->T_msb<<8 | scr->T_lsb;
	*iCap1=(uint16_t)scr->C1_msb<<8 | scr->C1_lsb;

  return TRUE;
}

/**
  * @brief  读电容通道2,3和4的测量结果。和 @ConvertCap联合使用
  * @param  icap:数组指针
  * @retval 读结果状态
*/
bool ReadCapC2C3C4(uint16_t *iCap)
{
	uint8_t scrb[sizeof(MDC04_C2C3C4)];
	MDC04_C2C3C4 *scr = (MDC04_C2C3C4 *) scrb;

	/*读6个字节。每两个字节依序分别为通道2、3和4的测量结果,最后字节是前两个的校验和--CRC。*/
	if(MDC04_ReadC2C3C4_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读寄存器失败*/
	}

	/*计算接收的前两个字节的校验和,并与接收的第3个CRC字节比较。*/
//  if(scrb[8] != MY_OW_CRC8(scrb, 8))
//  {
//		return FALSE;  /*CRC验证未通过*/
//  }

	iCap[0] = (uint16_t)scr->C2_msb<<8 | scr->C2_lsb;
	iCap[1] = (uint16_t)scr->C3_msb<<8 | scr->C3_lsb;
	iCap[2] = (uint16_t)scr->C4_msb<<8 | scr->C4_lsb;

  return TRUE;
}

/**
  * @brief  读偏置电容配置寄存器内容
  * @param  Coffset:偏置配置寄存器有效位的内容
  * @retval 无
*/
bool ReadCosConfig(uint8_t *Coscfg)
{
	uint8_t scrb[sizeof(MDC04_SCRPARAMETERS)];
	MDC04_SCRPARAMETERS *scr = (MDC04_SCRPARAMETERS *) scrb;

	/*读15个字节。第5字节是偏置电容配置寄存器,第10字节是量程电容配置寄存器,最后字节是前14个的校验和--CRC。*/
	if(MDC04_ReadParameters_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读寄存器失败*/
	}

	/*计算接收的前14个字节的校验和,并与接收的第15个CRC字节比较。*/
  if(scrb[sizeof(MDC04_SCRPARAMETERS)-1] != MY_OW_CRC8(scrb, sizeof(MDC04_SCRPARAMETERS)-1))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	*Coscfg = scr->Cos & (0xFF >> (3 - (scr->Cfb >> 6))); //屏蔽掉无效位,根据CFB寄存器的高2位

  return TRUE;
}

/**
  * @brief  写偏置电容配置寄存器和有效位宽设置
  * @param  Coffset:偏置配置寄存器的数值
  * @param  Cosbits:偏置配置寄存器有效位宽,可能为:
	*		@COS_RANGE_5BIT
	*		@COS_RANGE_6BIT
	*		@COS_RANGE_7BIT
	*		@COS_RANGE_8BIT
  * @retval 状态
*/
bool WriteCosConfig(uint8_t Coffset, uint8_t Cosbits)
{
	uint8_t scrb[sizeof(MDC04_SCRPARAMETERS)];
	MDC04_SCRPARAMETERS *scr = (MDC04_SCRPARAMETERS *) scrb;

	/*读15个字节。第5字节是偏置电容配置寄存器,第10字节是量程电容配置寄存器,最后字节是前14个的校验和--CRC。*/
	if(MDC04_ReadParameters_SkipRom(scrb) == FALSE)
	{
		return FALSE;   /*读寄存器失败*/
	}

	/*计算接收的前14个字节的校验和,并与接收的第15个CRC字节比较。*/
  if(scrb[sizeof(MDC04_SCRPARAMETERS)-1] != MY_OW_CRC8(scrb, sizeof(MDC04_SCRPARAMETERS)-1))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	scr->Cos = Coffset;
	scr->Cfb = (scr->Cfb & ~CFB_COSRANGE_Mask) | Cosbits;

	MDC04_WriteParameters_SkipRom(scrb);

  return TRUE;
}

/**
  * @brief  读量程电容配置寄存器内容
  * @param  Cfb:量程配置寄存器低6位的内容
  * @retval 状态
*/
bool ReadCfbConfig(uint8_t *Cfb)
{
	uint8_t scrb[sizeof(MDC04_SCRPARAMETERS)];
	MDC04_SCRPARAMETERS *scr = (MDC04_SCRPARAMETERS *) scrb;

	/*读15个字节。第5字节是偏置电容配置寄存器,第10字节是量程电容配置寄存器,最后字节是前14个的校验和--CRC。*/
	if(MDC04_ReadParameters_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读寄存器失败*/
	}

	/*计算接收的前14个字节的校验和,并与接收的第15个CRC字节比较。*/
  if(scrb[sizeof(MDC04_SCRPARAMETERS)-1] != MY_OW_CRC8(scrb, sizeof(MDC04_SCRPARAMETERS)-1))
  {
		return FALSE;   /*CRC验证未通过*/
  }

	*Cfb = scr->Cfb & MDC04_CFEED_CFB_MASK;

  return TRUE;;
}

/**
  * @brief  写量程电容配置寄存器
  * @param  Cfb:量程配置寄存器低6位的内容
  * @retval 状态
*/
bool WriteCfbConfig(uint8_t Cfb)
{
	uint8_t scrb[sizeof(MDC04_SCRPARAMETERS)];
	MDC04_SCRPARAMETERS *scr = (MDC04_SCRPARAMETERS *) scrb;

	/*读15个字节。第5字节是偏置电容配置寄存器,第10字节是量程电容配置寄存器,最后字节是前14个的校验和--CRC。*/
	if(MDC04_ReadParameters_SkipRom(scrb) == FALSE)
	{
		return FALSE;   /*读寄存器失败*/
	}

	/*计算接收的前14个字节的校验和,并与接收的第15个CRC字节比较。*/
  if(scrb[sizeof(MDC04_SCRPARAMETERS)-1] != MY_OW_CRC8(scrb, sizeof(MDC04_SCRPARAMETERS)-1))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	scr->Cfb &= ~CFB_CFBSEL_Mask;
	scr->Cfb |= Cfb;

	MDC04_WriteParameters_SkipRom(scrb);

  return TRUE;
}

/**
  * @brief  读电容转换通道选择
  * @param  chann:通道选择寄存器Ch_Sel低3位的内容,可能为:
		CCS_CapChannel_Cap1
		CCS_CapChannel_Cap2
		CCS_CapChannel_Cap3
		CCS_CapChannel_Cap4
		CCS_CapChannel_Cap1_2
		CCS_CapChannel_Cap1_2_3
		CCS_CapChannel_Cap1_2_3_4
  * @retval 状态
*/
bool GetCapChannel(uint8_t *chann)
{
	uint8_t scrb[sizeof(MDC04_SCRPARAMETERS)];
	MDC04_SCRPARAMETERS *scr = (MDC04_SCRPARAMETERS *) scrb;

	/*读15个字节。第4字节是通道选择寄存器,最后字节是前14个的校验和--CRC。*/
	if(MDC04_ReadParameters_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读寄存器失败*/
	}

	/*计算接收的前14个字节的校验和,并与接收的第15个CRC字节比较。*/
  if(scrb[sizeof(MDC04_SCRPARAMETERS)-1] != MY_OW_CRC8(scrb, sizeof(MDC04_SCRPARAMETERS)-1))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	*chann = scr->Ch_Sel & CCS_CHANNEL_Mask;

	return TRUE;
}

/**
  * @brief  写电容转换通道选择
  * @param  chann:通道选择寄存器Ch_Sel低3位的内容,可能为:
		CCS_CapChannel_Cap1
		CCS_CapChannel_Cap2
		CCS_CapChannel_Cap3
		CCS_CapChannel_Cap4
		CCS_CapChannel_Cap1_2
		CCS_CapChannel_Cap1_2_3
		CCS_CapChannel_Cap1_2_3_4
  * @retval 状态
*/
bool SetCapChannel(uint8_t chann)
{
	uint8_t scrb[sizeof(MDC04_SCRPARAMETERS)];
	MDC04_SCRPARAMETERS *scr = (MDC04_SCRPARAMETERS *) scrb;

	/*读15个字节。第4字节是通道选择寄存器,最后字节是前14个的校验和--CRC。*/
	if(MDC04_ReadParameters_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读寄存器失败*/
	}

	/*计算接收的前14个字节的校验和,并与接收的第15个CRC字节比较。*/
  if(scrb[sizeof(MDC04_SCRPARAMETERS)-1] != MY_OW_CRC8(scrb, sizeof(MDC04_SCRPARAMETERS)-1))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	scr->Ch_Sel = (scr->Ch_Sel & ~CCS_CHANNEL_Mask) | (chann & CCS_CHANNEL_Mask);

	MDC04_WriteParameters_SkipRom(scrb);

	return TRUE;
}

/**
  * @brief  设置周期测量频率和重复性
  * @param  mps 要设置的周期测量频率(每秒测量次数),可能为下列其一
	*				@arg CFG_MPS_Single		:每执行ConvertTemp一次,启动一次温度测量
	*				@arg CFG_MPS_Half			:每执行ConvertTemp一次,启动每秒0.5次重复测量
	*				@arg CFG_MPS_1				:每执行ConvertTemp一次,启动每秒1次重复测量
	*				@arg CFG_MPS_2				:每执行ConvertTemp一次,启动每秒2次重复测量
	*				@arg CFG_MPS_4				:每执行ConvertTemp一次,启动每秒4次重复测量
	*				@arg CFG_MPS_10				:每执行ConvertTemp一次,启动每秒10次重复测量
  * @param  repeatability:要设置的重复性值,可能为下列其一
	*				@arg CFG_Repeatbility_Low				:设置低重复性
	*				@arg CFG_Repeatbility_Medium		:设置中重复性
	*				@arg CFG_Repeatbility_High			:设置高重复性
  * @retval 无
*/
bool SetConfig(uint8_t mps, uint8_t repeatability)
{
	uint8_t scrb[sizeof(MDC04_SCRATCHPAD_READ)];
	MDC04_SCRATCHPAD_READ *scr = (MDC04_SCRATCHPAD_READ *) scrb;

	/*读9个字节。第7字节是系统配置寄存器,第8字节是系统状态寄存器。最后字节是前8个的校验和--CRC。*/
	if(MDC04_ReadScratchpad_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*读暂存器组水平*/
	}

	/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
  if(scrb[8] != MY_OW_CRC8(scrb, 8))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	scr->Cfg &= ~CFG_Repeatbility_Mask;
	scr->Cfg |= repeatability;
	scr->Cfg &= ~CFG_MPS_Mask;
	scr->Cfg |= mps;

	MDC04_WriteScratchpad_SkipRom(scrb+4);

	return TRUE;
}

/**
  * @brief  读状态和配置
  * @param  status 返回的状态寄存器值
  * @param  cfg 返回的配置寄存器值
  * @retval 状态
*/
bool ReadStatusConfig(uint8_t *status, uint8_t *cfg)
{
	uint8_t scrb[sizeof(MDC04_SCRATCHPAD_READ)];
	MDC04_SCRATCHPAD_READ *scr = (MDC04_SCRATCHPAD_READ *) scrb;

	/*读9个字节。第7字节是系统配置寄存器,第8字节是系统状态寄存器。最后字节是前8个的校验和--CRC。*/
	if(MDC04_ReadScratchpad_SkipRom(scrb) == FALSE)
	{
		return FALSE;  /*CRC验证未通过*/
	}

	/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
  if(scrb[8] != MY_OW_CRC8(scrb, 8))
  {
		return FALSE;  /*CRC验证未通过*/
  }

	*status = scr->Status;
	*cfg = scr->Cfg;

	return TRUE;
}

/**
  * @brief  将偏置电容数值(pF)转换为对应的偏置电容配置
  * @param  osCap:偏置电容的数值
  * @retval 对应偏置配置寄存器的数值
*/
uint8_t CaptoCoscfg(float osCap)
{int i; uint8_t CosCfg = 0x00;

	for(i = 7; i >= 0; i--)
	{
		if(osCap >= COS_Factor[i])
		{
			CosCfg |= (0x01 << i);
			osCap -= COS_Factor[i];
		}
	}

	return CosCfg;
}

/**
  * @brief  将偏置电容配置转换为对应的偏置电容数值(pF)
  * @param  osCfg:偏置电容配置
  * @retval 对应偏置电容的数值
*/
float CoscfgtoCapOffset(uint8_t osCfg)
{
	uint8_t i;
	float Coffset = 0.0;

	for(i = 0; i < 8; i++)
	{
		if(osCfg & 0x01) Coffset += COS_Factor[i];
		osCfg >>= 1;
	}

	return Coffset;
}

/**
  * @brief  将量程电容数值(pF)转换为对应的量程电容配置
  * @param  fsCap:量程电容的数值
  * @retval 对应量程配置的数值
*/
uint8_t CapRangetocfbCfg(float fsCap)
{int8_t i; uint8_t CfbCfg = 0x00;

	fsCap = fsCap * (3.6/0.507);

	fsCap -= CFB.Cfb0;

	for(i = 5; i >= 0; i--)
	{
		if(fsCap >= CFB.Factor[i])
		{
			fsCap -= CFB.Factor[i];
			CfbCfg |= (0x01 << i);
		}
	}

	return CfbCfg;
}

/**
  * @brief  将量程电容配置转换为对应的量程电容数值(pF)
  * @param  fbCfg:量程电容配置
  * @retval 对应量程电容的数值
*/
float CfbcfgtoCapRange(uint8_t fbCfg)
{
	uint8_t i;
	float Crange = CFB.Cfb0;

	for(i = 0; i <= 5; i++)
	{
		if(fbCfg & 0x01) Crange += CFB.Factor[i];
		fbCfg >>= 1;
	}

	return (0.507/3.6) * Crange;
}

/**
  * @brief  获取配置的偏置电容数值(pF)
  * @param  Coffset:偏置电容配置
  * @retval 无
*/
void GetCfg_CapOffset(float *Coffset)
{uint8_t Cos_cfg;

	ReadCosConfig(&Cos_cfg);
	*Coffset = CoscfgtoCapOffset(Cos_cfg);
}

/**
  * @brief  获取配置的量程电容数值(pF)
  * @param  Crange:返回量程电容数值
  * @retval 无
*/
void GetCfg_CapRange(float *Crange)
{
	uint8_t Cfb_cfg;

	ReadCfbConfig(&Cfb_cfg);
	*Crange = CfbcfgtoCapRange(Cfb_cfg);
}

/**
  * @brief  配置偏置电容
  * @param  Coffset:要配置的偏置电容数值。范围0~103.5 pF。
  * @retval 状态
*/
bool MDC04_CapConfigureOffset(float Coffset)
{
	uint8_t CosCfg, Cosbits;
	CosCfg = CaptoCoscfg(Coffset + 0.25);

	if(!(CosCfg & ~0x1F)) Cosbits = COS_RANGE_5BIT;
	else if(!(CosCfg & ~0x3F)) Cosbits = COS_RANGE_6BIT;
			 else if(!(CosCfg & ~0x7F)) Cosbits = COS_RANGE_7BIT;
						else Cosbits = COS_RANGE_8BIT;

	WriteCosConfig(CosCfg, Cosbits);

	return TRUE;
}

/**
  * @brief  配置量程电容
  * @param  Cfs:要配置的量程电容数值。范围+/-(0.281~15.49) pF。
  * @retval 状态
*/
bool MDC04_CapConfigureFs(float Cfs)
{
	uint8_t Cfbcfg;

	Cfs = (Cfs + 0.1408);
	Cfbcfg = CapRangetocfbCfg(Cfs);

	WriteCfbConfig(Cfbcfg);

	return TRUE;
}

/**
  * @brief  配置电容测量范围
  * @param  Cmin:要配置测量范围的低端。
  * @param  Cmax:要配置测量范围的高端。
  * @retval 状态
*/
bool MDC04_CapConfigureRange(float Cmin, float Cmax)
{ float Cfs, Cos;

//	if(!((Cmax <= 119.0) && (Cmax > Cmin) && (Cmin >= 0.0) && ((Cmax-Cmin) <= 31.0)))
//	return FALSE;	//The input value is out of range.

	Cos = (Cmin + Cmax)/2.0;
	Cfs = (Cmax - Cmin)/2.0;

	MDC04_CapConfigureOffset(Cos);
	MDC04_CapConfigureFs(Cfs);

	return TRUE;
}


/**
  * @brief  读电容配置
  * @param  Coffset:配置的偏置电容。
  * @param  Crange:配置的量程电容。
  * @retval 无
*/
bool ReadCapConfigure(float *Coffset, float *Crange)
{
	GetCfg_CapOffset(Coffset);
	GetCfg_CapRange(Crange);

	return TRUE;
}




MDC04驱动代码头文件

MDC04_driver.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MDC04_driver_H
#define MDC04_driver_H

//*********MCU文件**********//
#include "stm32f10x_rcc.h"
#include "MY_stdtype.h"

/* MDC04/01 Registers definition----------------------------------------------*/
/*Bit definition of config register*/
#define CFG_CLKSTRETCH_Mask   	0x20
#define CFG_MPS_Mask   		  	0x1C
#define CFG_Repeatbility_Mask 	0x03

#define CFG_MPS_Single  	0x00
#define CFG_MPS_Half  		0x04
#define CFG_MPS_1  			0x08
#define CFG_MPS_2 			0x0C
#define CFG_MPS_4 			0x10
#define CFG_MPS_10 			0x14

#define CFG_Repeatbility_Low   	0x00
#define CFG_Repeatbility_Medium 0x01
#define CFG_Repeatbility_High 	0x02

#define CFG_ClkStreatch_Disable (0x00 << 5)
#define CFG_ClkStreatch_Enable 	(0x01 << 5)
/*Bit definition of status register*/
#define Status_Meature_Mask   	0x81
#define Status_WriteCrc_Mask   	0x20
#define Status_CMD_Mask   			0x10
#define Status_POR_Mask   			0x08

/*Bit definition of CFB register*/
#define CFB_COSRANGE_Mask   		0xC0
#define CFB_CFBSEL_Mask   			0x3F

#define CFB_COS_BITRANGE_5  		0x1F
#define CFB_COS_BITRANGE_6  		0x3F
#define CFB_COS_BITRANGE_7  		0x7F
#define CFB_COS_BITRANGE_8  		0xFF

#define COS_RANGE_5BIT				  		0x00
#define COS_RANGE_6BIT				  		0x40
#define COS_RANGE_7BIT				  		0x80
#define COS_RANGE_8BIT				  		0xC0
/*Bit definition of Ch_Sel register*/
#define CCS_CHANNEL_Mask   					0x07

#define CCS_CapChannel_Cap1					0x01 		
#define CCS_CapChannel_Cap2					0x02
#define CCS_CapChannel_Cap3					0x03
#define CCS_CapChannel_Cap4					0x04
#define CCS_CapChannel_Cap1_2				0x05
#define CCS_CapChannel_Cap1_2_3			    0x06
#define CCS_CapChannel_Cap1_2_3_4		    0x07

#define CAP_CH1_SEL  								0x01
#define CAP_CH2_SEL  								0x02
#define CAP_CH3_SEL  								0x03
#define CAP_CH4_SEL  								0x04
#define CAP_CH1CH2_SEL  						0x05
#define CAP_CH1CH2CH3_SEL  					0x06
#define CAP_CH1CH2CH3CH4_SEL  			0x07

/******************  Bit definition for MDC04 configuration register  ******************/
#define MDC04_CFG_REPEATABILITY_MASK          0x03
#define MDC04_CFG_MPS_MASK										0x1C
#define MDC04_CFG_I2CCLKSTRETCH_MASK          0x20
/******************  Bit definition for MDC04 temperature register  *******/
#define MDC04_REPEATABILITY_LOW               (0x00 << 0)
#define MDC04_REPEATABILITY_MEDIUM            (0x01 << 0)
#define MDC04_REPEATABILITY_HIGH              (0x02 << 0)
/******************  Bit definition for TTrim in parameters  *******/
#define MDC04_MPS_SINGLE					            (0x00 << 2)
#define MDC04_MPS_0P5Hz					            	(0x01 << 2)
#define MDC04_MPS_1Hz					            		(0x02 << 2)
#define MDC04_MPS_2Hz					            		(0x03 << 2)
#define MDC04_MPS_4Hz					            		(0x04 << 2)
#define MDC04_MPS_10Hz					            	(0x05 << 2)

#define MDC04_CLKSTRETCH_EN					          (0x01 << 5)
/******************  Bit definition for status register  *******/
#define MDC04_STATUS_CONVERTMODE_MASK          0x81
#define MDC04_STATUS_I2CDATACRC_MASK           0x20
#define MDC04_STATUS_I2CCMDCRC_MASK            0x10
#define MDC04_STATUS_SYSRESETFLAG_MASK         0x08

#define MDC04_CONVERTMODE_IDLE             		 0x00
#define MDC04_CONVERTMODE_T             		   0x01
#define MDC04_CONVERTMODE_C             		   0x02
#define MDC04_CONVERTMODE_TC1            		   0x03
/******************  Bit definition for channel select register  *******/
#define MDC04_CHANNEl_SELECT_MASK           	 0x07
#define MDC04_CHANNEl_C1           					   0x01
#define MDC04_CHANNEl_C2           					   0x02
#define MDC04_CHANNEl_C3           					   0x03
#define MDC04_CHANNEl_C4           					   0x04
#define MDC04_CHANNEl_C1C2           				   0x05
#define MDC04_CHANNEl_C1C2C3           		   	 0x06
#define MDC04_CHANNEl_C1C2C3C4           	   	 0x07
/******************  Bit definition for feeadback capacitor register  *******/
#define MDC04_CFEED_OSR_MASK           	   		 0xC0
#define MDC04_CFEED_CFB_MASK           	   		 0x3F

/* MDC04/01 ow Commands-------------------------------------------------------*/
typedef enum
{
	//ROM command
    SKIP_ROM            	= 0xcc,
    READ_ROM            	= 0x33,
    MATCH_ROM           	= 0x55,
	SEARCH_ROM           	= 0xf0, 
	ALARM_SEARCH			= 0xec,
	//Function command
    CONVERT_C           	= 0x66,
    CONVERT_T           	= 0x44,
	CONVERT_TC1             = 0x10,	
	READ_SCRATCHPAD     	= 0xbe,
	WRITE_SCRATCHPAD     	= 0x4e,
	READ_TC1             	= 0xcf,	
	READ_C2C3C4			    = 0xdc,
	READ_PARAMETERS      	= 0x8b,
	WRITE_PARAMETERS     	= 0xab,	
	COPY_PAGE0				= 0x48,
	READ_SCRATCHPAD_EXT  	= 0xdd,
	WRITE_SCRATCHPAD_EXT 	= 0x77,
} MDC04_OW_CMD;

/******************  Scratchpad/SRAM  ******************/
/*SRAM scratchpad*/
typedef struct
{
	uint8_t T_lsb;					/*The LSB of 温度结果, RO*/
	uint8_t T_msb;					/*The MSB of 温度结果, RO*/
	uint8_t C1_lsb;					/*The LSB of 电容通道C1, RO*/
	uint8_t C1_msb;					/*The MSB of 电容通道C1, Ro*/	
	uint8_t Tha_set_lsb;		
	uint8_t Tla_set_lsb;		
	uint8_t Cfg;						/*系统配置寄存器, RW*/
	uint8_t Status;					/*系统状态寄存器, RO*/
	uint8_t crc_scr;				/*CRC for byte0-7, RO*/
} MDC04_SCRATCHPAD_READ;

typedef struct
{	
	int8_t Tha_set_lsb;				
	int8_t Tla_set_lsb;			
	uint8_t Cfg;						/*系统配置寄存器, RW*/
} MDC04_SCRATCHPAD_WRITE;

typedef struct
{
	uint8_t tha_clear;				
	uint8_t tla_clear;					
	uint8_t hha_set;					
	uint8_t hla_set;					
	uint8_t hha_clear;				
	uint8_t hla_clear;					
	uint8_t udf[5];							
	uint8_t MPW_test;					
	uint8_t crc_ext;						
} MDC04_SCRATCHPADEXT;

typedef struct
{	
	uint8_t C2_lsb;				/*The LSB of C2, RO*/
	uint8_t C2_msb;				/*The MSB of C2, RO*/
	uint8_t C3_lsb;				/*The LSB of C3, RO*/
	uint8_t C3_msb;				/*The MSB of C3, RO*/
	uint8_t C4_lsb;				/*The LSB of C4, RO*/
	uint8_t C4_msb;				/*The MSB of C4, RO*/
/*crc*/	
} MDC04_C2C3C4;

typedef struct
{
	uint8_t Family;				/*Family byte, RO*/
	uint8_t Id[6];				/*Unique ID, RO*/
	uint8_t crc_rc;				/*Crc code for byte0-7, RO*/
} MDC04_ROMCODE;

typedef struct
{
	uint8_t Res[3];
	uint8_t Ch_Sel;					/*电容通道选择寄存器,RW*/
	uint8_t Cos;						/*偏置电容配置寄存器,RW*/
	uint8_t Res1;				
	uint8_t T_coeff[3];			
	uint8_t Cfb;						/*量程电容配置寄存器,RW*/									
	uint8_t Res2;
	uint8_t Res3[2];
	uint8_t dummy8;
	uint8_t crc_para;				/*CRC for byte0-13, RO*/
} MDC04_SCRPARAMETERS;


/*顶层驱动函数原型*/
int MY_Read_ROM(void);
int MY_T(void);
int MY_TC1(void);
int MY_C(void);
int MY_P(void);
int MY_F(int repeatability,int mps);
int MY_Channel(uint8_t channel);
int MY_Offset(float Co);
int MY_FullScale(float Cr);
int MY_Range(float Cmin,float Cmax);
int MY_EEPROM(void);

/*底层函数原型*/
float MDC04_OutputtoTemp(int16_t out);
int16_t MDC04_TemptoOutput(float Temp);
bool MDC04_ReadROM(uint8_t *scr);
float MDC04_OutputtoCap(uint16_t out, float Co, float Cr);
uint8_t MY_OW_CRC8(uint8_t *serial, uint8_t length);
bool MDC04_nReadScratchpad_SkipRom(uint8_t *scr, uint8_t size);
bool MDC04_ReadScratchpad_SkipRom(uint8_t *scr);
bool MDC04_WriteScratchpad_SkipRom(uint8_t *scr);
bool MDC04_ReadScratchpadExt_SkipRom(uint8_t *scr);
bool MDC04_WriteScratchpadExt_SkipRom(uint8_t *scr);
bool MDC04_ReadC2C3C4_SkipRom(uint8_t *scr);
bool MDC04_ReadParameters_SkipRom(uint8_t *scr);
bool MDC04_WriteParameters_SkipRom(uint8_t *scr);
bool SavetoE2PROMPage0(void);
bool ConvertTemp(void);
bool ConvertTC1(void);
bool ConvertCap(void);
bool ReadTempWaiting(uint16_t *iTemp);
bool ReadTempPolling(uint16_t *iTemp);
bool ReadTempCap1(uint16_t *iTemp, uint16_t *iCap1);
bool ReadTempCap1Polling(uint16_t *iTemp, uint16_t *iCap1);
bool ReadCapC2C3C4(uint16_t *iCap);
bool ReadCosConfig(uint8_t *Coscfg);
bool WriteCosConfig(uint8_t Coffset, uint8_t Cosbits);
bool ReadCfbConfig(uint8_t *Cfb);
bool WriteCfbConfig(uint8_t Cfb);
bool GetCapChannel(uint8_t *chann);
bool SetCapChannel(uint8_t chann);
bool SetConfig(uint8_t mps, uint8_t repeatability);
bool ReadStatusConfig(uint8_t *status, uint8_t *cfg);
uint8_t CaptoCoscfg(float osCap);
float CoscfgtoCapOffset(uint8_t osCfg);
uint8_t CapRangetocfbCfg(float fsCap);
float CfbcfgtoCapRange(uint8_t fbCfg);
void GetCfg_CapOffset(float *Coffset);
void GetCfg_CapRange(float *Crange);
bool MDC04_CapConfigureOffset(float Coffset);
bool MDC04_CapConfigureFs(float Cfs);
bool MDC04_CapConfigureRange(float Cmin, float Cmax);
bool ReadCapConfigure(float *Coffset, float *Crange);

#endif /*MDC04_driver_H */


用户APP调用函数


/****************************************************************************************/
/*
 *
 * Copyright (C) 2020. Mysentech Inc, unpublished work. This computer 
 * program includes Confidential, Proprietary Information and is a Trade Secret of 
 * Minyuan Sensing Technology Inc.(Mysentech)  All use, disclosure, and/or reproduction is prohibited 
 * unless authorized in writing. All Rights Reserved.
 *
 *  Please contact <sales@mysentech.com> or contributors for further questions.
*/
/****************************************************************************************/
/* Includes(用户内部MCU配置头文件) ------------------------------------------------------------------*/


/* Includes(MDC04驱动头文件) ------------------------------------------------------------------*/
#include "MDC04_driver.h"
#include "bsp_SysTick.h"
#include "MY_ow.h"

extern float CapCfg_offset, CapCfg_range;

/*
  * @brief  读取Rom id函数
*/
int MY_Read_ROM(void)
{ 
	uint8_t rom_id[8];
	
  MDC04_ReadROM(rom_id);
	printf("\r\n MDC04 ROMID :");				
	for(int i=0;i<8;i++)
	{
	printf("%2x ", rom_id[i]);				
	}		
	return 1;
}
/*
  * @brief  测量温度函数
*/
int MY_T(void)
{ 
	float fTemp; uint16_t iTemp; 
	
	if(ConvertTemp() == TRUE)
	{
    ow_Delay_ms(15);
		ReadTempWaiting(&iTemp);
		fTemp=MDC04_OutputtoTemp((int16_t)iTemp); 
		printf("\n\r T= %3.3f ", fTemp);
	}
	else
	{
		printf("\r\n No MDC04");
	}	
	
  ow_Delay_ms(990);
				
	return 1;
}
/*
  * @brief  测量温度+通道1电容函数
*/
int MY_TC1(void)
{	
	uint16_t iTemp, iCap1; 
	float fTemp, fCap1;
		
	 ReadCapConfigure(&CapCfg_offset, &CapCfg_range);
	 SetCapChannel(CAP_CH1_SEL);
	
		if(ConvertTC1() == TRUE)
		{
			ow_Delay_ms(15);		
			if(ReadTempCap1(&iTemp, &iCap1) == TRUE) 
			{
				fTemp=MDC04_OutputtoTemp(iTemp);
				fCap1=MDC04_OutputtoCap(iCap1, CapCfg_offset, CapCfg_range);
				printf("\r\n T= %3.3f C C1= %6.3f pF", fTemp, fCap1);	
			}
		}
		else
		{
			printf("\r\n No MDC04");
		}
		ow_Delay_ms(990);
	return 1;		
}

/*
  * @brief  测量四通道电容函数
*/
int MY_C(void)
{	
	float fcap1, fcap2, fcap3, fcap4; uint16_t iTemp, icap1, icap[3];
	uint8_t status, cfg;
		
	SetCapChannel(CAP_CH1CH2CH3CH4_SEL);
	ReadStatusConfig((uint8_t *)&status, (uint8_t *)&cfg);
	
	if(ConvertCap() == FALSE)
	{
		printf("\r\nNo MDC04");
	}else
	{
		
		ow_Delay_ms(15);
		ReadCapConfigure(&CapCfg_offset, &CapCfg_range);
		{
		ReadStatusConfig((uint8_t *)&status, (uint8_t *)&cfg);
		ReadTempCap1(&iTemp, &icap1);
		ReadCapC2C3C4(icap);

		fcap1 = MDC04_OutputtoCap(icap1, CapCfg_offset, CapCfg_range);
		fcap2 = MDC04_OutputtoCap(icap[0], CapCfg_offset, CapCfg_range);
		fcap3 = MDC04_OutputtoCap(icap[1], CapCfg_offset, CapCfg_range);
		fcap4=  MDC04_OutputtoCap(icap[2], CapCfg_offset, CapCfg_range);
		printf("\r\n C1=%5d , %6.3f  C2=%5d, %6.3f  C3=%5d, %6.3f  C4=%5d, %6.3f  SC=%02X%02X", icap1, fcap1, icap[0], fcap2, icap[1], fcap3, icap[2], fcap4, status, cfg);
		}
	}
	ow_Delay_ms(990);
	return 1;		
}

/*
  * @brief  Polling模式下读取温度函数
*/
int MY_P(void)
{ 
	uint16_t iTemp;
	
	ConvertTemp();
	ReadTempPolling(&iTemp);
	MDC04_OutputtoTemp((int16_t)iTemp); 
	
	return 1;
}

/*
  * @brief  设置配置寄存器
  * MPS:  000   001     010    011    100   101
  *      单次  0.5次/S 1次/S  2次/S  4次/S 10次/S
  * Repeatability:  00: 低重复性
  *                 01:中重复性
  *                 10:高重复性
*/
int MY_F(int repeatability,int mps)
{ 
	int status, cfg;
	SetConfig(mps & 0x07, repeatability & 0x03);
	ReadStatusConfig((uint8_t *)&status, (uint8_t *)&cfg);
	printf("S=%02x C=%02x", status, cfg);
	
	return 0;
}

/*
  * @brief      设置电容测量通道
  * Cap1					0x01 		
  * Cap2					0x02
  * Cap3					0x03
  * Cap4					0x04
  * Cap1_2				0x05
  * Cap1_2_3			0x06
  * Cap1_2_3_4		0x07
*/
int MY_Channel(uint8_t channel)
{ 
			
		SetCapChannel(channel);
									
		return 1;
}

/*
  * @brief  设置偏置电容offset
*/
int MY_Offset(float Co)
{ 
				
		printf("\r\nCo= %5.2f", Co);
			
		if(!((Co >=0.0) && (Co <= 103.5))) 
		{
		printf(" %s", "The input is out of range"); 
			return 0;
		}
		
		MDC04_CapConfigureOffset(Co);
		
		return 1;
}

/*
  * @brief  设置量程电容
  * 默认出厂配置量程电容±15.5pf
*/
int MY_FullScale(float Cr)
{  	
	   printf("\r\nCr= %5.3f", Cr);
			
	   if(!((Cr >=0.0) && (Cr <= 15.5))) 
		{printf(" %s", "The input is out of range"); return 0;}
		
		MDC04_CapConfigureFs(Cr);
	
		ReadCapConfigure(&CapCfg_offset, &CapCfg_range);	
		
		return 1;
}
/*
  * @brief  设置电容测量范围
  * 请勿设置超出电容量程0~119pf,请勿超出最大range:±15.5pf
*/
int MY_Range(float Cmin,float Cmax)
{ 
//		printf("\r\nCmin= %3.2f Cmax=%3.2f", Cmin, Cmax);
			
		if(!((Cmax <= 119.0) && (Cmax > Cmin) && (Cmin >= 0.0) && ((Cmax-Cmin) <= 31.0)))  
		{printf(" %s", "The input is out of range"); return 0;}
		
		MDC04_CapConfigureRange(Cmin, Cmax);
		
		ReadCapConfigure(&CapCfg_offset, &CapCfg_range);
		
		return 1;
}

/*
  * @brief 将暂存器内配置存入EEPROM
*/
int MY_EEPROM(void)
{
	
	SavetoE2PROMPage0();
	
	return 1;
}

main主程序

#include <stdio.h>
#include <stdlib.h>

#include "stm32f10x.h"

#include "bsp_SysTick.h"
#include "bsp_usart1.h"

#include "MY_ow.h"
#include "MDC04_driver.h"

int main(void)
{ 
	float Cmin=0, Cmax=30;

	USART1_Config();
	SysTick_Init();
	
	OW_Init();
	
	/********************读取MDC04_ROM_ID*******************************/
		MY_Read_ROM();
	
	/********************电容配置流程***********************************/
	MY_Range(Cmin,Cmax); 		//Cmax-Cmin<31pF,配置最大最小电容值,确定量程范围
	MY_F(MDC04_REPEATABILITY_HIGH,MDC04_MPS_SINGLE);		//配置高重复性,单次测量
	MY_Channel(0x07);
	while(1)
	{
		/********************单独测温*************************************/
//		MY_T();
		/********************温度及1通道电容测量**************************/
		MY_TC1();
		/********************4通道电容测量********************************/
//		MY_C();
//		ow_Delay_ms(1000000);     
	}
}

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

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

相关文章

配置Super-VLAN下的DHCP服务器示例

组网需求 如图1所示&#xff0c;某公司拥有两个部门&#xff0c;为了节省IP地址&#xff0c;部门A和部门B规划为同一网段&#xff1b;为了提升业务安全性&#xff0c;将不同部门的用户划分到不同VLAN中。企业管理员为了方便统一管理&#xff0c;希望部门内终端通过DHCP服务器动…

4.4 审计

思维导图&#xff1a; 4.4 审计理解笔记&#xff1a; 1. 审计的重要性&#xff1a; 除了用户身份验证和访问控制&#xff0c;审计是实现数据库安全的关键组成部分。审计是达到高安全标准&#xff08;如TDI/TCSEC的C2级别&#xff09;的必要功能。 2. 审计功能的核心&#xf…

【密评】商用密码应用安全性评估从业人员考核题库(十四)

商用密码应用安全性评估从业人员考核题库&#xff08;十四&#xff09; 国密局给的参考题库5000道只是基础题&#xff0c;后续更新完5000还会继续更其他高质量题库&#xff0c;持续学习&#xff0c;共同进步。 3251 单项选择题 根据GB/T 39786《信息安全技术 信息系统密码应用…

07.K8S高可用集群节点规划

K8S高可用集群节点规划 1、部署拓扑图 2、master节点数(物理机数) 总数最少存活失败容忍说明110单个主节点时使用220不推荐321推荐431不推荐532推荐642不推荐743可以考虑&#xff0c;但会导致确定集群成员和仲裁的开销加大853不推荐954可以考虑&#xff0c;但会导致确定集群成…

[论文笔记]GTE

引言 今天带来今年的一篇文本嵌入论文GTE, 中文题目是 多阶段对比学习的通用文本嵌入。 作者提出了GTE,一个使用对阶段对比学习的通用文本嵌入。使用对比学习在多个来源的混合数据集上训练了一个统一的文本嵌入模型,通过在无监督预训练阶段和有监督微调阶段显著增加训练数…

Java电商平台 - API 接口设计之 token、timestamp、sign 具体架构与实现|电商API接口接入

一&#xff1a;token 简介 Token&#xff1a;访问令牌access token, 用于接口中, 用于标识接口调用者的身份、凭证&#xff0c;减少用户名和密码的传输次数。一般情况下客户端(接口调用方)需要先向服务器端申请一个接口调用的账号&#xff0c;服务器会给出一个appId和一个key, …

Python 算法高级篇:归并排序的优化与外部排序

Python 算法高级篇&#xff1a;归并排序的优化与外部排序 引言 1. 归并排序的基本原理2. 归并排序的优化2.1 自底向上的归并排序2.2 最后优化 3. 外部排序4. 性能比较5. 结论 引言 在计算机科学中&#xff0c;排序是一项基本的任务&#xff0c;而归并排序&#xff08; Merge S…

轻量封装WebGPU渲染系统示例<2>-彩色立方体(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/version-1.01/src/voxgpu/sample/VertColorCube.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 2. 高频调用与低频调用隔离。 3. 面向用户的易用性封装。 4. 渲染数据和渲染机制分离。 5. …

@Lazy注解的原理

1.ContextAnnotationAutowireCandidateResolver是主要逻辑类 2.当Lazy与Autowired或者Resource合用时&#xff0c;依赖创建的是代理对象(目标对象是TargetSource),在执行时&#xff0c;执行的是代理对象&#xff0c;在invoke(Object proxy,Method method,Object[] args)中执行…

Linux虚拟机部署与发布项目(Windows版本)

目录 前言 一、虚拟机部署项目的流程 二、单机项目 1. 本机测试 2.虚拟机部署项目 三、前后端分离项目 前言 在软件开发过程中&#xff0c;部署和发布项目是非常重要的一环。使用虚拟机技术可以方便、灵活且可重复使用地部署和发布项目。本篇博客将介绍如何在 Windows 环…

代码随想录打卡第五十三天|309.最佳买卖股票时机含冷冻期 ● 714.买卖股票的最佳时机含手续费

309.最佳买卖股票时机含冷冻期 题目&#xff1a; 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 卖…

2023年中国道路扫雪车分类、市场规模及发展前景分析[图]

道路扫雪车是一种专门用于清除道路上积雪和冰雪的机动车辆&#xff0c;通常配备有雪铲、扫雪刷、除冰剂喷洒系统等装置&#xff0c;用于在雪季或寒冷气候条件下&#xff0c;对道路进行清扫、除雪、除冰等作业&#xff0c;以确保道路的通行安全。 道路扫雪车行业分类 资料来源&…

浅谈分布式系统

文章目录 分布式系统应用数据分离架构应用服务集群架构读写分离 / 主从分离架构引入缓存--冷热分离架构数据库分库分表存储集群微服务架构小结 分布式系统 只有一台服务器负责所有的工作称为单机架构&#xff0c;但是一台主机的硬件资源是有上限的&#xff0c;当同一时刻主机收…

借助 Pyroscope 对 Amazon EKS 容器服务进行 Continuous Profiling 诊断应用性能

Continuous Profiling 的现状 在可观测领域&#xff0c;Trace、Log、Metrics 作为“三大支柱”&#xff0c;帮助工程师更方便的洞察应用的内部问题。然而&#xff0c;对于开发人员而言&#xff0c;经常还需要深入应用程序&#xff0c;找出造成瓶颈的根本原因。在可观测的“三大…

Annotorious入门教程:图片注释工具

本文简介 最近有工友问我前端怎么给图片做标注。使用 Fabric.js 或者 Konva.js 等库确实可以实现&#xff0c;但我又好奇有没有专门做图片标注的工具呢&#xff1f; 在网上搜了一下发现 Annotorious 可以实现这个功能。Annotorious 提供了图片注释和标注功能&#xff0c;而且…

UVa10976 Fractions Again?!(分数拆分)

1、题目 2、题意 输入正整数 k k k&#xff0c;找到所有正整数 x ≥ y x \ge y x≥y&#xff0c;使得 1 k 1 x 1 y \frac{1}{k} \frac{1}{x} \frac{1}{y} k1​x1​y1​。 3、分析 既然要求找出所有的 x , y x,y x,y&#xff0c;枚举对象自然是 x , y x,y x,y了。可…

​Vue2【双向数据绑定/响应式原理】

目录 初始化 initProps()&#xff1a;父组件传的 props 列表&#xff0c;proxy() 把属性代理到当前实例上 vm._props.xx 变成 vm.xx initData()&#xff1a;判断data和props、methods是否重名&#xff0c;proxy() 把属性代理到当前实例上 this.xx observe()&#xff1a;给…

c++实现dijskstra算法

图 我一开始写成了最小生成树的代码&#xff0c;最小生成树一直在选最小的那条边&#xff0c;对每个节点来说&#xff0c;它到原点的距离不一定是最近的。 代码 #include<iostream> using namespace std; #include<list> #include<vector>class Node { pub…

RocketMQ事务消息 超时重发还是原来的消息吗?

以下面的一个demo例子来分析一下&#xff0c;探索RocketMQ事务消息原理。 public static final String PRODUCER_GROUP "tran-test";public static final String DEFAULT_NAMESRVADDR "127.0.0.1:9876";public static final String TOPIC "Test&qu…

如何理解Quadratic Weighted Kappa?

Motivation 假定我们现在有 N N N个作文样例&#xff0c;以及它们对应的人类评分和GPT评分。评分一共有 C C C个互斥类别&#xff0c;分别是{0,1,2,3}。现在我们要衡量人类评分和GPT评分的一致性。 一个很直观的想法是&#xff0c;画出混淆矩阵&#xff0c;然后将对角线上的值…