51单片机-LED灯&蜂鸣器&数码管&按键&DS18B20温度传感器

LDE灯的相关程序

LED灯闪烁

LED流水灯

方法1

方法二:

因为P1口可以直接控制P1^0~P1^7的8个led灯,利用一个8位的二进制数字来进行控制即可。如果要点亮P1^0 只需要给P1口传递 1111 1110即可。

蜂鸣器的使用

什么是蜂鸣器?

蜂鸣器是一种一体化结构的电子发生器,主要是用来起到报警的作用。

蜂鸣器分类

有源蜂鸣器

内部有震荡源,所以只要通电就会鸣叫,控制比较方便。

无源蜂鸣器

内部不带震荡源,所以通电不能让它直接鸣叫,必须使用2K~5K的方波去驱动它,声音频率可以调整。

什么是三极管

一种控制电流的半导体器件,作用就是把微弱的电信号放大成更大幅度的电信号,在电路中主要作用于开关和放大电流的作用。

三级管有三个引脚:B(基极)、C(集电极)、E(发射极)。

PNP三极管的图示:

关键点在于B极和E极之间的电压情况,对于PNP而言,只要E极电话高于B极0.7V以上,这个三极管就可以顺利导通。

方波

一种非正弦曲线的波形,通常会与电子和讯号处理的时候出现。

理想的方波只有高和低这两个值,救护车的声音频率高频是1000Hz 低频是 750Hz。

1000HZ的分析:

750HZ的分析:

方波图:

代码实现

数码管的使用

数码管显示数字的原理

数码管的电路图

数码管段选图

不同的数字对应的P0口应该传递的16进制数字(不带小数点的)

数码管显示指定数字

数码管显示动态数字

按键的使用

按键消抖

当物理按键按下或者弹起的时候,电平都不是立即为0或者立即为1的,会出现抖动的情况,所以要进行消抖操作。

按键按下一次的时候电平变化:

代码演示

DS18B20温度传感器的使用

简介

DS18B20是一款常用的高精度单总线数字温度测量芯片,体积小,占用资源少,抗干扰能力强。

使用方法说明

图示

由于温度传感器的电路设计原因,必须按照如下顺序进行操作才能成功

1、先复位

2、执行一次ROM指令

3、执行一次RAM指令

注意: 一次ROM只能搭配一次RAM

完成温度读取的步骤

先做温度转换

复位和检测:每次发命令之前都要先进行复位检测,目的是检测当前温度传感器的状态是否正常。

按照ROM指令表,发送0xCC来跳过ROM存储器,因为设备上只有一个DS18B20,所以不需要进行其他的寻址等操作。

按照RAM指令表,发送0x44来启动温度传感器降温度转化为数字信号,存储到RAM中。

读取温度数据

复位和检测

给ROM发送0xCC跳过ROM存储器

给RAM发送0xBE来读取RAM暂存器中的温度数据:读取温度低位;读取温度高位。

温度的转化问题
图示

原码、反码和补码

原码:

最高位是符号位,0表示正数,1表示负数。

反码:

最高位是符号位,0表示正数,1表示负数;

正数的反码是它本身,负数的反码除了符号位以外,各位取反。

补码:

最高位是符号位,0表示正数,1表示负数;

正数的补码也是它本身,负数的补码是反码+1;

如:原码是1011 对应反码是1100 补码就是 1101;

设计补码的目的:就是能够和其相反数相加通过溢出的方式从而使计算机内的结果变为合理的二进制码。

例:比如1 和 -1相加 正常的结果是0;如果用原码计算:0001 + 1001 = 1010,结果是-2 这样的结果是错误的;利用补码实现:0001 + 1111 = 10000, 将最高位的1溢出, 结果就变成了0000,这样的结果是正确的。

DS18B20的时序问题

初始化时序

图示:

单总线上所有的通信都是从初始化时序开始的,主机输出低电平,保持低电平至少480us(实际在480~960us之间都可以),以产生复位脉冲。

接着主机释放总线,将电平拉高,延时15~60us,进入接受模式,接着DS18B20会自己拉低总线60~240us,会产生应答脉冲,如果是低电平会延时一段时间,之后会上拉电阻至少480us结束。

代码

写时序

图示:

说明:

写0时序:主机输出低电平,60us以后拉高电平 延时一会让电平稳定。

写1时序:主机输出低先平,立即拉高,然后延时60us即可。

按位与(&):

按位与遵循的原则:两个二进制数对应的每一位如果都是1,结果就是1,否则0。

代码演示

读时序

图示:

说明:

单总线仅在主机发出读时序的时候,才向主机传输数据,所以在发出读数据命令之后,必须马上产生读时序,以便从机能够发送输出给主机。

所有的读时序都需要60us的时间, 并且要在两次独立的读时序之间要间隔至少1us。主机在读时序期间必须要释放总线,并且在时序起始后的15us采样数据。

按位或(|):

对应的两个数字,如果有一个为1,那么结果就是1,否则结果为0。

代码:

使用DS18B20温度传感器完成温度检测并在数码管上显示:

// DS18B20的温度传感器程序
#include <reg51.h>
// 定义温度传感器的引脚变量
sbit DQ=P3^7;
// 定义不带小数点的数字数组
unsigned char arr1[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
// 定义带小数点的数字数组
unsigned char arr2[10] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};
// 定义全局变量来保存温度的第八位和高八位
unsigned char tempL = 0;
unsigned char tempH = 0;

// 定义变量存放温度值的整数部分
unsigned int sdata;

// 定义变量来存放小数第一位和第二位
unsigned char xiaoshu1;
unsigned char xiaoshu2;
// 定义延时函数
// 这个延时程序的具体延时时间是 time(us) = i * 8 + 10, 适用于2ms之内的延时
void delay(unsigned char i)
{
	for(i; i > 0; i--);
}
// 初始化程序
unsigned char Init_DS18B20()
{
	unsigned char x = 0;
	DQ=1; // 先让DS18B20稳定在高电平的状态,先拉高
	delay(8); // 延时74us准备开始初始化时序
	DQ=0; // 发送低电平,开始发送低电压的脉冲信号
	delay(80); // 等待650us,在480us到960us之间
	DQ=1; // 拉高总线
	delay(5); // 延时50us(在15us到60us之间) 等待DS18B20反应,准备接收DS18B20发送的数据
	x = DQ; // 用x来接受DS18B20返回的电平值,如果DS18B20初始化成功X的值就是0,否则为1
	delay(30); // 等待一会完成整个的初始化时序。
	return x;
}

// 写函数
// 调用一次写入一个字节
void writeOneChar(unsigned char dat)
{
	unsigned char i=0;
	for(i = 8;i > 0;i--) // 循环8次,每次写入一位,写完8位 就是一个字节
	{
		DQ=0; // 不论写0还是写1,都需要先拉低总线
		// 从最低位开始写,让dat和0x01进行与操作获取最低位数字发送给DS18B20
		DQ=dat&0x01;
		delay(5); // 继续延时,等待DS18B20采样完成
		DQ=1; // 释放总线
		dat>>=1; // 将dat的值直接右移,将下一位的值移动到最低位,再重新赋值给dat用来下次获取最低位数据
		delay(2); // 执行完一个写数字的程序,等待一下 准备开始下次写程序。
	}
}


// 读函数
// 循环8次可以读完一个字节
unsigned char readOneChar()
{
	unsigned char dat=0; // 准备一个变量来接受读出来的一个字节的数据
	unsigned int i ;
	for(i = 0; i < 8 ;i++)
	{
		DQ=1;// 先拉高电平,进入准备工作
		delay(1); // 可以让每次的读时序间隔1us以上,实际等待了18us
		DQ=0; // 拉低总线
		delay(1); // 延时18us
		
		// 将dat右移一位,因为实际保存的数据是8位数据。
		// 但是在每次保存之后进行位移,总共位移7次,所以要将第一次位移给取消掉
		dat>>=1; // 如果读到的DQ是1 进行下面判断将1写入dat,如果是0,就直接进行右移,将0保存下来即可
		DQ=1; // 释放总线,回到高电平,会产生读信号。
		// 因为DS18B20如果发送的是一个0的数据,产生读信号之后,仍然会将总线设置为低电平持续完读时序之后才释放总线
		// 如果DS18B20要发送的是一个1的数据,产生读信号之后,会直接释放总线,那么我们读到的就是高电平。
		
		// 如果读到的DQ是高电平,就直接与0x80进行按位或运算, 将数据直接写到dat中
		if(DQ)
		{
			// dat		0000 0000
			// 0x80   1000 0000
			// 1000 0000
			
			// 右移一位
			// 0100 0000
			
			// dat		0100 0000
			// 0x80   1000 0000
			// 1100 0000
			// 0110 0000
			dat|=0x80;
		}
		delay(4); // 等待42us完成整个的读时序
	}
	return dat;
}

// 读取温度值
void readTemperature()
{
	while(Init_Ds18B20()); // 初始化
	writeOneChar(0xcc); // 跳过ROM读序列号的操作
	writeOneChar(0x44); // 命令DS18B20开始温度转化
	delay(124); // 等一会开始下一次的执行步骤
	while(Init_Ds18B20()); // 初始化
	writeOneChar(0xcc); // 跳过ROM读序列号的操作
	writeOneChar(0xbe); // 开始读暂存器的数据
	tempL = readOneChar(); // 读取温度值的低8位 LSB
	tempH = readOneChar(); // 读取温度值的高8位 MSB
	
	// 将读取到的温度值进行转化成实际温度
	// LSB 1111 1100
	// MSB 0000 0111
	// 0000 0111 0000 0000
	// 0000 0000 1111 1100
	// 0000 0111 1111 1100
	
	sdata = (float)(tempH << 8 | tempL) / 16.0; // 整数部分计算
	// 计算小数一位
	xiaoshu1 = (tempL&0x0f)*10/16;
	// 计算小数二位
	xiaoshu2 = (tempL&0x0f)*100/16%10;
}

void led()
{
	P2=0xfe;// 打开第一个数码管
	P0=arr1[sdata/10]; // 显示十位数
	P0=0xff;
	
	P2=0xfd;// 打开第二个数码管
	P0=arr2[sdata%10]; // 显示个位数
	P0=0xff;
	
	P2=0xfb;// 打开第三个数码管
	P0=arr1[xiaoshu1]; // 显示小数第一位
	P0=0xff;
	
	P2=0xf7;// 打开第四个数码管
	P0=arr1[xiaoshu2]; // 显示小数第二位
	P0=0xff;
}
void main()
{
	while(1)
	{
		readTemperature();
		led();
	}
}

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值