STM32之MAX31826驱动

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号的查找算法程序,即单总线可以挂接多片该芯片

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值