高精度数字电容传感芯片-MDC04
简介
MDC04以低成本等优势,可用于智能小家电液位、水箱液位、油液液位、水浸传感、食品/土壤水分含量、冰霜检测、位移传感等应用场景。
引脚说明
引脚 | 名称 | 说明 |
---|---|---|
1 | RSTN | 复位,输入;低电平有效 |
2 | MODE | 通讯接口模式选择,输入。0 时,PIN12 为 I²C 的 SDA;1 时,PIN12 为 1-wire 的 DQ。 |
3 | VSS | 电源地 |
4 | C4_OUT | 电容 C4 接入,模拟输出 |
5 | C4_IN | 电容 C4 接入,模拟输入 |
6 | C1_IN | 电容 C1 接入,模拟输入 |
7 | C1_OUT | 电容 C1 接入,模拟输出 |
8 | C2_IN | 电容 C2 接入,模拟输入 |
9 | C2_OUT | 电容 C2 接入,模拟输出 |
10 | C3_IN | 电容 C3 接入,模拟输入 |
11 | C3_OUT | 电容 C3 接入,模拟输出 |
12 | SDA/DQ | I²C 数据线或单总线数据线,I/O |
13 | ADDR | I²C 通讯地址选择线,输入,不可悬空。0 时,I²C 地址为 0x44;1 时,I²C 地址为 0x45。注意:选择单总线通讯模式时,ADDR 需要接地。 |
14 | NC | - |
15 | SCL | I²C 时钟线;I/O,不可悬空。注意:选择单总线通讯模式时,SCL 需要接地。 |
16 | NC | - |
17 | NC | - |
18 | NC | - |
19 | NC | - |
20 | VDD | 电源,输入 |
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
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头文件
c
/* 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
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
c
/* 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调用函数
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(用户内部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主程序
c
#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);
}
}