519 lines
13 KiB
C
519 lines
13 KiB
C
#include "temperature.H"
|
||
#include <stdio.h>
|
||
#include <math.h>
|
||
|
||
UnSwSample UnSwSample_1 = {0};
|
||
#define Measure_Period 11000
|
||
|
||
unsigned char romid[MAXNUM][8];
|
||
int RomNum;
|
||
|
||
/**
|
||
* @brief 计算多个字节序列的校验和
|
||
* @param serial:字节数组指针
|
||
* @param length:字节数组的长度
|
||
* @retval 校验和(CRC)
|
||
*/
|
||
#define POLYNOMIAL 0x131 //100110001
|
||
ubyte MY_OW_CRC8(ubyte *serial, ubyte length)
|
||
{
|
||
ubyte result = 0x00;
|
||
ubyte pDataBuf;
|
||
ubyte 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;
|
||
}
|
||
|
||
|
||
//非精确延时2*X us,固定误差10us
|
||
//@12.000MHz 12T模式
|
||
void Delay_us(uword x)
|
||
{
|
||
for (; x > 0; x--)
|
||
{
|
||
_nop_();
|
||
_nop_();
|
||
}
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////
|
||
// 主机发送 复位脉冲( 大于 480 us 低电平) ,并检查 存在 脉冲
|
||
unsigned char OW_ResetPresence(void)
|
||
{
|
||
unsigned char presence; int count=0;
|
||
|
||
SFR_PAGE(_pp0, noSST); // switch to page 0
|
||
P3_DIR = P3_DIR | 0x20; // load direction register P3.5切换为输出
|
||
|
||
DQ = 0; // 主机拉低 DQ 总线
|
||
Delay_us(240); // 拉低 DQ 总线 持续 480us
|
||
DQ = 1; // 主机释放总线,由上拉电阻拉高
|
||
|
||
SFR_PAGE(_pp0, noSST); // switch to page 0
|
||
P3_DIR = P3_DIR & 0xDF;// load direction register
|
||
|
||
Delay_us(40); // 等待 80us 后检查 presence
|
||
presence = DQ; // 检查存在 脉冲
|
||
while( presence && (count< 17) )
|
||
{
|
||
Delay_us(5);
|
||
presence = DQ;
|
||
count++;
|
||
}
|
||
Delay_us(200); // 时序末尾 等待
|
||
return (presence ? FALSE : TRUE);
|
||
} // presence =0 时, M6 01 存在 , presence =1 时, M601 不存在
|
||
|
||
////////////////////////////////////////////////////////////////////
|
||
//// READ_BIT – 从 M601 读取 一位数
|
||
unsigned char read_bit(void)
|
||
{
|
||
unsigned char res;
|
||
|
||
SFR_PAGE(_pp0, noSST); // switch to page 0
|
||
P3_DIR = P3_DIR | 0x20; // load direction register 切换为输出状态
|
||
|
||
DQ = 0; // 主机拉低 DQ 总线
|
||
Delay_us(1); // 拉低 DQ 总线 持续 3us
|
||
DQ = 1; // 主机释放 DQ 总线,由上拉电阻拉高
|
||
SFR_PAGE(_pp0, noSST); // switch to page 0
|
||
P3_DIR = P3_DIR & 0xDF;// load direction register
|
||
|
||
Delay_us(3); // 等待 10us 确保总线上数据稳定
|
||
|
||
res = DQ;
|
||
Delay_us(27); // 时序末尾 等待
|
||
return(res); // 返回读取 数值
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////
|
||
//// WRITE_BIT – 主机 写一位数据 到 M601
|
||
void write_bit(char bitval)
|
||
{
|
||
SFR_PAGE(_pp0, noSST); // switch to page 0
|
||
P3_DIR = P3_DIR | 0x20; // load direction register 切换为输出状态
|
||
|
||
DQ = 0; // 主机拉低 DQ 总线
|
||
Delay_us(2); // 拉低 DQ 总线 持续 5us
|
||
if(bitval == 1) DQ =1; // 如果 写 1,此时拉高 DQ 总线
|
||
Delay_us(25); // 如果 写 0,则持续拉低 DQ 总线 60 us
|
||
DQ = 1; // 释放 DQ 总线
|
||
Delay_us(5); // (写 0)恢复 时间 10us
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////
|
||
//// READ_BYTE - 从 M601 读取 一字节 数据
|
||
unsigned char OW_ReadByte(void)
|
||
{
|
||
unsigned char i, j;
|
||
unsigned char value = 0;
|
||
for (i = 0;i < 8;i++) {
|
||
j = read_bit();
|
||
value = (value) | (j<<i); // 每次读进 1 位(低位 先行 ), 然后 左移
|
||
}
|
||
return(value);
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////
|
||
//// WRITE_BYTE - 主机 写一字节数据 到 M601
|
||
void OW_WriteByte(char val)
|
||
{
|
||
unsigned char i;
|
||
unsigned char temp;
|
||
for (i = 0; i < 8; i++) { // 写字节 ,每次 一位
|
||
temp = val >> i;
|
||
temp &= 0x01; // 低位 先行
|
||
write_bit(temp);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief 读芯片寄存器的暂存器组
|
||
* @param scr:字节数组指针, 长度为 @sizeof(M601_SCRATCHPAD_READ)
|
||
* @retval 读状态
|
||
*/
|
||
BOOL M601_ReadScratchpad_SkipRom(ubyte *scr)
|
||
{
|
||
int i;
|
||
|
||
// /*size < sizeof(M601_SCRATCHPAD_READ)*/
|
||
if(OW_ResetPresence() == FALSE)
|
||
return FALSE;
|
||
|
||
OW_WriteByte(SKIP_ROM);
|
||
OW_WriteByte(READ_SCRATCHPAD);
|
||
|
||
for(i=0; i < sizeof(M601_SCRATCHPAD_READ); i++)
|
||
{
|
||
*scr++ = OW_ReadByte();
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 写芯片寄存器的暂存器组
|
||
* @param scr:字节数组指针, 长度为 @sizeof(M601_SCRATCHPAD_WRITE)
|
||
* @retval 写状态
|
||
**/
|
||
BOOL M601_WriteScratchpad_SkipRom(ubyte *scr)
|
||
{
|
||
int i;
|
||
|
||
if(OW_ResetPresence() == FALSE)
|
||
return FALSE;
|
||
|
||
OW_WriteByte(SKIP_ROM);
|
||
OW_WriteByte(WRITE_SCRATCHPAD);
|
||
|
||
for(i=0; i < sizeof(M601_SCRATCHPAD_WRITE); i++)
|
||
{
|
||
OW_WriteByte(*scr++);
|
||
}
|
||
|
||
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(ubyte mps, ubyte repeatability)
|
||
{
|
||
ubyte scrb[sizeof(M601_SCRATCHPAD_READ)];
|
||
M601_SCRATCHPAD_READ *scr = (M601_SCRATCHPAD_READ *) scrb;
|
||
|
||
/*读9个字节。第7字节是系统配置寄存器,第8字节是系统状态寄存器。最后字节是前8个的校验和--CRC。*/
|
||
if(M601_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;
|
||
|
||
M601_WriteScratchpad_SkipRom(scrb+4);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 把16位二进制补码表示的温度输出转换为以摄氏度为单位的温度读数
|
||
* @param out:有符号的16位二进制温度输出
|
||
* @retval 以摄氏度为单位的浮点温度
|
||
*/
|
||
float M601_OutputtoTemp(int out)
|
||
{
|
||
|
||
|
||
|
||
return ((float)(out/256.0) + 40.0);
|
||
}
|
||
|
||
/**
|
||
* @brief 启动温度测量
|
||
* @param 无
|
||
* @retval 单总线发送状态
|
||
*/
|
||
BOOL ConvertTemp(void)
|
||
{
|
||
if(OW_ResetPresence() == FALSE)
|
||
return FALSE;
|
||
|
||
OW_WriteByte(SKIP_ROM);
|
||
OW_WriteByte(CONVERT_T);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 等待转换结束后读测量结果。和@ConvertTemp联合使用
|
||
* @param iTemp:返回的16位温度测量结果
|
||
* @retval 读状态
|
||
*/
|
||
//BOOL ReadTempWaiting(uword *iTemp)
|
||
//{
|
||
// ubyte scrb[sizeof(M601_SCRATCHPAD_READ)];
|
||
// M601_SCRATCHPAD_READ *scr = (M601_SCRATCHPAD_READ *) scrb;
|
||
|
||
// /*读9个字节。前两个是温度转换结果,最后字节是前8个的校验和--CRC。*/
|
||
// if(M601_ReadScratchpad_SkipRom(scrb) == FALSE)
|
||
// {
|
||
// UnSwSample_1.bit_data.temperature[1] = 1;
|
||
// return FALSE; /*读寄存器失败*/
|
||
// }
|
||
|
||
// /*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
|
||
// UnSwSample_1.bit_data.temperature[1] = scrb[8];
|
||
// if(scrb[8] != MY_OW_CRC8(scrb, 8))
|
||
// {
|
||
|
||
// return FALSE; /*CRC验证未通过*/
|
||
// }
|
||
//// UnSwSample_1.bit_data.temperature[1] = *iTemp;
|
||
// /*将温度测量结果的两个字节合成为16位字。*/
|
||
// *iTemp = ((uword)(scr->T_msb) << 8) | scr->T_lsb;
|
||
//
|
||
// return TRUE;
|
||
//}
|
||
|
||
|
||
|
||
/**
|
||
* @brief 启动温度测量并读温
|
||
* @param 无
|
||
* @retval 状态
|
||
*/
|
||
|
||
//BOOL GetTemp(void)
|
||
//{
|
||
// static uword intTemp = 0;//定义为静态变量,否则会出现值自己变化
|
||
// float fTemp;
|
||
// int signedInt_f_tem = 0;
|
||
////---------------------------------------
|
||
// intTemp = 0;
|
||
// if(ConvertTemp() == FALSE) return FALSE;
|
||
// Delay_us(6000);
|
||
// ReadTempWaiting(&intTemp);
|
||
|
||
// signedInt_f_tem = (int)intTemp;
|
||
//
|
||
// fTemp = ( (float)(signedInt_f_tem)/256.0 ) + 40.0;
|
||
//
|
||
//
|
||
//// fTemp = M601_OutputtoTemp(signedInt_f_tem);
|
||
//// 将浮点数转换为有符号整型
|
||
// signedInt_f_tem = (int)(fTemp*10);
|
||
//// 温度 有符号整型转成无符号整形
|
||
// UnSwSample_1.bit_data.temperature[0] = signedInt_f_tem;
|
||
// return TRUE;
|
||
//}
|
||
/**-----------------------------------------------------------------------
|
||
* @brief 主机从芯片读取两个bit(读取顺序:低位->高位)
|
||
* @param 无
|
||
* @retval 读取到的两个bit数据
|
||
-------------------------------------------------------------------------*/
|
||
unsigned char OW_Read2Bits(void)
|
||
{
|
||
unsigned char i, dq, owdata;
|
||
owdata = 0;
|
||
|
||
for (i = 0; i < 2; i++)
|
||
{
|
||
dq = read_bit();
|
||
owdata = (owdata) | (dq << i);
|
||
}
|
||
return owdata;
|
||
}
|
||
|
||
|
||
// 搜索算法
|
||
/**
|
||
* @brief 搜索总线上接入的所有芯片的ROM ID
|
||
* @param 存有ROM ID的二维数组
|
||
* @retval 搜索到的M601的个数
|
||
*/
|
||
int Search_ROM(unsigned char(*romID)[8])
|
||
{
|
||
unsigned char k, l = 0, ConflictBit, m, n;
|
||
unsigned char BUFFER[MAXNUM]={0};
|
||
unsigned char ss[64];
|
||
unsigned char s = 0;
|
||
int num = 0;
|
||
do
|
||
{
|
||
if (OW_ResetPresence() == 0)//检查总线上从机是否存在
|
||
{
|
||
return 0;
|
||
}
|
||
OW_WriteByte(0xF0);//搜索 ROM 序列号指令
|
||
for (m = 0; m < 8; m++)
|
||
{
|
||
for (n = 0; n < 8; n++)
|
||
{
|
||
k = OW_Read2Bits(); //主机从 DQ 总线上读两位数据
|
||
k = k & 0x03;
|
||
s = s >> 1;
|
||
|
||
if (k == 0x02)
|
||
{ //此时读到总线上当前数据位为 0
|
||
write_bit(0); //主机写 0, 使总线上数据位为 0 的设备响应
|
||
ss[(m * 8 + n)] = 0;
|
||
}
|
||
else if (k == 0x01)
|
||
{ //此时读到总线上当前数据位为 1
|
||
s = s | 0x80;
|
||
write_bit(1); //主机写 1, 使总线上数据位为 1 的设备响应
|
||
ss[(m * 8 + n)] = 1;
|
||
}
|
||
else if (k == 0x00)
|
||
{//如果读到 00, 则此位数据有冲突,需选择
|
||
ConflictBit = m * 8 + n + 1;
|
||
if (ConflictBit > BUFFER[l])
|
||
{ //凡遇到新的差异位,选择 0
|
||
write_bit(0);
|
||
ss[(m * 8 + n)] = 0;
|
||
BUFFER[++l] = ConflictBit;
|
||
}
|
||
else if (ConflictBit < BUFFER[l])
|
||
{//凡上次遍历时最后一个走 0 的差异位之前的差异位仍按上次遍历的老路走
|
||
s = s | ((ss[(m * 8 + n)] & 0x01) << 7);
|
||
write_bit(ss[(m * 8 + n)]);
|
||
}
|
||
else if (ConflictBit == BUFFER[l])
|
||
{ //凡上次遍历时最后一个走 0 的差异位本次应走 1
|
||
s = s | 0x80;
|
||
write_bit(1);
|
||
ss[(m * 8 + n)] = 1;
|
||
l = l - 1;
|
||
}
|
||
}
|
||
else
|
||
{ //如果读到 11,说明总线上不存在设备
|
||
return num; //搜索完成
|
||
}
|
||
}
|
||
romID[num][m] = s;
|
||
s = 0;
|
||
}
|
||
num = num + 1;
|
||
} while (BUFFER[l] != 0 && (num < MAXNUM));
|
||
return num; //返回搜索到的 M601 个数
|
||
}
|
||
|
||
/**
|
||
* @brief 读芯片寄存器的暂存器组
|
||
* @param scr:字节数组指针, 长度为 @sizeof(M601_SCRATCHPAD_READ)
|
||
* @param j :search到的芯片的序号,如总线上只有一颗芯片,j赋值0
|
||
* @retval 读状态
|
||
*/
|
||
BOOL M601_ReadScratchpad(unsigned char* scr, unsigned char j)
|
||
{
|
||
unsigned char i, k;
|
||
|
||
/*size < sizeof(M601_SCRATCHPAD_READ)*/
|
||
if (OW_ResetPresence() == FALSE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
//#ifdef SingleIC
|
||
// OW_WriteByte(SKIP_ROM);
|
||
|
||
//#else
|
||
OW_WriteByte(MATCH_ROM);
|
||
for (k = 0; k < 8; k++)
|
||
{
|
||
OW_WriteByte(romid[j][k]);
|
||
}
|
||
//#endif
|
||
OW_WriteByte(READ_SCRATCHPAD);
|
||
|
||
for (i = 0; i < sizeof(M601_SCRATCHPAD_READ); i++)
|
||
{
|
||
*scr++ = OW_ReadByte();
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief 等待转换结束后读测量结果。和@ConvertTemp联合使用
|
||
* @param iTemp:返回的16位温度测量结果
|
||
* @param j :search到的芯片的序号,如总线上只有一颗芯片,j赋值0
|
||
* @retval 读状态
|
||
*/
|
||
BOOL ReadTempWaiting(unsigned short* iTemp, unsigned char j)
|
||
{
|
||
unsigned char scrb[sizeof(M601_SCRATCHPAD_READ)];
|
||
M601_SCRATCHPAD_READ* scr = (M601_SCRATCHPAD_READ*)scrb;
|
||
|
||
/*读9个字节。前两个是温度转换结果,最后字节是前8个的校验和--CRC。*/
|
||
if (M601_ReadScratchpad(scrb, j) == 0)
|
||
{
|
||
return FALSE; /*读寄存器失败*/
|
||
}
|
||
|
||
/*计算接收的前8个字节的校验和,并与接收的第9个CRC字节比较。*/
|
||
if (scrb[8] != MY_OW_CRC8(scrb, 8))
|
||
{
|
||
return FALSE; /*CRC验证未通过*/
|
||
}
|
||
|
||
/*将温度测量结果的两个字节合成为16位字。*/
|
||
*iTemp = (unsigned short)scr->T_msb << 8 | scr->T_lsb;
|
||
|
||
return TRUE;
|
||
}
|
||
/**
|
||
* @brief 测温读温
|
||
* @param 无
|
||
* @retval 状态
|
||
*/
|
||
BOOL GetTemp(void)
|
||
{
|
||
float fTemp;
|
||
static unsigned int iTemp[MAXNUM];
|
||
int i;
|
||
int signedInt_f_tem = 0;
|
||
//----------------------------------------------------
|
||
// memset(romid, 0, sizeof(romid));//清零
|
||
|
||
/*总线上所有芯片一起测温*/
|
||
if(ConvertTemp() == FALSE) return FALSE;
|
||
Delay_us(6500);
|
||
|
||
|
||
for (i = 0; i < RomNum; i++) //遍历所有芯片
|
||
{
|
||
iTemp[i] = 0;
|
||
/*读温*/
|
||
ReadTempWaiting(&iTemp[i], i);
|
||
|
||
fTemp = M601_OutputtoTemp((int)iTemp[i]); //温度输出的浮点数
|
||
|
||
// 将浮点数转换为有符号整型
|
||
signedInt_f_tem = (int)(fTemp*10);
|
||
// 温度 有符号整型转成无符号整形
|
||
UnSwSample_1.bit_data.temperature[i] = (unsigned int)signedInt_f_tem;
|
||
}
|
||
return TRUE;
|
||
}
|