构建驱动模块1--STM32F4 DS18B20温度采集驱动

 构建驱动模块1---STM32 DS18B20温度采集

 一般常见的STM32的关于DS18B20的例程都是针对一个IO口进行操作,若要实现多个IO口读取温度,需要写多个DS18B20相同的驱动,不方便管理。这个代码就是针对这种情况完善的单总线管理,移植简单,把相关的单总线操作集成在一起。

    DS18B20初始化函数,实现设备挂载,把DS18B20与单总线进行连接。

void ds18b20hardwareInit(ht_int8_t *name,ht_int16_t devno)
{
 char str[64];
	ht_device_t ds1820_dev;
	ds1820_dev=(ht_device_t) cmMalloc(sizeof(struct ht_device) );
	 if(ds1820_dev==NULL)
	{
		cmFault(SYS_ERROR_MEMMALLOC_ABNORMAL,RECORD_FLAG);
	}
	 
  ht_printk("\r\nCfg DS18b20 Dev<%s-%d>\r\n",name,devno);
  cmMemset(ds1820_dev,0,sizeof(struct ht_device));
	ds1820_dev -> open = bspds18b20Open;
	ds1820_dev -> close = bspds18b20Close;
	ds1820_dev -> read = bspds18b20Read;
	ds1820_dev->control = NULL;
	ds1820_dev->help = ds18b20help;
	ds1820_dev->write = NULL;
	ds1820_dev->user_privatedata = NULL;
	ds1820_dev->del=bspds18b20del;
	sprintf(str,"%s-%d",name,devno);
	if(SinglehardwareInit("singbus",devno)>0)//注册单总线操作
	{
    htDevFsRegister( ds1820_dev,str);//创建DS18B20设备
	htDevFsAssociated(ds1820_dev,"singbus",devno);//在DS18B20设备下挂载单总线
 
	}
	else
	{
		cmFree(ds1820_dev);
	}
	
}

 接下来实现DS18B20标准文件操作,DS18B20主要实现读取温度,因此只要实现bspds18b20Read 接口就行了。

 /**********************************************************************************************************
 *
 *  函数名:bspds18b20Read
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
 
 
	ht_inline ht_int32_t  bspds18b20Read   (ht_device_t dev, ht_uint32_t pos, void *buffer, ht_int32_t size)
 {

	ht_int32_t iResult = 2;
	ht_uint8_t *Dat = (ht_uint8_t *)( buffer);
	ht_uint16_t Tempra;
	 if(sigGpio!=NULL)
	 {
	  m_DS18B20Temprate= DS18B20_Get_Temp();
	  m_DS18B20Temprate=m_DS18B20Temprate*100;
		
	 }
	 else
	 {
		 iResult=-1;
	 }
	Tempra = (ht_uint16_t)(m_DS18B20Temprate);
	Dat[0]=(ht_uint8_t)(Tempra>>8);
	Dat[1]=(ht_uint8_t)(Tempra);
	return iResult;
}
 /**********************************************************************************************************
 *
 *  函数名:bspds18b20Open
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
 
ht_inline ht_int32_t  bspds18b20Open  (ht_device_t dev, ht_uint32_t oflag)
{
     
	sigGpio	=(single_driver_t*) dev->ChidNode;
	if(sigGpio==NULL)
	{
		return -1;
	}
	DS18B20_Init();
	 
	return HT_EOK;
	 
}
 /**********************************************************************************************************
 *
 *  函数名:bspds18b20Close
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
 
ht_inline ht_int32_t bspds18b20Close (ht_device_t dev)
{
		if(sigGpio!=NULL)sigGpio=NULL;
	return HT_EOK;
}
 /**********************************************************************************************************
 *
 *  函数名:ht_ds18b20test
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *ds18b20test ds18b20
 **********************************************************************************************************/
 	ht_int32_t  ds18b20help   (ht_device_t dev, ht_int8_t argc, ht_int8_t * argv[])//这个是温度测试函数,通过串口终端命令连接,输入ds18b20test 执行温度测试。
{
	int arg=0,i;
	htDevFsHandle fd;
	ht_uint8_t buffer[2];
	ht_uint16_t temp;
	if(arg<=argc)
	{
		if (strcmp((char const *) argv[2], "test")==0)
		{
		ht_printk("devname %s\r\n",argv[1]);
		fd=htDevFsOpen( argv[1],0);
		if(fd!=NULL)
		{
			 
			for(i=0;i<10;i++)
			{
				OSTimeDlyHMSM(0,0,0,300);
		 
			if(htDevFsRead(fd,0,buffer,2)==2)
			{
				temp=buffer[0]*256+buffer[1];
				ht_printk("   DS18B20 Dat:%d %d   Temp:%d.%d C\r\n",buffer[0],buffer[1],temp/100,temp%100);
			}
			else
				ht_printk("   DS18B20 is ERROR\r\n" );
		}
       htDevFsClose(fd);	
      // htDevFsDel(fd);		
		}
		else
		{
			ht_printk("can not find dev\r\n");
		}
	}
}
 	
}
 
/**********************************************************************************************************
 *
 *  函数名:bspds18b20del
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0          2016/04/27    Create
 *
 **********************************************************************************************************/
 ht_inline ht_int32_t  bspds18b20del(ht_device_t dev)
 {
	  htDevFsUnregister(dev);//卸载驱动

	   cmFree(dev);//释放Device
     dev->user_privatedata=NULL;
	 
	 return 1;
 }

       按照DS18B20的手册进行单总线读写操作,在基本操作函数里,调用单总线操作函数,sigGpio->Single_Set_Out,这些函数并没有实例化,需要初始化后调用SinglehardwareInit后实例化,这部分程序和硬件无关,可以移植到其他单片机平台。

if(SinglehardwareInit("singbus",devno)>0)//注册单总线操作
    {
    htDevFsRegister( ds1820_dev,str);//创建DS18B20设备
    htDevFsAssociated(ds1820_dev,"singbus",devno);//在DS18B20设备下挂载单总线
 
    }
    else
    {
        cmFree(ds1820_dev);
    }

/*****************************************************************************************************
 *
 *  函数名:DS18B20_Rst
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline  void DS18B20_Rst(void)
{
	/* 主机设置为推挽输出 */
	sigGpio->Single_Set_Out();
 
	sigGpio->Single_DATA_OUT(0);
	/* 主机至少产生480us的低电平复位信号 */
	delay_us18b20(750);

	/* 主机在产生复位信号后,需将总线拉高 */
	sigGpio->Single_DATA_OUT(1);

	/*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/
	delay_us18b20(15);
}
 /**********************************************************************************************************
 *
 *  函数名:DS18B20_Presence
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline  ht_uint8_t DS18B20_Presence(void)
{
	ht_uint8_t pulse_time = 0;

	/* 主机设置为上拉输入 */
	 
   sigGpio->Single_Set_In();
	/* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号 
	 * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
	 */
	while( sigGpio->Single_DATA_IN() && pulse_time<150 )
	{
		pulse_time++;
		delay_us18b20(1);
	}
	/* 经过100us后,存在脉冲都还没有到来*/
	if( pulse_time >=150 )
	return 1;
	else
	{
 
	pulse_time = 0;
	}

	/* 存在脉冲到来,且存在的时间不能超过240us */
	while( !sigGpio->Single_DATA_IN() && pulse_time<240 )
	{
		pulse_time++;
		delay_us18b20(1);
	}
	if( pulse_time >=240 )
	return 1;
	else
	{
	return 0;
		//ht_printk("OK\r\n");
	}
}
 /**********************************************************************************************************
 *
 *  函数名:DS18B20_Read_Bit
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline  ht_uint8_t DS18B20_Read_Bit(void)
{
	ht_uint8_t dat;

	/* 读0和读1的时间至少要大于60us */
	sigGpio->Single_Set_Out();
 
	/* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
 
	sigGpio->Single_DATA_OUT(0);
	delay_us18b20(2);
	sigGpio->Single_DATA_OUT(1);
	/* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
 
	sigGpio->Single_Set_In();
	delay_us18b20(12);

	if( sigGpio->Single_DATA_IN() == 1 )
	dat = 1;
	else
	dat = 0;

	/* 这个延时参数请参考时序图 */
	delay_us18b20(50);

	return dat;
}

 /**********************************************************************************************************
 *
 *  函数名:DS18B20_Read_Byte
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline ht_uint8_t DS18B20_Read_Byte(void)
{
	ht_uint8_t i, j, dat = 0;

	for(i=0; i<8; i++)
	{
		j = DS18B20_Read_Bit();
		dat = (dat) | (j<<i);
	}

	return dat;
}
 /**********************************************************************************************************
 *
 *  函数名:DS18B20_Write_Byte
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline void DS18B20_Write_Byte(ht_uint8_t dat)
{
	ht_uint8_t i, testb;
	sigGpio->Single_Set_Out();
	 

	for( i=0; i<8; i++ )
	{
		testb = dat&0x01;
		dat = dat>>1;
		/* 写0和写1的时间至少要大于60us */
		if (testb)
		{
			sigGpio->Single_DATA_OUT(0);
	 
			/* 1us < 这个延时 < 15us */
			delay_us18b20(2);

			sigGpio->Single_DATA_OUT(1);
			delay_us18b20(60);
		}
		else
		{
		 
			sigGpio->Single_DATA_OUT(0);
			/* 60us < Tx 0 < 120us */
			delay_us18b20(60);
      sigGpio->Single_DATA_OUT(1);
			 
			/* 1us < Trec(恢复时间) < 无穷大*/
			delay_us18b20(2);
		}
	}
}
 /**********************************************************************************************************
 *
 *  函数名:DS18B20_Start
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline void DS18B20_Start(void)
{
	DS18B20_Rst();
	DS18B20_Presence();
	DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
	DS18B20_Write_Byte(0X44); /* 开始转换 */
}
 /**********************************************************************************************************
 *
 *  函数名:DS18B20_Init
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline ht_uint8_t DS18B20_Init(void)
{

	sigGpio->Single_GPIO_Config();
	DS18B20_Rst();
	return DS18B20_Presence();
}

 
 /**********************************************************************************************************
 *
 *  函数名:DS18B20_Get_Temp
 *  功 能:
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0     
 *
 **********************************************************************************************************/
ht_inline float DS18B20_Get_Temp(void)
{
	ht_uint8_t tpmsb, tplsb;
	short s_tem;
	float f_tem;
	DS18B20_Rst();
	DS18B20_Presence();
	DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
	DS18B20_Write_Byte(0X44); /* 开始转换 */
	DS18B20_Rst();
	DS18B20_Presence();
	DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
	DS18B20_Write_Byte(0XBE); /* 读温度值 */

	tplsb = DS18B20_Read_Byte();
	tpmsb = DS18B20_Read_Byte();

	s_tem = tpmsb<<8;
	s_tem = s_tem | tplsb;

	if( s_tem < 0 ) /* 负温度 */
	f_tem = (~s_tem+1) * 0.0625;
	else
	f_tem = s_tem * 0.0625;
 
	return f_tem;
}

实例化硬件接口,其代码如下:实现STM32基本IO口操作。

/**********************************************************************************************************
 *
 *  函数名:ds18b20_init_sg
 *  功 能: 
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0          2016/04/27    Create
 *
 **********************************************************************************************************/
ht_inline void ds18b20_init_sg (void) 
{
 
	GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
  //GPIOA15
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
 
	
}
/**********************************************************************************************************
 *
 *  函数名:ds18b20_setin_sg
 *  功 能: 
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0          2016/04/27    Create
 *
 **********************************************************************************************************/
ht_inline void ds18b20_setin_sg (void) 
{
	GPIOA->MODER&=0XCFFFFFFF;
	GPIOA->MODER|=0;
}
/**********************************************************************************************************
 *
 *  函数名:ds18b20_setout_sg
 *  功 能: 
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0          2016/04/27    Create
 *
 **********************************************************************************************************/
ht_inline void ds18b20_setout_sg(void) 
{

	GPIOA->MODER&=0XCFFFFFFF;
	GPIOA->MODER|=0x40000000;	//PA15输出模式
}

 
/**********************************************************************************************************
 *
 *  函数名:ds18b20_out_sg
 *  功 能: 
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0          2016/04/27    Create
 *
 **********************************************************************************************************/
ht_inline void ds18b20_out_sg(ht_uint8_t dat)
{
	GPIO_WriteBit(GPIOA,GPIO_Pin_15,dat);
}
/**********************************************************************************************************
 *
 *  函数名:ds18b20_in_sg
 *  功 能: 
 *  参  数:
 *  返回值:
 *  版 本:REV1.0.0          2016/04/27    Create
 *
 **********************************************************************************************************/
ht_inline ht_uint8_t ds18b20_in_sg(void) 
{

	return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15);
}

  
//配置DS18B20
const struct hcfResource ds18b20DrvResources[] ={ 
    { "S_Init", HT_RES_ADDR, { (void **)&ds18b20_init_sg } }, 
		{	"S_SetIn", HT_RES_ADDR, { (void **)&ds18b20_setin_sg } }, 
		{	"S_SetOut", HT_RES_ADDR, { (void **)&ds18b20_setout_sg } }, 
		{	"S_Out", HT_RES_ADDR, { (void **)&ds18b20_out_sg } }, 
		{	"S_BitRead", HT_RES_ADDR, {  (void **)&(ds18b20_in_sg)   } }, 
  
   };

#define ds18b20DrvNum NELEMENTS(ds18b20DrvResources)

测试结果:

驱动节点:

温度采集结果:

猜你喜欢

转载自blog.csdn.net/u011996698/article/details/83541431