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

来源:互联网 发布:php 汉字转ascii 编辑:程序博客网 时间:2024/06/05 07:12

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);          //初始化DS18B20short 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);         //检测是否存在DS18B20void 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                                     ////////////////////////////////////////////////////////////////////////////////////复位DS18B20void 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/0u8 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再分离每一位的数据,直接分离就好。

2 0