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
- STM32学习笔记(四)------DS18B20的操作与使用
- Stm32-DS18B20的使用
- STM32学习笔记(三)------GPIO口寄存器的操作与使用
- 基于STM32与DS18B20的温度采集
- stm32学习笔记(四)外部中断
- STM32学习笔记(一)-------GPIO口的操作
- STM32下DS18B20的驱动
- STM32下单只DS18B20的驱动
- 基于STM32的DS18B20驱动
- DS18B20驱动学习笔记(一)
- 单片机学习笔记--DS18B20
- nmap的操作与使用(学习笔记)
- STM32学习笔记(1):GPIO口的使用
- STM32学习笔记(2):外部中断的使用
- STM32学习笔记(2):外部中断的使用
- STM32学习笔记(2):外部中断的使用
- STM32学习笔记(7):USART串口的使用
- STM32学习笔记(1):GPIO口的使用
- ext集成struts2的小demo
- Class.getSimpleName()的作用
- hdu4536
- LeetCode OJ Valid Anagram 字符串
- Android应用: 改变当前屏幕背光亮度
- STM32学习笔记(四)------DS18B20的操作与使用
- HDU 5353 Average(枚举)
- LeetCode OJ - - Edit Distance
- 杭电 ACM 1008:Elevator
- Oracle事务的隐式提交
- 解析Myeclipse项目下的.classpath文件
- 2251 Dungeon Master【bfs】
- Linux 下常用的 19 条命令
- C语言操作windows的小程序