#include "temperature.H" #include #include 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; 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[1] = (unsigned int)signedInt_f_tem; } return TRUE; }