STM32学习笔记(四)------DS18B20的操作与使用

1、新建一个工程模板

2、搭建一个显示平台
由于我使用的是STM32mini板,且还没带LCD,所以我要想操作STM32,并用DS18B20采取温度数据之前,需要一个显示器,这里我手头有一块1602,所以先让它在STM32上跑起来。
做好之后大概就是这个样子。
这里写图片描述
这里写图片描述

由于STM32没有1602的库,所以要自己写,1602的操作相对来说还是比较简单的。

/******************************************************
建立一个1602的头函数
用于:使能端口定义
     数据端口定义
     函数声明
******************************************************/
#include "stm32f10x.h"
#ifndef __lcd1602_H
#define __lcd1602_H
#define uchar unsigned char


//使能端口定义
#define LCD162A_RS PCout(8)
#define LCD162A_RW PCout(7)    
#define LCD162A_E  PCout(6)
//数据端口定义
#define DATAOUT(x) GPIOA->ODR=(GPIOA->ODR&0xff00)|(x&0x00FF); //Pa0-Pa7

// 函数声明
void lcd162a_WriteCommand(u8 CMD);
void lcd162a_WriteData(u8 dataW);
void lcd_init(void);

#endif

接下来就是1602的相关函数的编写

/*********************************************************
建立一个1602的C文件
用于:相关函数的编写
**********************************************************/
#include "lcd1602.h"
#include "delay.h"
#include "stm32f10x.h"

//写命令
void lcd162a_WriteCommand(u8 CMD)
{
 delay_ms(2);  

 LCD162A_RS=0;
 LCD162A_RW=0;
 LCD162A_E=1;

 DATAOUT(CMD);

 delay_us(2);

 LCD162A_E=0;               
}

//写数据
void lcd162a_WriteData(u8 dataW)
{
 delay_ms(2); 

 LCD162A_RS=1;
 LCD162A_RW=0;
 LCD162A_E=1;

 DATAOUT(dataW);

 delay_us(2);

 LCD162A_E=0;              
}

//初始化,主要用于IO的声明和使能
//这里我学会了两种方法,一个是函数法,另一个是寄存器法;读懂寄存器发首先要了解GPIO口相关寄存器的使用
void lcd_init(void)
{
//  GPIO_InitTypeDef*   GPIO_InitStruct;
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);   //使能PA,PD端口时钟
//  //设置PA0-PA7
//  GPIO_InitStruct->GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
//  GPIO_InitStruct->GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
//  GPIO_InitStruct->GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_Init(GPIOA, GPIO_InitStruct);  
//  GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);   //置1
//  //设置PC6-PC8
//  GPIO_InitStruct->GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
//  GPIO_InitStruct->GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
//  GPIO_InitStruct->GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_Init(GPIOC, GPIO_InitStruct);  
//  GPIO_SetBits(GPIOC,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8); //pc6-pc9  置1

/****************************************************************      
               寄存器的写法与注释
*****************************************************************/  

    RCC->APB2ENR|=1<<2;    
    RCC->APB2ENR|=1<<4;     //使能PA,PD端口时钟
    GPIOA->CRL=0X33333333;    //PA0-7  推挽输出
    GPIOA->ODR|=0X00FF;       //PA0-7  端口置1

    //pc6-pc9
    GPIOC->CRH&=0XFFFFFF00;     //清掉PC8 9原来的设置
    GPIOC->CRL&=0X00FFFFFF;     //清掉PC6 7原来的设置
    GPIOC->CRH|=0X00000033;     //PC8  9   推挽输出
    GPIOC->CRL|=0X33000000;     //PC6  7   推挽输出
    GPIOC->ODR|=0X03C0;       //pc6-pc9  置1


    LCD162A_E=0;
    lcd162a_WriteCommand(0x38);     //设置16*2显示,5*7点阵,8位数据接口
    lcd162a_WriteCommand(0x0c);     //设置开显示,不显示光标
    lcd162a_WriteCommand(0x06);     //写一个字符后地址指针加一
    lcd162a_WriteCommand(0x01);     //显示清0,数据指针清零
}

上面这块完成之后,LCD1602基本上能显示数据了。
接下来就是调用STM32 中的DS18B20的库,使用其中的相关函数。我用的是原子哥的板子,当然用的也是他们的函数,向原子哥致敬,这里我贴出来,方便我日后理解。

#ifndef __DS18B20_H
#define __DS18B20_H 
#include "sys.h"   
//IO方向设置
#define DS18B20_IO_IN()  {GPIOB->CRL&=0XFFFFFFF0;GPIOB->CRL|=8<<0;}
#define DS18B20_IO_OUT() {GPIOB->CRL&=0XFFFFFFF0;GPIOB->CRL|=3<<0;}
IO操作函数                                             
#define DS18B20_DQ_OUT PBout(0) //数据端口  PA0
#define DS18B20_DQ_IN  PBin(0)  //数据端口  PA0 

u8 DS18B20_Init(void);          //初始化DS18B20
short DS18B20_Get_Temp(void);   //获取温度
void DS18B20_Start(void);       //开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void);     //读出一个字节
u8 DS18B20_Read_Bit(void);      //读出一个位
u8 DS18B20_Check(void);         //检测是否存在DS18B20
void DS18B20_Rst(void);         //复位DS18B20    
#endif
#include "ds18b20.h"
#include "delay.h"  
//////////////////////////////////////////////////////////////////////////////////   
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK miniSTM32开发板
//DS18B20驱动代码      
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/12
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved                                     
//////////////////////////////////////////////////////////////////////////////////


//复位DS18B20
void DS18B20_Rst(void)     
{                 
    DS18B20_IO_OUT(); //SET PA0 OUTPUT
    DS18B20_DQ_OUT=0; //拉低DQ
    delay_us(750);    //拉低750us
    DS18B20_DQ_OUT=1; //DQ=1 
    delay_us(15);     //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void)     
{   
    u8 retry=0;
    DS18B20_IO_IN();//SET PA0 INPUT  
    while (DS18B20_DQ_IN&&retry<200)
    {
        retry++;
        delay_us(1);
    };   
    if(retry>=200)return 1;
    else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
    {
        retry++;
        delay_us(1);
    };
    if(retry>=240)return 1;     
    return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void)            // read one bit
{
    u8 data;
    DS18B20_IO_OUT();//SET PA0 OUTPUT
    DS18B20_DQ_OUT=0; 
    delay_us(2);
    DS18B20_DQ_OUT=1; 
    DS18B20_IO_IN();//SET PA0 INPUT
    delay_us(12);
    if(DS18B20_DQ_IN)data=1;
    else data=0;     
    delay_us(50);           
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)    // read one byte
{        
    u8 i,j,dat;
    dat=0;
    for (i=1;i<=8;i++) 
    {
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }                           
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
    DS18B20_IO_OUT();//SET PA0 OUTPUT;
    for (j=1;j<=8;j++) 
    {
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}
//开始温度转换
void DS18B20_Start(void)// ds1820 start convert
{                                          
    DS18B20_Rst();     
    DS18B20_Check();     
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// convert
} 
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在         
u8 DS18B20_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    //使能PORTA口时钟 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;               //PORTA0 推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_SetBits(GPIOB,GPIO_Pin_0);    //输出1

    DS18B20_Rst();

    return DS18B20_Check();
}  
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
    short tem;
    DS18B20_Start ();                    // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();     
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert     
    TL=DS18B20_Read_Byte(); // LSB   
    TH=DS18B20_Read_Byte(); // MSB  

    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//温度为负  
    }else temp=1;//温度为正       
    tem=TH; //获得高八位
    tem<<=8;    
    tem+=TL;//获得底八位
    tem=(float)tem*0.625;//转换     
    if(temp)return tem; //返回温度值
    else return -tem;    
} 
/******************************************************
                    主     函     数   
*******************************************************/
#include "stm32f10x.h"
#include "lcd1602.h"
#include "delay.h"
#include "sys.h"
#include "ds18b20.h"   

 int main(void)
 {  
        short temperature;

        u8 ge;
        u8 shi;
      u8 bai;
      u8 qian;
      uchar t = 0;
        uchar table[] =  "  1602 TEST...  ";
      uchar table1[] = "  Successful !  ";
        uchar table2[] = " DS18B20 TEST...";
      uchar table3[] =  "TEMPERATURE IS: ";

  delay_init();          
  lcd_init();  
  delay_ms(1000);
  DS18B20_Init();

     lcd162a_WriteCommand(0x80);
     for(t = 0;t < 16;t++)
     {
         lcd162a_WriteData(table[t]);
         delay_ms(5);
     }
     delay_ms(1000);
     lcd162a_WriteCommand(0x80+0x40);
     for(t = 0;t < 16;t++)
     {
         lcd162a_WriteData(table1[t]);
         delay_ms(5);
     }
     delay_ms(1000);
     lcd162a_WriteCommand(0x01);

     for(t = 0;t < 16;t++)
     {
         lcd162a_WriteData(table2[t]);
         delay_ms(5);
     }
     delay_ms(1000);
     lcd162a_WriteCommand(0x80+0x40);
     for(t = 0;t < 16;t++)
     {
         lcd162a_WriteData(table1[t]);
         delay_ms(5);
     }
     delay_ms(1000);
     lcd162a_WriteCommand(0x01);

        for(t = 0;t < 16;t++)
     {
         lcd162a_WriteData(table3[t]);
         delay_ms(5);
     }

     while(1)
     {

             temperature=DS18B20_Get_Temp();    
       temperature =  temperature*10;
           qian =  temperature /1000;
             bai = temperature % 1000 / 100;
             shi = temperature % 1000 % 100 / 10;
             ge = temperature % 10;
             lcd162a_WriteCommand(0x80 + 0x44);
             lcd162a_WriteData(0x30+qian);lcd162a_WriteData(0x30+bai);lcd162a_WriteData(0x2e);lcd162a_WriteData(0x30+shi);lcd162a_WriteData(0x30+ge);lcd162a_WriteData(0xdf);lcd162a_WriteData(0x43);
             delay_ms(100);
     }
}

3、遇到的问题

(1)1602最开始的时候我用的直接就是一个空的工程模板,但是里面的HARDWARE中有一组led.c led.h
这里面也有端口的定义和声明,但是我没有注意到,并且自顾自的编写了1602.h和1602.c里面进行了重复的工作,导致1602一致没有正常工作。所以以后编写STM32程序的时候,需要什么固件库再往里面添加,否则会出现意想不到的问题,也很难查找问题的所在,即便你自己的写的是对的。

(2)在主函数里面temperature=DS18B20_Get_Temp()之后,我认为temperature的值就是XX,X的小数,所以就直接乘以10再分离每一位的数据,导致显示出错。
事实上temperature的值就是XXX 不用将其乘以10再分离每一位的数据,直接分离就好。

  • 19
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值