单片机学习篇"/>
51单片机学习篇
开篇先说一句废话····
本旺名字叫萨摩耶,,Please 叫我旺财,,,哈哈,招财进宝嘛!
Ds18b20
没啥好说的,这玩意就是测温度的器件。先看看长啥样:
它有三根线,一个VCC,一根GND,一根数据传输线DQ,所以最后数据传输都在这个DQ上。
说说这个玩意的特点:
- 与单片机连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯
- 可编程的分辨率为 9~12 位, 对应的可分辨温度分别为 0.5℃、0.25℃、0.125℃ 和 0.0625℃, 可实现高精度测温。(一般默认采用12)
- 12 位分辨率时最多在 750ms 内把温度值转换为数字, 速度更快
说这些有用的因为之前传输数据都是有专门的数据线,而这玩意只有一根,那么对于传输时时间就必须严谨(要是不严谨,一阵时钟脉冲一阵数据会传输失败)
操作Ds18b20
1.修改分辨率,这个人家默认12位,想试着更改可参考数据手册修改对应位即可
2.时序图
这里就是注意时间就好,时间太短或者太长会导致传输失败
-
初始化
步骤:
1.将数据传输线DQ拉低
2.延时642us(480–960us)
3.将DQ拉高
4.等待Ds18b20拉低(给你个反应证明自己的存在):如果等到低电平放回1(存在),等不到等一会就好不能一直等(5ms)退出放回0(不存在) -
写时序
注意的是它这时序图是写0或者写1,也就是每次写一位,而一个字节数据有8位,所以要循环八次哦,循环内部;
步骤:
1.将数据线DQ拉低
2 将数据最低位写入DQ中(数据&0x01)(本是延时15us,太短,一次延时)
3 延时60us以上(15+15+30us)
4 拉高数据线DQ
5 数据右移一位(为下次传输准备)
- 读时序
同样,这里也需要循环八次读0或者读1,循环内部:
步骤:
1 将数据线DQ拉低(给一个i++表示小延时)
2 将数据线拉高(给两个i++(6us)让数据稳定)
3 读出最低位(bi)
4 将读出的最低位和返回变量进行或运算((dat>>1)|(bi<<7))
5 延时46us以上(>1+45us)
循环8次后将返回变量返回出去(return)
基础函数写完,就要把他们调用起来了
Ds18b20典型温度读取过程
- 初始化(延时1ms)
- 发送ROM指令(0xcc)
- 发送温度转换命令(0x44)
- 初始化(延时1ms)
- 发送ROM指令(0xcc)
- 发送读取温度指令(0xbe)
- 读出低八位数据
- 读出高八位数据
- 将俩个八位数据或运算到一个16位变量(int)中
- 将16位变量返回出去 (注意返回类型)
使用Ds18b20温度传感器检测室内温度,使用数码管显示
//Ds18b20.c
#include "Ds18b20.h"
#include "intrins.h"
void Delay(u16 i) //11.0592MHz 1ms
{while(i--){unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);}
}
//Ds18b20初始化
u8 Ds18b20Init(){u8 i;DSPORT=0;i=70;while(i--);DSPORT=1;i=0;while(DSPORT){i++;Delay(1);if(i>5)return 0;}return 1;
}
//Ds18b20写入数据
void Ds18b20WriteByte(u8 dat){u8 i,j;for(i=0;i<8;i++){DSPORT=0;j++;DSPORT=dat&0x01; //发送最低位j=6;while(j--);DSPORT=1;dat>>=1;}
}
//Ds18b20读出数据
u8 Ds18b20ReadByte(){u8 i,j;u8 bi,dat;for(i=0;i<8;i++){DSPORT=0;j++;DSPORT=1;j++;j++;bi=DSPORT;dat=(dat>>1)|(bi<<7);j=4;while(j--);}return dat;
}
//开启温度转换
void Ds18b20ChangeTemp(){Ds18b20Init();Delay(1);Ds18b20WriteByte(0xcc);Ds18b20WriteByte(0x44);
}
//从储存寄存器读出数据
void Ds18b20ReadCom(){Ds18b20Init();Delay(1);Ds18b20WriteByte(0xcc);Ds18b20WriteByte(0xbe);
}
//读出温度数据 16位数据
int Ds18b20ReadTemp(){u8 tmh,tml;int dat=0;Ds18b20ChangeTemp();Ds18b20ReadCom();tml=Ds18b20ReadByte();tmh=Ds18b20ReadByte();dat=tmh;dat<<=8;dat|=tml;return dat;
}
//main.c
#include "reg52.h"
#include "Ds18b20.h"//typedef unsigned int u16;
//typedef unsigned char u8;u8 smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
u8 Display[8];//38译码器
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;//数据处理函数
void Datapross(int dat){float tp;if(dat<0){Display[0]=0x40; //符号位显示负号dat=dat-1;dat=~dat;tp=dat;dat=tp*0.0625*100+0.5;}else{Display[0]=0x00; //符号位不显示tp=dat;dat=tp*0.0625*100+0.5;}Display[1]=smgduan[dat/10000];Display[2]=smgduan[dat%10000/1000];Display[3]=smgduan[dat%1000/100]|0x80; //个位加小数点Display[4]=smgduan[dat%100/10];Display[5]=smgduan[dat%10];
}
//数码管显示函数
void Showsmg(){ u16 i;for(i=0;i<6;i++){ switch(i){case 5: LSA=1;LSB=0;LSC=0;break;case 4: LSA=0;LSB=1;LSC=0;break;case 3: LSA=1;LSB=1;LSC=0;break;case 2: LSA=0;LSB=0;LSC=1;break;case 1: LSA=1;LSB=0;LSC=1;break;case 0: LSA=0;LSB=1;LSC=1;break;}P0=Display[i];Delay(1);P0=0x00;}
}
void main(){while(1){Datapross(Ds18b20ReadTemp());Showsmg();}
}
//Ds18b20.h
#ifndef _DS18B20_H
#define _DS18B20_H#include "reg52.h"#ifndef u8
#define u8 unsigned char
#endif#ifndef u16
#define u16 unsigned int
#endifsbit DSPORT=P3^7;void Delay(u16 i);
int Ds18b20ReadTemp();#endif
总结
- 这个是时钟控制与数据传输在一根线上,所以要注意时序图中时间的控制,可以采用Keil仿真计算时间
- 除了在数码管上显示也可以在LCD1602字符型液晶上显示
- 时序图的阅读越来越重要了呀
更多推荐
51单片机学习篇
发布评论