打印
[STM32F4]

基于STM32自码 DS18B20驱动程序

[复制链接]
1006|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
643757107|  楼主 | 2018-1-31 14:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <ds18b20.h>
#include "delay.h"
#include "usart.h"       

//ds18b20初始化
void  init_ds18b20( void )
{
        init_onewire_out();
        GPIO_ResetBits(GPIOG,GPIO_Pin_9);
        delay_us(480);
        init_onewire_in();
        delay_us(60);
        if( !DQ_In)
        {
                delay_us(120);
                               
        }
}
//ds18b20 检测
void  chack_ds18b20( void )
{
        init_onewire_out();
        GPIO_ResetBits(GPIOG,GPIO_Pin_9);
        delay_us(240);
        init_onewire_in();
        delay_us(60);
        if( !DQ_In)
        {
                delay_us(80);
                if( !DQ_In )
                        printf("检测到DS18B20!\r\n");
                               
        }

}
//设置为主设备写总线,从设备读总线
void init_onewire_out( void )
{
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
        GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
}
//设置为主设备读取总线,从设备写总线
void init_onewire_in( void )
{
       
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
//        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
        GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
}

void ds18b20_write_byte( u8 data )
{
        u8 i;
        u8 j=0;
        init_onewire_out();
        for(i=0;i<8;i++)
                {
                        j=data & 0x01;
                        if(j)
                        {
                                DQ_Out=0;                //写1
                                delay_us(15);
                                DQ_Out=1;
                                delay_us(60);
                               
                        }
                        else
                        {
                                DQ_Out=0;                //写0
                                delay_us(60);
                                DQ_Out=1;
                                delay_us(1);
                        }
                        data = data>>1;
                }       
}
//读取DS18B20 的一位
u8 ds18b20_read_bit( void )
{       
        u8 bit;
        init_onewire_out();
        DQ_Out=0;
        delay_us(2);
        DQ_Out=1;
        init_onewire_in();
        delay_us(12);
        if(DQ_In)
                bit=1;
        else
                bit=0;
        delay_us(50);
        return bit;
}
//读ds18b20的字节
u8 ds18b20_read_byte ( void )
{
        u8 data=0;
        u8 i;
        u8 j=0;
        for(i=0;i<8;i++)
        {
                j=ds18b20_read_bit();
                if(j)                        //注意顺序即可,ds18b20先发送地位到总线上
                        j=j<<i;
                data |=j;

        }
        return data;
}
//获取ds18b20的系列码和48位唯一序列号
void ds18b20_read_rom_number()
{
        u32 number=0;
        u8 data,i,serial_num,ds18b20_crc;
        init_ds18b20();
        ds18b20_write_byte(0x33);
        serial_num = ds18b20_read_byte();
        for(i=0;i<6;i++)
        {
                data = ds18b20_read_byte();
                number |= data;
                number = number<<8;
        }
        ds18b20_crc = ds18b20_read_byte();
       
        printf("系列号是:%d\r\n",serial_num);
        printf("序列号是:%d\r\n",number);
        printf("CRC校验为:%d\r\n",ds18b20_crc);
       
}
//开启ds18b20温度转换
void tem_chage( void )
{
        init_ds18b20();
        ds18b20_write_byte(0xcc);                //忽略rom指令
        ds18b20_write_byte(0x44);        //开启转换
}

short  get_temp( void )
{
        int temp=0;
        u8 i,TH,TL;
        short tem;

        tem_chage();
        delay_us(10);
        init_ds18b20();
        ds18b20_write_byte(0xcc);                //忽略rom指令
        ds18b20_write_byte(0xbe);        //读取温度转换值
        TL=ds18b20_read_byte();
        TH=ds18b20_read_byte();
       
        if(TH > 7)                 //通过判读存储器的高五位的0,1来判断温度的正负,
        {
                temp = 0;        //为负
                TH =~TH;
                TL =~TL;
        }
        else
                temp = 1;        //为正
        tem = TH;
        tem =tem<<8;
        tem =tem+TL;
        tem = (double)tem * 0.625;
        if(temp)
                return tem;
        else
                return -tem;
       
}
void ds18b20_return_TH_TL_CONF( void )
{
        char data,data_TH,data_TL,CONF;
        init_ds18b20();
        ds18b20_write_byte(0xcc);                //忽略rom指令
        ds18b20_write_byte(0xbe);        //读取温度转换值
        data = ds18b20_read_byte();
        data = ds18b20_read_byte();
        data_TH = ds18b20_read_byte();
        data_TL = ds18b20_read_byte();
        CONF =ds18b20_read_byte();
        printf("过温报警的温度为:%d℃\r\n",data_TH);
        printf("低温报警的温度为:%d℃\r\n",-(data_TL-128));
        CONF &=0x60 ;
        CONF =CONF>>5;
        switch (CONF) {
                case 0:
                        printf("ds18b20的测量精度为9位,精度为0.5℃\r\n");
                        break;
                case 1:
                        printf("ds18b20的测量精度为10位,精度为0.25℃\r\n");
                        break;
                case 2:
                        printf("ds18b20的测量精度为11位,精度为0.125℃\r\n");
                        break;
                case 3:
                        printf("ds18b20的测量精度为12位,精度为0.0625℃\r\n");
                        break;
                default:
                        printf("error!!\r\n");
                        break;
        }
}
//设置温度报警值和配置精度,TH过温报警值(TH>0),TL低温报警值(TL为负数 ),mode配置模式0,1,2,3
//mode=0 精度为9位        00011111 dat=31
//mode=1 精度为10位  00111111        dat=63
//mode=2 精度为11位        01011111        dat=95
//mode=3 精度为12位  01111111        dat =127
void ds18b20_write_TH_TL_CONF(u8 TH,u8 TL,u8 mode)
{
        u8 dat;
        switch (mode){
                case 0:
                        dat=31;
                        break;
                case 1:
                        dat=63;
                        break;
                case 2:
                        dat=95;
                        break;
                case 3:
                        dat=127;
                        break;
                default:
                        printf("mode error!!\r\n");
                        dat=127;
                        break;
        }
        TL=TL+128;
        init_ds18b20();
        ds18b20_write_byte(0xcc);                //忽略rom指令
        ds18b20_write_byte(0x4e);        //写入暂存寄存器 ,过温和低温报警值
        ds18b20_write_byte(TH);        //写入20°为过温报警值
        ds18b20_write_byte(TL);        //写入-20°为低温报警值
        ds18b20_write_byte(dat);        //写入精度
        init_ds18b20();
        ds18b20_write_byte(0xcc);                //忽略rom指令
        ds18b20_write_byte(0x48);        //将写入的暂存寄存器拷入EEPROM
}
void ds18b20_chack_self( void )
{
        chack_ds18b20();
        ds18b20_read_rom_number();
        ds18b20_return_TH_TL_CONF();
}





沙发
643757107|  楼主 | 2018-1-31 14:57 | 只看该作者
1.初始化时序要注意,笔者亲测,在MCU控制单总线为低电平240us即可(数据手册上要求至少480us)释放总线,等待60us后即可检测到到DS18B20返回的拉低单总线信号,此处,需注意至少应在此等待120us,否则可能会导致温度传感器无**常工作。

使用特权

评论回复
板凳
643757107|  楼主 | 2018-1-31 14:57 | 只看该作者
2.初学者需注意时序,对于DS18B20的操作都必需经过三步:初始化,ROM命令(多为跳过指令0xCC),DS18B20功能命令。再次强调对其的每一个操作必须经过这三步,可阅读code加深理解。

3.在读取DS18B20时,注意顺序,DS18B20先发送低位,在字节读取时应当注意。

4.初学者应尝试实现对于DS18B20内部ROM的8位系列号(28H),和48位唯一序列号进行读取,以及修改温度传感器内部EEPROM的过温、低温报警值。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

213

主题

3805

帖子

11

粉丝