Files
acquisition_module/temperature.C

519 lines
13 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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字节数组指针 长度为 @sizeofM601_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字节数组指针 长度为 @sizeofM601_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字节数组指针 长度为 @sizeofM601_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[1] = (unsigned int)signedInt_f_tem;
}
return TRUE;
}