51单片机学习篇

编程入门 行业动态 更新时间:2024-10-14 20:25:34

51<a href=https://www.elefans.com/category/jswz/34/1769836.html style=单片机学习篇"/>

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典型温度读取过程

  1. 初始化(延时1ms)
  2. 发送ROM指令(0xcc)
  3. 发送温度转换命令(0x44)
  4. 初始化(延时1ms)
  5. 发送ROM指令(0xcc)
  6. 发送读取温度指令(0xbe)
  7. 读出低八位数据
  8. 读出高八位数据
  9. 将俩个八位数据或运算到一个16位变量(int)中
  10. 将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单片机学习篇

本文发布于:2024-03-23 16:51:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1740536.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:单片机

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!