接https://blog.csdn.net/pxy198831/article/details/98038695,
MAX31826是一款单总线的温度传感器,带有1K EEPROM驱动如下:
/******************************************************************************
* 文 件 名 称:BspMAX31826.c
* 文件功能概述:实现MAX31826接口声明
* 文 件 作 者:xxx
* 版 本:V1.0.0.0
* 修 订 记 录:2017-6-30创建
2019-2-14修订 潘星宇 添加搜索ROM ID功能
******************************************************************************/
#include "BspMAX31826.h"
#include "PeripheralPollTask.h" //之所以#include "PeripheralPollTask.h"不放在头文件是因为该头文件调用了"BspMAX31826.h"的一个枚举定义
//如果放在"BspMAX31826.h"中也要放到该枚举定义的后面
#define MAX31826DelayUs(x) DelayUs(x)
typedef struct
{
uint8 IdCode[8];
}S_Max31826IdCode;
S_Max31826IdCode stMax31826IdCode[E_MAX31826_Max]=
{
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
};
static E_OWx stMax31826Ow[E_MAX31826_Max] = {E_OW_1,E_OW_DYDY,E_OW_GYDY,E_OW_MB,E_OW_BB};
//全局搜索变量
static uint8 stROM_NO[8]; //数组,存放本次搜索到的ROM码(8个字节)
static uint8 LastDiscrepancy; //每轮搜索后指向最后一个走0的差异位
static uint8 LastFamilyDiscrepancy; //指向家族码(前8位)中最后一个走0的差异位
static uint8 LastDeviceFlag; //搜到最后一个ROM后,程序通过判别将该变量置TRUE,下轮搜索时即会结束退出
//uint8 crc8_status; //CRC校验结果
uint8 OWSearch(E_MAX31826 eMax31826);
uint8 OWFirst(E_MAX31826 eMax31826);
uint8 OWNext(E_MAX31826 eMax31826);
uint8 OWVerify(E_MAX31826 eMax31826);
void MAX31826_GPIO_Init(void)
{
GPIO_InitTypeDef s_GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOI , ENABLE);/* 使能GPIOB&GPIOC&GPIOD时钟*/
s_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3;
s_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
s_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOA, &s_GPIO_InitStructure);
s_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
s_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
s_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOI, &s_GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名:static void MAX31826DelayUs(uint16 Us)
* 参 数:uint16 Us : 延时单位
* 返 回:无
* 创 建 人:xxx
* 创建时间:2017-6-30
* 详 述:MAX31826使用的延时函数
* 修改记录:2017-6-30创建
*******************************************************************************/
//static void MAX31826DelayUs(uint16 Us)
//{
// uint16 i=0,j=0;
//
// for(j=0; j<Us; j++)
// {
// for(i=0; i<21; i++)
// {
// }
// }
//
//}
/*******************************************************************************
* 函 数 名:static sint8 MAX31826ReadRom(uint8 *pdata)
* 参 数:E_MAX31826 eMax31826: 选择对应的器件
* uint8 *pdata: 存储序列码的数据地址
* 返 回:0 成功
* -1 失败
* 创 建 人:xxx
* 创建时间:2017-6-30
* 详 述:获取max31826的max31826的序列码
* 修改记录:2017-6-30创建
*******************************************************************************/
static sint8 MAX31826ReadRom(E_MAX31826 eMax31826, uint8 *pdata)
{
uint8 data[8]={0, 0, 0, 0, 0, 0, 0, 0};
if(OneWireReset(stMax31826Ow[eMax31826]) == 0)
{
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_READ_ROM);
data[0] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[1] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[2] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[3] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[4] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[5] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[6] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[7] = OneWireReadByte(stMax31826Ow[eMax31826]);
if(data[7] == crc8(data,7))
{
if(data[0] == MAX31826_FAMILYCODE)
{
memcpy(pdata, data, 8);
return 0;
}
else
{
return -1;
}
}
else
{
return -1;
}
}
return -1;
}
/*******************************************************************************
* 函 数 名:static sint8 MAX31826SerchRom(uint8 *pdata)
* 参 数:E_MAX31826 eMax31826: 选择对应的器件
* uint8 *pdata: 存储序列码的数据地址
* 返 回:0 成功
* -1 失败
* 创 建 人:潘星宇
* 创建时间:2019-2-13
* 详 述:搜索max31826的ROM序列码
* 修改记录:2019-2-13创建
*******************************************************************************/
static sint8 MAX31826SerchRom(E_MAX31826 eMax31826, uint8 *pdata)
{
uint8 data[8]={0, 0, 0, 0, 0, 0, 0, 0};
uint8 i;
if(OneWireReset(stMax31826Ow[eMax31826]) == 0)
{
//目前单总线仅挂接至多2个1-WIRE设备,先不用FOR循环
if((eMax31826 == E_MAX31826_DYDY) || (eMax31826 == E_MAX31826_MB))
{
//每根总线第一次查询,第一次查询到的ID号和第二次查询到的器件不一定在条件中的板件位置,因为二叉路径选择具有随机性
if((TRUE == OWFirst((E_MAX31826)stMax31826Ow[eMax31826])) &&
(TRUE == OWVerify((E_MAX31826)stMax31826Ow[eMax31826])))
{
for(i = 0; i < 8; i++)
{
data[i] = stROM_NO[i];
}
}
else
{
return -1;
}
}
else
{
//每根总线第二次查询
if((TRUE == OWNext((E_MAX31826)stMax31826Ow[eMax31826])) &&
(TRUE == OWVerify((E_MAX31826)stMax31826Ow[eMax31826])))
{
for(i = 0; i < 8; i++)
{
data[i] = stROM_NO[i];
}
}
else
{
return -1;
}
}
//两次查询到ROM ID号之后要进行CRC校验
if(data[7] == crc8(data,7))
{
if(data[0] == MAX31826_FAMILYCODE)
{
memcpy(pdata, data, 8);
}
else
{
return -1;
}
}
else
{
return -1;
}
}
else
{
}
return -1;
}
/*******************************************************************************
* 函 数 名:static sint8 MAX31826SerchRom(uint8 *pdata)
* 参 数:E_MAX31826 eMax31826: 选择对应的器件
* 返 回:0 成功
* -1 失败
* 创 建 人:潘星宇
* 创建时间:2019-2-14
* 详 述:匹配max31826的ROM序列码
* 修改记录:2019-2-14创建
*******************************************************************************/
sint8 MAX31826MatchROM(E_MAX31826 eMax31826)
{
uint8_t i,j;
uint8 data[9]={0};
uint8 address = 0xff;
for(i = 0; i<E_MAX31826_Max ; i++)
{
//复位
if(OneWireReset(stMax31826Ow[eMax31826]) == 0)
{
//发送ROM匹配命令
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_MATCH_ROM);
//发送64位ROM地址
for(j = 0; j < 8; j++)
{
OneWireWriteByte(stMax31826Ow[eMax31826],stMax31826IdCode[stMax31826Ow[eMax31826]].IdCode[j]);
}
//发送ROM读取SCRATCHPAD1命令
OneWireWriteByte(stMax31826Ow[eMax31826],CMD_READ_SCRATCHPAD1);
//读取SCRATCHPAD1内容
for(j = 0; j < 9; j++)
{
data[j] = OneWireReadByte(stMax31826Ow[eMax31826]);
}
//校验
if(data[8] == crc8(data,8))
{
address = data[4] & 0x0f;//地址只有低四位有效
}
else
{
return -1;
}
//开始匹配
if((eMax31826 == E_MAX31826_DYDY) || (eMax31826 == E_MAX31826_GYDY))
{
if(address == E_MAX31826_DYDY_ADDRESS)
{
memcpy(&g_s_PeriPollInfo[E_MAX31826_DYDY].u8_RomId[0],&stMax31826IdCode[eMax31826],8);
}
else if(address == E_MAX31826_GYDY_ADDRESS)
{
memcpy(&g_s_PeriPollInfo[E_MAX31826_GYDY].u8_RomId[0],&stMax31826IdCode[eMax31826],8);
}
else
{
}
}
else
{
if(address == E_MAX31826_MB_ADDRESS)
{
memcpy(&g_s_PeriPollInfo[E_MAX31826_MB].u8_RomId[0],&stMax31826IdCode[eMax31826],8);
}
else if(address == E_MAX31826_BB_ADDRESS)
{
memcpy(&g_s_PeriPollInfo[E_MAX31826_BB].u8_RomId[0],&stMax31826IdCode[eMax31826],8);
}
else
{
}
}
}
else
{
return -1;
}
}
if(eMax31826 == E_MAX31826_BB)
{
for(eMax31826 = E_MAX31826_DYDY; eMax31826 < E_MAX31826_Max; eMax31826++)
{
memcpy(&stMax31826IdCode[eMax31826],&g_s_PeriPollInfo[eMax31826].u8_RomId[0],8);
}
}
else
{
}
return 0;
}
/*******************************************************************************
* 函 数 名:sint8 MAX31826Init(E_MAX31826 eMax31826)
* 参 数:无
* 返 回:0 成功
* -1 失败
* 创 建 人:xxx
* 创建时间:2017-6-30
* 详 述:MAX31826进行初始化
* 修改记录:2019-2-14修改 PXY
*******************************************************************************/
sint8 MAX31826Init(E_MAX31826 eMax31826)
{
if(OneWireInit(stMax31826Ow[eMax31826]) == -1)
{
return -1;
}
else
{
}
if(eMax31826 == E_MAX31826_1)
{
// if(MAX31826SerchRom(eMax31826,(uint8 *)&stMax31826IdCode[eMax31826]) == -1)
// {
// return -1;
// }
// else
// {
// memcpy((uint8 *)&g_s_PeriPollInfo[E_MAX31826_1].u8_RomId[0],stROM_NO,sizeof(g_s_PeriPollInfo));
// }
if(MAX31826ReadRom(eMax31826,(uint8 *)&stMax31826IdCode[eMax31826]) == -1)
{
return -1;
}
else
{
memcpy(&g_s_PeriPollInfo[E_MAX31826_1].u8_RomId[0],&stMax31826IdCode[E_MAX31826_1],8);
}
}
else
{
if(MAX31826SerchRom(eMax31826,(uint8 *)&stMax31826IdCode[eMax31826]) == -1)
{
return -1;
}
else
{
}
}
return 0;
}
/*******************************************************************************
* 函 数 名:void MAX31826GetRomCode(uint8 *pdata)
* 参 数:uint8 *pdata : 存储序列码的数据地址
* 返 回:无
* 创 建 人:xxx
* 创建时间:2017-6-30
* 详 述:返回MAX31826的序列码,在初始化函数成功之后调用
* 修改记录:2017-6-30创建
*******************************************************************************/
void MAX31826GetRomCode(E_MAX31826 eMax31826,uint8 *pdata)
{
if(MAX31826ReadRom(eMax31826,pdata) == -1)
{
memcpy(pdata, (uint8 *)&stMax31826IdCode[eMax31826], sizeof(S_Max31826IdCode));
}
else
{
memcpy((uint8 *)&stMax31826IdCode[eMax31826], pdata, sizeof(S_Max31826IdCode));
}
}
/*******************************************************************************
* 函 数 名:sint8 MAX31826StartConvert(void)
* 参 数:无
* 返 回:-1 :发生超时错误 0 :正常执行
* 创 建 人:xxx
* 创建时间:2017-6-30
* 详 述:向max31826发送温度转换命令并等待转换结束
* 修改记录:2017-6-30创建
*******************************************************************************/
sint8 MAX31826StartConvert(E_MAX31826 eMax31826)
{
uint8 i = 0;
if(OneWireReset(stMax31826Ow[eMax31826]) == 0)
{
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_SKIP_ROM);
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_CONVERT);
MAX31826DelayUs(1);
while(OneWireReadByte(stMax31826Ow[eMax31826])==0x00)
{
i++; //通常在i约等于180时完成转换
if(i>=0xfe)
{
return -1;
}
}
}
else
{
return -1;
}
return 0;
}
/*******************************************************************************
* 函 数 名:sint8 MAX31826ReadTemperature(E_MAX31826 eMax31826,float *pData)
* 参 数:E_MAX31826 eMax31826:选择不同的总线
* float *pData:数据
* 返 回:-1 :发生错误 非-1 :转换得到的温度值
* 创 建 人:xxx
* 创建时间:2017-6-30
* 详 述:从max31826读取温度值
* 修改记录:2019-2-11修改 潘星宇
*******************************************************************************/
sint8 MAX31826ReadTemperature(E_MAX31826 eMax31826, float *pData)
{
uint8 data[11] = {0};
uint8 flag = 0;
uint16 temp = 0;
uint8 i;
float temp_f = 0.0f;
if(OneWireReset(stMax31826Ow[eMax31826]) == 0)
{
if(eMax31826 == E_MAX31826_1)
{
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_SKIP_ROM);
}
else
{
//发送ROM匹配命令
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_MATCH_ROM);
//发送64位ROM地址
for(i = 0; i< 8; i++)
{
OneWireWriteByte(stMax31826Ow[eMax31826],stMax31826IdCode[stMax31826Ow[eMax31826]].IdCode[i]);
}
}
//发送ROM读取SCRATCHPAD1命令
OneWireWriteByte(stMax31826Ow[eMax31826],CMD_READ_SCRATCHPAD1);
data[0] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[1] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[2] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[3] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[4] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[5] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[6] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[7] = OneWireReadByte(stMax31826Ow[eMax31826]);
data[8] = OneWireReadByte(stMax31826Ow[eMax31826]);
if(data[8] != crc8(data,8))
{
return -1;
}
if(data[1] & 0x80)
{
flag = 1;
}
else
{}
data[1] &= 0x07;
temp = data[1];
temp = temp << 8;
temp = temp | data[0];
temp &= 0x03ff;
temp_f = (float)(temp) * (float)MAX31826_RATIO;
if(flag == 1)
{
temp_f = (float)0.0 - temp_f;
}
*pData = temp_f;
return 0;
}
else
{
return -1;
}
}
/**********************************************************************/
static uint8 MAX3182x_opt_Scratchpad2(E_MAX31826 eMax31826,uint8 nAddr, const uint8 *pBuf)
{
uint8 nIndex;
uint8 i;
/** 写Scratchpad */
if(OneWireReset(stMax31826Ow[eMax31826]) != 0)
{
if(OneWireReset(stMax31826Ow[eMax31826]) != 0)
{
return (uint8)FALSE;
}
else
{
}
}
else
{
if(eMax31826 == E_MAX31826_1)
{
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_SKIP_ROM);
}
else
{
//发送ROM匹配命令
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_MATCH_ROM);
//发送64位ROM地址
for(i = 0; i< 8; i++)
{
OneWireWriteByte(stMax31826Ow[eMax31826],stMax31826IdCode[stMax31826Ow[eMax31826]].IdCode[i]);
}
}
OneWireWriteByte(stMax31826Ow[eMax31826],CMD_WRITE_SCRATCHPAD2);
OneWireWriteByte(stMax31826Ow[eMax31826],nAddr); /** 地址 */
for(nIndex = 0; nIndex < 8; nIndex++)
{
OneWireWriteByte(stMax31826Ow[eMax31826],pBuf[nIndex]);
}
}
/** Copy Scratchpad(Write EEPROM) */
if(OneWireReset(stMax31826Ow[eMax31826]) != 0)
{
return (uint8)FALSE;
}
else
{
if(eMax31826 == E_MAX31826_1)
{
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_SKIP_ROM);
}
else
{
//发送ROM匹配命令
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_MATCH_ROM);
//发送64位ROM地址
for(i = 0; i< 8; i++)
{
OneWireWriteByte(stMax31826Ow[eMax31826],stMax31826IdCode[stMax31826Ow[eMax31826]].IdCode[i]);
}
}
OneWireWriteByte(stMax31826Ow[eMax31826],CMD_COPY_SCRATCHPAD2); /** 0x55 */
OneWireWriteByte(stMax31826Ow[eMax31826],CMD_WRITE_EEPROM); /** 0xA5 */
}
OneWireTakeBus(stMax31826Ow[eMax31826]);
DelayUs(20000);
OneWireRealseBus(stMax31826Ow[eMax31826]);
return (uint8)TRUE;
}
/***********************************************************************************************
功 能:向MAX31826 EEPROM写数据
参 数:eMax31826 选择对应的芯片
nTempNum - 第n路温度传感器(n = 0、1、2)
nAddr - 写入MAX3182x的EEPROM的偏移地址(注:因为写一次EEPROM操作为
8个字节,所以此处地址应为8的整数倍,如0、8、16等,最大120)
*pBuf - 写入MAX3182x的EEPROM的数据缓冲区
nLen - 写入MAX3182x的EEPROM的数据长度
返 回:
TRUE 成功
FALSE 失败
***********************************************************************************************/
uint8 MAX3182x_Write_EEPROM(E_MAX31826 eMax31826,uint8 nAddr, uint8 *pBuf, uint8 nLen)
{
uint8 nIndex;
uint8 retVal = 0;
uint8 l_u8_startAddr = 0;
uint8 l_u8_IntVal = 0;
uint8 l_u8_RemainVal = 0;
uint8 l_u8_TempArr[8U];
if(((nAddr & 0x07U) != 0) || ((nAddr + nLen) > MAX31826_EEPROM_Size))
{
return (uint8)FALSE;
}
else
{
/** nothing */
}
/** 对写入长度进行处理 */
l_u8_startAddr = nAddr;
l_u8_IntVal = (uint8)(nLen >> 3U);
l_u8_RemainVal = (uint8)(nLen & 0x07);
if(l_u8_RemainVal != 0)
{
MAX3182x_Read_EEPROM(eMax31826,(l_u8_IntVal<<3U),l_u8_TempArr,8);
memcpy(l_u8_TempArr,(pBuf+(l_u8_IntVal<<3U)),l_u8_RemainVal);
}
if(l_u8_IntVal > 0)
{
for(nIndex = 0; nIndex < l_u8_IntVal; nIndex++)
{
retVal = MAX3182x_opt_Scratchpad2(eMax31826,(uint8)(l_u8_startAddr + (uint8)(nIndex * 8U)), &pBuf[(uint8)(nIndex * 8U)]);
if(retVal == 0)
{
return (uint8)FALSE;
}
else
{
/** nothing */
}
}
}
else
{
/** nothing */
}
l_u8_startAddr = (uint8)(l_u8_IntVal * 8U);
pBuf = pBuf + (uint8)(l_u8_IntVal * 8U);
if(l_u8_RemainVal != 0)
{
retVal = MAX3182x_opt_Scratchpad2(eMax31826,l_u8_startAddr, l_u8_TempArr);
if(retVal == 0)
{
return (uint8)FALSE;
}
else
{
/** nothing */
}
}
else
{
/** nothing */
}
return (uint8)TRUE;
}
/***********************************************************************************************
功 能:从MAX31826 EEPROM读出数据
参 数:nTempNum - 第n路温度传感器(n = 0、1、2)
nAddr - 读数据的首字节地址
*pBuf - 读出MAX3182x的EEPROM的数据缓冲区
nLen - 从MAX3182x的EEPROM的读出数据的长度
返 回:
TRUE 成功
FALSE 失败
***********************************************************************************************/
uint8 MAX3182x_Read_EEPROM(E_MAX31826 eMax31826,uint8 nAddr, uint8 *pBuf, uint8 nLen)
{
uint8 nIndex;
uint8 i;
if(OneWireReset(stMax31826Ow[eMax31826]) != 0)
{
return (uint8)FALSE;
}
else
{
if(eMax31826 == E_MAX31826_1)
{
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_SKIP_ROM);
}
else
{
//发送ROM匹配命令
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_MATCH_ROM);
//发送64位ROM地址
for(i = 0; i< 8; i++)
{
OneWireWriteByte(stMax31826Ow[eMax31826],stMax31826IdCode[stMax31826Ow[eMax31826]].IdCode[i]);
}
}
OneWireWriteByte(stMax31826Ow[eMax31826],CMD_READ_EEPROM);
OneWireWriteByte(stMax31826Ow[eMax31826],nAddr);
for(nIndex = 0; nIndex < nLen; nIndex++)
{
pBuf[nIndex] = OneWireReadByte(stMax31826Ow[eMax31826]);
}
}
return (uint8)TRUE;
}
static uint8 st_u8_hardinfo_update = 0U;
sint8 MAX3182x_Write_HardwareInfo(E_MAX31826 eMax31826, uint8 *p_u8_id, uint8 *p_u8_version)
{
S_HardwareInfo sHardwareInfo;
memcpy(&sHardwareInfo.u8_HardwareId,p_u8_id,sizeof(sHardwareInfo.u8_HardwareId));
memcpy(&sHardwareInfo.u8_HardwareVersion,p_u8_version,sizeof(sHardwareInfo.u8_HardwareVersion));
sHardwareInfo.u32_crc = CrcCalWithInit(0XFFFFFFFF,(uint8 *)&sHardwareInfo,sizeof(sHardwareInfo)-sizeof(sHardwareInfo.u32_crc));
st_u8_hardinfo_update = 0U;
if(TRUE==MAX3182x_Write_EEPROM(eMax31826,0x00,(uint8 *)&sHardwareInfo,sizeof(sHardwareInfo)))
{
return 0;
}
else
{
return -1;
}
}
sint8 MAX3182x_Read_HardwareInfo(E_MAX31826 eMax31826, uint8 *p_u8_id, uint8 *p_u8_version)
{
S_HardwareInfo sHardwareInfo;
memset(&sHardwareInfo,0,sizeof(sHardwareInfo));
// if(0U == st_u8_hardinfo_update)
// {
MAX3182x_Read_EEPROM(eMax31826,0x00,(uint8 *)&sHardwareInfo,sizeof(sHardwareInfo));
if(sHardwareInfo.u32_crc == CrcCalWithInit(0XFFFFFFFF,(uint8 *)&sHardwareInfo,sizeof(sHardwareInfo)-sizeof(sHardwareInfo.u32_crc)))
{
// st_u8_hardinfo_update = 1U;
// memcpy(p_u8_id,&sHardwareInfo.u8_HardwareId,sizeof(sHardwareInfo.u8_HardwareId));
memcpy(p_u8_version,&sHardwareInfo.u8_HardwareVersion,sizeof(sHardwareInfo.u8_HardwareVersion));
return 0;
}
else
{
return -1;
}
// }
// else
// {
// return 0;
// }
}
/*以下函数用于遍历寻找单总线挂接多个1-WIRE器件时的ROM ID号*/
/***********************************************************************************************
*功 能:调用OWSearch完成第一次搜索
*参 数:E_MAX31826 eMax31826:选择不同的总线
*返 回:TRUE 找到,存入stROM_NO缓冲
* FALSE 无设备
*创 建 人:潘星宇
*创建时间:2019-2-11
***********************************************************************************************/
uint8 OWFirst(E_MAX31826 eMax31826)
{
//先将初始化3个变量,然后调用OWSearch算法进行搜索
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return OWSearch(eMax31826);
}
/***********************************************************************************************
*功 能:在单总线上搜索下一个器件
*参 数:E_MAX31826 eMax31826:选择不同的总线
*返 回:TRUE 找到,存入stROM_NO缓冲
* FALSE 无设备,结束搜索
*创 建 人:潘星宇
*创建时间:2019-2-11
***********************************************************************************************/
uint8 OWNext(E_MAX31826 eMax31826)
{
//在前一轮搜索的基础上(3个变量均在前一轮搜索中有明确的值),再执行一轮搜索
return OWSearch(eMax31826);
}
/***********************************************************************************************
*功 能:单总线搜索算法,利用了一些状态变量,这是算法的核心程序,代码也较长
* 算法详解可自行搜索“1-WIRE ROM搜索算法”详解,就是个二叉树法搜索
*参 数:E_MAX31826 eMax31826:选择不同的总线
*返 回:TRUE: 找到,存入stROM_NO缓冲
* FALSE:无设备或CRC校验失败,结束搜索
*创 建 人:潘星宇
*创建时间:2019-2-11
***********************************************************************************************/
uint8 OWSearch(E_MAX31826 eMax31826)
{
uint8 id_bit_number = 1; //指示当前搜索ROM位(取值范围为1-64)
uint8 last_zero = 0; //记录一次搜索(ROM1-64位)最后一位往0走的混码点编号
uint8 rom_byte_number = 0; //ROM字节序号,作为stROM_NO[]数组的下标,取值为1—8
uint8 search_result = FALSE; //搜索结果,函数返回值
uint8 id_bit = 0; //“二读”的第一次读,从机回应正码
uint8 cmp_id_bit = 0; //“二读”的第二次读,从机回应补码
uint8 search_direction = 0; //“一写”,当遇到分叉时,选择方向(走0或1)
uint8 rom_byte_mask = 1; //ROM字节掩码
// crc8_status = FALSE;
//是否搜索完成(已到最后一个设备)
//LastDeviceFlag由上轮搜索确定是否为最后器件,当然首次进入前必须置False
if(LastDeviceFlag == FALSE)
{
//复位总线
if(OneWireReset(stMax31826Ow[eMax31826]) == -1)
{
//复位几个搜索变量
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return FALSE; //如果无应答,返回FALSE,退出本轮搜索程序
}
else
{
}
//发送ROM搜索命令F0H
OneWireWriteByte(stMax31826Ow[eMax31826],MAX31826_SERCH_ROM);
// OneWireDelayUs(200);
/*
* 开始循环处理1-64位ROM,每位必须进行“二读”后进行判断,确定搜索路径
* 然后按选定的路径进行“一写”,直至完成全部位的搜索,这样一次循环
* 可以完成一轮搜索,找到其中一个ROM码。
*/
//逐位读写搜索,1-64位循环
do
{
id_bit = OneWireReadBit((E_OWx)stMax31826Ow[eMax31826]); //二读:先读正码、再读反码
cmp_id_bit = OneWireReadBit((E_OWx)stMax31826Ow[eMax31826]);
/* 正码 反码 表明情况
0 0 连接器件的该位有0有1,这是一个差异位(混码位)
0 1 连接器件的该位均为0
1 0 连接器件的该位均为1
1 1 没有器件与总线相连 */
//二读11,则无器件退出程序
if((id_bit == 1U) && (cmp_id_bit == 1U))
{
break;
}
//二读不为11,则需分二种情况
else
{
//第一种情况:01或10,直接可明确搜索方向
if (id_bit != cmp_id_bit)
{
search_direction = id_bit;//记下搜索方向search_direction的值待“一写”
}
else
{
//否则就是第二种情况:遇到了混码点(有分叉,先走0),需分三种可能分析:
//1.当前位未到达上轮搜索的“最末走0混码点”(由LastDiscrepancy存储)
// 说明当前经历的是一个老的混码点,判别特征为当前位在(小于)LastDiscrepancy前
// 不管上次走的是0还是1,只需按上次走的路即可,该值需从stROM_NO中的当前位获取
if(id_bit_number < LastDiscrepancy)
{
if((stROM_NO[rom_byte_number] & rom_byte_mask) == 0)
{
search_direction = 0;
}
else
{
search_direction = 1;
}
}
//2.当前位正好为上轮标记的最末的混码点,这个混码点也就是上次走0的点
// 那么这次就需要走1
else if(id_bit_number == LastDiscrepancy)
{
search_direction = 1;
}
//除去上二种可能,那就是第3种可能:这是一个新的混码点(先走0)
//id_bit_number>LastDiscrepancy
else
{
search_direction = 0;
}
//确定了混码点的路径方向还没完事,还需要更新一个指针:last_zero
//这个指针每搜索完一位后(注意是一bit不是一轮)总是指向新的混码点
//凡遇到新的混码点,我们按算法都是先走0,所以凡遇走0的混码点必须更新此指针
if(search_direction == 0)
{
last_zero = id_bit_number;
//下面二条是程序的高级功能了:64位ROM中的前8位是器件的家族代码,
//用LastFamilyDiscrepancy这个指针来记录前8位ROM中的最末一个混码点
//可用于在多类型器件的单线网络中对家族分组进行操作
if(last_zero < 9)
{
LastFamilyDiscrepancy = last_zero;
}
}
else
{
}
}
//确定了要搜索的方向search_direction,该值即ROM中当前位的值,需要写入ROM
//然而64位ROM需分8个字节存入stROM_NO[],程序使用了一个掩码字节rom_byte_mask
//以最低位为例:该字节值为00000001,如记录1则两个字节或,记录0则与反掩码
if (search_direction == 1)
{
stROM_NO[rom_byte_number] |= rom_byte_mask;
}
else
{
stROM_NO[rom_byte_number] &= ~rom_byte_mask;
}
//关键的一步操作终于到来了:一写,选择分叉方向
OneWireWriteBit((E_OWx)eMax31826,search_direction);
// OneWireDelayUs(100);
//一个位的操作终于完成,但还需做些工作,以准备下一位的操作:
//包括:位变量id_bit_number指向下一位;字节掩码左移一位
id_bit_number++;
rom_byte_mask <<= 1;
//如果够8位一字节了,则对该字节计算CRC处理、更新字节号变量、重设掩码
if (rom_byte_mask == 0)
{
// docrc8(ROM_NO[rom_byte_number]); // accumulate the CRC
rom_byte_number++;
rom_byte_mask = 1;
}
else
{
}
}
}
while(rom_byte_number < 8); //ROM bytes编号为 0-7
// //一轮搜索成功,进行CRC校验,校验暂放在应用层进行
// if(id_bit_number == 65)
// {
// if(stROM_NO[7] == crc8(stROM_NO,7))
// {
// crc8_status = TRUE;
// }
// else
// {
// crc8_status = FALSE;
// }
// }
// else
// {
//
// }
if(id_bit_number == 65)
{
//一轮搜索结束后,变量last_zero指向了本轮中最后一个走0的混码位
//然后再把此变量保存在LastDiscrepancy中,用于下一轮的判断
//当然,last_zero在下轮初始为0,搜索是该变量是不断变动的
LastDiscrepancy = last_zero;
//如果这个指针为0,说明全部搜索结束,再也没有新ROM号器件了
if(LastDiscrepancy == 0)
{
LastDeviceFlag = TRUE;//设置结束标志
}
else
{
LastDeviceFlag = FALSE;
}
search_result = TRUE;//返回搜索成功
}
else
{
}
}
else
{
}
//搜索完成,如果搜索不成功,复位状态变量到首次搜索的状态
if(search_result == FALSE)
{
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
search_result = FALSE;
}
else
{
}
return search_result;
}
/***********************************************************************************************
*功 能:校验获取到的ROM ID是否正确
*参 数:E_MAX31826 eMax31826:选择不同的总线
*返 回:TRUE: 当前ID号的设备存在
* FALSE:当前ID号的设备不存在
*创 建 人:潘星宇
*创建时间:2019-2-12
***********************************************************************************************/
uint8 OWVerify(E_MAX31826 eMax31826)
{
uint8 rom_backup[8];
uint8 i;
uint8 rslt;
uint8 ld_backup;
uint8 ldf_backup;
uint8 lfd_backup;
//将当前状态进行保存
for (i = 0; i < 8; i++)
{
rom_backup[i] = stROM_NO[i];
}
ld_backup = LastDiscrepancy;
ldf_backup = LastDeviceFlag;
lfd_backup = LastFamilyDiscrepancy;
//设置查找相同的器件
LastDiscrepancy = 64;
LastDeviceFlag = FALSE;
if (OWSearch(eMax31826))
{
// check if same device found
rslt = TRUE;
for (i = 0; i < 8; i++)
{
if (rom_backup[i] != stROM_NO[i])
{
rslt = FALSE;
break;
}
}
}
else
{
rslt = FALSE;
}
//重新装载当前状态
for (i = 0; i < 8; i++)
{
stROM_NO[i] = rom_backup[i];
}
LastDiscrepancy = ld_backup;
LastDeviceFlag = ldf_backup;
LastFamilyDiscrepancy = lfd_backup;
//返回校验状态
return rslt;
}
//--------------------------------------------------------------------------
// Setup the search to find the device type 'family_code' on the next call
// to OWNext() if it is present.
//高级功能,用于设置整个系列的芯片用于跳转,暂无用
void OWTargetSetup(unsigned char family_code)
{
int i;
// set the search state to find SearchFamily type devices
stROM_NO[0] = family_code;
for (i = 1; i < 8; i++)
{
stROM_NO[i] = 0;
}
LastDiscrepancy = 64;
LastFamilyDiscrepancy = 0;
LastDeviceFlag = FALSE;
}
//--------------------------------------------------------------------------
// Setup the search to skip the current device type on the next call
// to OWNext().
//高级功能,用于整个系列的芯片分支跳转,暂无用
void OWFamilySkipSetup()
{
// set the Last discrepancy to last family discrepancy
LastDiscrepancy = LastFamilyDiscrepancy;
LastFamilyDiscrepancy = 0;
// check for end of list
if (LastDiscrepancy == 0)
{
LastDeviceFlag = TRUE;
}
}
头文件如下:
/******************************************************************************
* 文 件 名 称:BspMAX31826.h
* 文件功能概述:实现MAX31826驱动接口声明
* 文 件 作 者:
* 版 本:V1.0.0.0
* 修 订 记 录:2017-6-30创建
******************************************************************************/
#ifndef __BSP_MAX31826_H__
#define __BSP_MAX31826_H__
/*----------------------------------------------*
* 包含头文件 *
*----------------------------------------------*/
#include "..\BspInterface.h"
#include "BspOneWire.h"
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
/* MAX31826 Debug*/
#define MAX31826_DEBUG
#ifdef MAX31826_DEBUG
#define MAX31826_Print printf
#else
#define MAX31826_Print(...)
#endif
#define MAX31826_FAMILYCODE 0x3B //31826系列固定代码
#define MAX31826_SERCH_ROM (uint8)0xF0 //遍历芯片的ROM ID
#define MAX31826_MATCH_ROM (uint8)0x55 //匹配对应ROM ID的芯片
#define MAX31826_READ_ROM (uint8)0x33 //读取ROM Code的命令
#define MAX31826_SKIP_ROM (uint8)0xCC //跳过读取ROM Code的命令
#define MAX31826_CONVERT (uint8)0x44 //开始温度转换的命令
#define CMD_READ_ROM (uint8)(0x33)
#define CMD_SKIP_ROM (uint8)(0xCC)
#define CMD_READ_SCRATCHPAD (uint8)(0xBE)
#define CMD_BEGINS_COVERSION (uint8)(0x44)
#define CMD_READ_SCRATCHPAD1 (uint8)(0xBE)
#define CMD_READ_SCRATCHPAD2 (uint8)(0xAA)
#define CMD_WRITE_SCRATCHPAD2 (uint8)(0x0F)
#define CMD_COPY_SCRATCHPAD2 (uint8)(0x55)
#define CMD_WRITE_EEPROM (uint8)(0xA5)
#define CMD_READ_EEPROM (uint8)(0xF0)
#define MAX31826_EEPROM_Size (128U) /** EEPROM容量,单位字节 */
#define MAX31826_RATIO (0.0625) //温度分辨率
#define E_MAX31826_DYDY_ADDRESS (uint8)(0x02)
#define E_MAX31826_GYDY_ADDRESS (uint8)(0x03)
#define E_MAX31826_MB_ADDRESS (uint8)(0x08)
#define E_MAX31826_BB_ADDRESS (uint8)(0x00)
typedef struct
{
uint8 u8_HardwareId[8];
uint8 u8_HardwareVersion[4];
uint32 u32_crc;
}S_HardwareInfo;
/*****************/
typedef enum
{
E_MAX31826_1 = 0x00,
E_MAX31826_DYDY,
E_MAX31826_GYDY,
E_MAX31826_MB,
E_MAX31826_BB,
E_MAX31826_Max,
E_MAX31826_Invalid
}E_MAX31826;
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
sint8 MAX31826Init(E_MAX31826 eMax31826);
sint8 MAX31826StartConvert(E_MAX31826 eMax31826);
sint8 MAX31826ReadTemperature(E_MAX31826 eMax31826,float *pData);
void MAX31826GetRomCode(E_MAX31826 eMax31826,uint8 *pdata);
uint8 MAX3182x_Write_EEPROM(E_MAX31826 eMax31826,uint8 nAddr, uint8 *pBuf, uint8 nLen);
uint8 MAX3182x_Read_EEPROM(E_MAX31826 eMax31826,uint8 nAddr, uint8 *pBuf, uint8 nLen);
sint8 MAX3182x_Write_HardwareInfo(E_MAX31826 eMax31826, uint8 *p_u8_id, uint8 *p_u8_version);
sint8 MAX3182x_Read_HardwareInfo(E_MAX31826 eMax31826, uint8 *p_u8_id, uint8 *p_u8_version);
sint8 MAX31826MatchROM(E_MAX31826 eMax31826);
void MAX31826_GPIO_Init(void);
#endif
以上代码包含了一个遍历64位MAX31826ID号的查找算法程序,即单总线可以挂接多片该芯片