参考资料
先上参考资料
欧老师的DS18B20视频讲解
【进阶强化01】蓝桥杯中DS18B20的基本应用
西风老师的DS18B20视频讲解
第六讲 DS18B20模块
西风老师讲的是大模板的使用,配合他的大模板的食用效果更加
我能看懂的就是一个定时器的复用(我只看了这集hhhh)这点很巧妙,我觉得应该会很有用的,定时器的复用这个思路确实我是第一次见,大家有兴趣的可以去看看。
单总线的原理
我推荐这个博客和两个教学视频搭配食用(我不会,讲了怕误人子弟hhhh)
读取温度代码如下
float rd_temperature(){
u8 low,high;
int t;
init_ds18b20();//初始化
Write_DS18B20(0xcc);//写入指令跳过rom
Write_DS18B20(0x44);//进行温度转换
Delay_OneWire(200);//延时给点时间让其转换一下
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过rom
Write_DS18B20(0xbe);//读取温度
low=Read_DS18B20();//先读低的
high=Read_DS18B20();//再读高的 顺序不能反
t=high<<8|low;//两者合并
return t/16.0;//这个精度是0.0625
}
这个顺序不能反的,就是这么使用的,把这个当作使用说明就好了,当成一个新的机器,先会使用,其他的之后再说hhhhh。
这次采用的是模块化编程,因为有个onewire.c文件
代码
这个是onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include "main.h"
sbit DQ = P1^4;
float rd_temperature();
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
#endif
这个是onewire.c 其实就是官方文档加了个我们自己写的读取温度的函数
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
//
#include "onewire.h"
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
float rd_temperature(){
u8 low,high;
int t;
init_ds18b20();//初始化
Write_DS18B20(0xcc);//写入指令跳过rom
Write_DS18B20(0x44);//进行温度转换
Delay_OneWire(200);//延时200ms让机器读一下温度
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过rom
Write_DS18B20(0xbe);//读取温度
low=Read_DS18B20();//先读低的
high=Read_DS18B20();//再读高的 顺序不能反
t=high<<8|low;//两者合并
return t/16.0;//这个精度是0.0625
}
这个是main.h 要包含的头文件都在这里
#ifndef __MAIN_H
#define __MAIN_H
typedef unsigned char u8;
typedef unsigned int u16;
#include <reg52.h>
#include "onewire.h"
void selecthc573(u8 channel);
void delay(u8 t);
void smg_display(u8 pos,u8 value);
void T_show();
#endif
这是main.c
#include "main.h"
float t=0;//全局变量存储温度
void selecthc573(u8 channel){
switch(channel){
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
}
}
u8 code smg_duanma[19]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f,0xff};
void delay(u8 t){
int i;
while(t--){
for(i=0;i<12;i++);//12M晶振需要循环12次 这个问题终于被解决
}
}
void smg_display(u8 pos,u8 value){
selecthc573(6);
P0=0x01<<pos;
selecthc573(7);
P0=0xff;//数码管消影
P0=value;
}
void T_show(){//显示温度
t=rd_temperature();
smg_display(0,smg_duanma[(u8)t/10%10]);
delay(50);
smg_display(1,smg_duanma[(u8)t%10]-0x80);
delay(50);
smg_display(2,smg_duanma[(u16)(t*10)%10]);
delay(50);
smg_display(3,smg_duanma[(u16)(t*100)%10]);
delay(50);
}
void main(){
t=rd_temperature();
delay(800);
selecthc573(4);
P0=0xff;//关闭LED灯
while (1){
T_show();
}
}
数码管什么的我们之前的代码都写过的,可以参考我之前的文章
这个是工程截图
编写代码的时候我遇到一个问题
就是有个警告 一连四个一起出现
意思是说我这个函数,使用了但是找不到定义,我寻思我也没有忘记定义啊?
于是我回去看,好家伙,写错了一个字母。。。。
应该是是temp'e'rature 打错了。。。。
不过这也提醒了我,一连出现这个四个错误,有可能就是你定义函数打错字了。
修改之后完美通过
复制一下这个错误
linking...
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?RD_TEMPRATURE?ONEWIRE
*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
SYMBOL: RD_TEMPERATURE
MODULE: .\Objects\main.obj (MAIN)
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
SYMBOL: RD_TEMPERATURE
MODULE: .\Objects\main.obj (MAIN)
ADDRESS: 02CCH
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
SYMBOL: RD_TEMPERATURE
MODULE: .\Objects\main.obj (MAIN)
ADDRESS: 04EBH
效果演示
CT107D模块DS18B20功能演示
还差超声波 ds1302等等 冲!!!!!!!