2019-10-29 22:38:50 weixin_45761362 阅读数 149
  • 温度传感器DS18B20-第2季第1部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第1个课程,主要讲解单片机系统中常用的温度传感器DS18B20。本课程的目标是让大家进一步掌握时序的分析和编程实现,学会移植和调试DS18B20的程序,能够读取温度。

    2173 人正在学习 去看看 朱有鹏

51单片机总结—— DS18B20数字温度传感器

单总线时序和注意事项:
单总线信号类型:复位脉冲、存在脉冲、写0、写1、读0、读1。所有这些信号除存在脉冲由DS18B20发出的以外其他信号都由总线控制器发出。
数据传输总是从最低有效位开始
电路连接图示

执行序列
通过单线总线端口访问DS18B20的协议如下:
步骤1. 初始化
步骤2. ROM操作指令
步骤3. DS18B20功能指令
温度转换命令
读取暂存器命令

电路连接图示
在这里插入图片描述
程序中使用:
在这里插入图片描述
**

程序内容:

初始化时序
初始化时序里面包含了复位DS18B20和接收DS18B20返回的存在信号。
主机和DS18B20做任何通讯前都需要对其初始化。初始化期间,总线控制器拉低总线并保持480us以上挂在总线上的器件将被复位,然后释放总线,等到15-60us,此时18B20将返回一个60-240 us之间的低电平存在信号。
复位脉冲和存在脉冲时序图
在这里插入图片描述
程序中使用:
在这里插入图片描述
写时序:
写时序分为写0时序和写1时序。
总线控制器通过控制单总线高低电平持续时间从而把逻辑1或0写DS18B20中。
总线控制器要产生一个写时序,必须将总线拉低最少1us,产生写0时序时总线必须保持低电平60~120us之间,然后释放总线,产生写1时序时在总线产生写时序后的15us内允许把总线拉高。注意:2次写周期之间至少间隔1us。
在这里插入图片描述
程序中的使用:
在这里插入图片描述
读时序:
读时序分为读0时序和读1时序。
总线控制器通过读取由DS18B20控制的总线高低电平接收DS18B20数据。
总线控制器要产生一个读时序,必须将总线拉低至少1us,然后释放总线,在读信号开始后15us内总线控制器采样总线数据,读一位数据至少保持在60us以上。注意:2次读周期之间至少间隔1us。
在这里插入图片描述
程序中的使用:
在这里插入图片描述
主函数内容配置
DS18B20暂存器
在这里插入图片描述
在这里插入图片描述
配置寄存器图表
在这里插入图片描述
DS18B20功能指令:
温度转换指令(44h)
这条命令用以启动一次温度转换。温度转换指令被执行,产生的温度转换结果数
据以2个字节的形式被存储在高速暂存器中,而后DS18B20保持等待状态。
读暂存器指令(BEh)
这条命令读取暂存器的内容。读取将从字节0 开始,一直进行下去,直到读完暂存
器所有字节,如果不想读完所有字节,控制器可以在任何时间发出复位命令来中止
读取。
写暂存器指令(4Eh)
这条命令向DS18B20 的暂存器写入数据,开始位置在TH 寄存器(暂存器的第2
个字节),接下来写入TL 寄存器(暂存器的第3 个字节),最后写入配置寄存器
(暂存器的第4 个字节)
拷贝暂存器指令(48h)
这条命令把TH,TL 和配置寄存器(第2、3、4 字节)的内容拷贝到EEPROM 中。

程序中的使用(用在主函数中):
在这里插入图片描述
程序实现:
#include <reg52.h>
#include <intrins.h>
#define MAIN_Fosc 11059200UL //宏定义主时钟HZ
//自定义类型名
typedef unsigned char INT8U;
typedef unsigned char uchar;

typedef unsigned int INT16U;
typedef unsigned int uint;

//硬件接口位声明
sbit DS = P2^2; //DS18B20单总线
sbit du = P2^6; //数码管段选
sbit we = P2^7; //数码管位选

void Display(INT16U Value);

//共阴极数码管段选码
uchar code table[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //不带小数点0-9
//数码管位选码
uchar code T_COM[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//第1,2,3,4,5,6,7,8位

void Delay_Ms(INT16U ms) //毫秒延时
{
INT16U i;
do{
i=MAIN_Fosc/96000;
while(–i); //96T per loop
} while(–ms);
}
//us延时函数,执行一次us–需要6.5us,进入一次函数需要11.95us
void Delay_us(uchar us)
{
while(us–);
}

/单总线初始化时序/
bit ds_init()
{
bit i;//声明一个变量存储(返回的信号值)
DS = 1;//总线置于高电平
nop();//空指令延时?
DS = 0;//拉低总线480us以上
Delay_us(75); //499.45us,挂接在总线上的18B20将会全部被复位
DS = 1;//释放总线
Delay_us(4);//15~60us,延时37.95us,等待18B20发回存在信号
i = DS;//(0 or 1)
Delay_us(20);//60~240us, 141.95us
DS = 1;//释放单总线
nop();//延时等稳定
return (i);//若1=0,则DS1802存在在总线上,并且准备好了,可以对其操作
}
/写一个字节,写时序/
void write_byte(uchar dat)//把要写的数据赋给形参dat,然后传递进来(一次一个字节,要循环八次)
{
uchar i;
for(i=0;i<8;i++)
{
DS = 0; //拉低总线
nop();//小延时,产生写时序
DS = dat & 0x01;//数据传输总是从最低有效位开始的,在这里即是从数据的最低位开始(eg:00000001&00000001=00000001 00000000&00000001=00000000)
Delay_us(10);//写0时序,低电平保持60~120us,写1时序,60us以上,此处延时76.95us,同时满足0和1
DS = 1;//释放总线,准备下一次写入数据
nop(); //延时大于1us即可
dat >>= 1;//写入第一个数据以后,dat右移一位(此处为何右移,明白了,使第二位,三位。。。挪到一位与1&)
}
}
/读一个字节/
uchar read_byte()
{
uchar i,j,dat;//循环变量,存储每读一位时用到的变量,存储一个字节的变量
for(i=0;i<8;i++)
{
DS = 0;//拉低单总线
nop();//小延时,此处要求1us,产生读时序
DS = 1;
nop();//释放总线
j=DS;//用j获取DS上的值
Delay_us(10);//76.95us,此处要求60us以上
DS = 1;
nop();//释放总线,又把总线交给从机DS180控制,方便下一次数据的读取
dat = (j<<7)|(dat>>1);//j左移七位,就将字节的最低位,移到了最高位,与上dat右移一位,把j的最高位写入dat最高位,依次
}
return (dat);//读字节

}

void main()
{
uint i; //温度两个字节
uchar L,M;//存取温度的低字节和高字节
while(1)
{
ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x44);//发送温度转换指令
ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0xbe);//读取DS18B20暂存器值
L = read_byte();//读第一个字节
M = read_byte();//读第二个字节,只读两个字节是因为只需要知道温度值
/若为负温度时
M=0xfc;
L=0x90;
i=M;
i<<=8;
i|=L;
if(M>=0x08) //判断是否为负数
{
i=~i+1; //负数是以补码的形式存放的需要我们需要取反加一
s=0x40; //显示负数符号
}
else s=0;//为正数则不显示
temp=i
0.062510000;//浮点型数据转换
Display(temp);
/

	i = M;
	i<<=8;//左移八位,将M放到i的高八位
	i |=L;//把L写入i的低八位
	i = i * 0.0625 * 10 + 0.5;//将二进制换算成实际温度,10是为了保留小数点后一位,到时候在数码管上手动加小数点,0.5是为了四舍五入
	Display(i);
}

}
void Display(INT16U Value) //由于需要显示的数大于一个字节,所有形参需为int
{
du=0;//关闭段选
P0=table[Value/100]; //数码管显示百位
du=1; //打开段选
du=0; //关闭段选

we=0;	 //关闭位选
P0=T_COM[0];		   //选择第一位数码管
we=1;  //打开位选
Delay_Ms(3);



du=0;//关闭段选
P0=table[Value%100/10]|0x80; //数码管显示十位
du=1;	//打开段选
du=0;	//关闭段选

we=0;	 //关闭位选
P0=T_COM[1];		   //选择第二位数码管
we=1;  //打开位选
Delay_Ms(3);



du=0;//关闭段选
P0=table[Value%10]; //数码管显示个位
du=1;	//打开段选
du=0;	//关闭段选

we=0;	 //关闭位选
P0=T_COM[2];		   //选择第三位数码管
we=1;  //打开位选
Delay_Ms(3);

}

附表
在这里插入图片描述
谢谢!

2019-06-14 17:01:00 weixin_31301271 阅读数 60
  • 温度传感器DS18B20-第2季第1部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第1个课程,主要讲解单片机系统中常用的温度传感器DS18B20。本课程的目标是让大家进一步掌握时序的分析和编程实现,学会移植和调试DS18B20的程序,能够读取温度。

    2173 人正在学习 去看看 朱有鹏

1.首先单片机AD是多少位的,比如n位,那么单片机AD的最大值是2^n-1;

2.串接传感器的电阻为R,传感器的电阻为Rc

3.AD的值: val = (Rc/(R+Rc))*2^n;

4.根据供应商提供的温度和电阻的匹配表,进行计算。温度和电阻一般为非线性的,所以一般会用查表法来查找温度值(精度要求不高的情况下)。

 

8位单片机ram很小,把你要查的数据设成 const,  别设成valitile,不然ram肯定不够。

查找数据的时候用二分法会比较快。

有的人为节省空间,会把AD值的低位舍弃。

最后可以把写好的程序用可变电阻实测一遍,把偏差较大的数值进行修改。

2019-03-09 22:11:00 weixin_33708432 阅读数 116
  • 温度传感器DS18B20-第2季第1部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第1个课程,主要讲解单片机系统中常用的温度传感器DS18B20。本课程的目标是让大家进一步掌握时序的分析和编程实现,学会移植和调试DS18B20的程序,能够读取温度。

    2173 人正在学习 去看看 朱有鹏
技术:51单片机、Arduino、光敏传感器、PCF8591、AD/DA转换
 

概述

本文介绍了如何接收传感器的模拟信号和如何使用PCF8591 AD/DA转换模块对光敏传感器的模拟信号进行转换。讲述了51单片机和Arduino如何读取模拟信号,并通过串口实时显示出来。

详细

一、光敏传感器

1545624326555030055.png光敏传感器是利用光敏元件将光信号转换为电信号的传感器,它的敏感波长在可见光波长附近,包括红外线波长和紫外线波长。光传感器不只局限于对光的探测,它还可以作为探测元件组成其他传感器,对许多非电量进行检测,只要将这些非电量转换为光信号的变化即可。光敏传感器中最简单的电子器件是光敏电阻,它能感应光线的明暗变化,输出微弱的电信号,通过简单电子线路放大处理,可以控制LED灯具的自动开关。

 

模块使用说明

 

  • 光敏电阻模块对环境光线最敏感,一般用来检测周围环境的光线的亮度,触发单片机或继电器模块等;

  • 模块在环境光线亮度达不到设定阈值时,DO 端输出高电平,当外界环境光线亮度超过设定阈值时,DO端输出低电平;

  • DO 输出端可以与单片机直接相连,通过单片机来检测高低电平,由此来检测环境的光线亮度改变;

  • 小板模拟量输出 AO 可以和 AD 模块相连,通过 AD 转换,可以获得环境光强更精准的数值.

二、C51单片机串口显示光照强度

光敏传感器的AO引脚输出的是模拟信号,而51单片机内部没有AD/DA转换器,不能接收模拟信号,只能接收到数字信号,所以我们需要一个能够进行AD/DA转换的模块,这里我选择了PCF8591模块来进行AD转换。

1545625014533085926.pngPCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591 具有 4 个模拟输入、1 个模拟输出和 1个串行 I2C 总线接口。PCF8591 的 3 个地址引脚 A0, A1 和 A2 可用于硬件地址编程,允许在同个 I2C 总线上接入8个PCF8591 器件,而无需额外的硬件。在 PCF8591 器件上输入输出的地址、控制和数据信号都是通过双线双向 I2C 总线以串行的方式进行传输。(简单的说:可以实现4路 模拟输入,1路模拟输出,具体功能看模块使用说明)

硬件连接: 图片3.png

PCF8591的使用会涉及到I2C总线,程序中也要加入对I2C的操作,Pcf8591SendByte()来选择使用PCF8591 模块的哪一路输入(这里选择AIN0)

void Pcf8591SendByte(uchar channel)
{   
    I2C_Start();    //开始I2C总线
    I2C_SendByte(WRITEADDR);        //发送写器件地址
    I2C_SendByte(0x40|channel);     //发送控制寄存器
    I2C_Stop();
}
 
uchar Pcf8591ReadByte()    //读取值
{
    uchar num;
    I2C_Start();
    I2C_SendByte(READADDR);      //发送读器件地址
    num=I2C_ReadByte();          //读取数据
    I2C_Stop();                  //结束总线
    return num;
}
 
void main()
{
    uint adNum;
    float value;
    UsartInit(); 
    while(1)
    {    
        Pcf8591SendByte(0);      //使用通道0   (可选择通道0-3)光敏传感器A0连接PCF8591传感器的AIN0
        /*adNum一定是0到255之间的一个数,因为pcf8591是8位的AD/DA芯片,所以输出的范围为00000000
          到11111111,即0到255*/
        adNum=Pcf8591ReadByte();   //读出数值
        value = adNum;
        value=100.0 - value*100.0/255.0; //把光敏值转换为0-100的数值,这里255.0可更改
                                         //(根据实际测试value最暗值)
        printf("light:");        
        printf("%.2f\n",value);    //打印数据到串口
        delay1s();
    }
}

打开串口调试助手,获取光照强度值:

1545625249470004185.png

三、Arduino串口显示光照强度

Arduino内部有AD/DA转换器,所以接收模拟信号会变得非常容易操作。

硬件连接: 图片5.png

代码如下:

#define light A5   //定义模拟口A5
float Intensity = 0;//光照度数值
 
void setup()  //初始化
{
  Serial.begin(9600);//设置波特率9600
}
 
void loop()//程序主体循环
{
  Intensity = analogRead(light);  //读取模拟口AD5的值,存入Intensity变量
  //Intensity = 100.0 - Intensity / 6.7;//VCC接3.3V时,Intensity最高为670,最低为0
  Intensity = 100.0 - Intensity / 10.23;//VCC接5V时,Intensity最高为1023,最低为0
  Serial.print("Intensity = ");  //串口输出"Intensity = "
  Serial.print(Intensity);       //串口输出Intensity变量的值
  Serial.print("%\n");  
  delay(1000);     //延时1s
}

 

串口读取到的光照强度值如下图:

1545625406996032991.png

四、总结

本文实现51单片机和Arduino串口显示光照强度,介绍了光敏传感器和PCF8591 AD/DA转换模块的使用方法,如果你对模拟信号和数字信号还不怎么了解,我建议你先去学下。学完了这个,建议去读取其他传感器的模拟信号,具体实现方法是一样的。

五、项目结构图

图片7.png

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

转载于:https://www.cnblogs.com/demodashi/p/10503375.html

2019-08-21 11:39:49 qq_44790423 阅读数 246
  • 温度传感器DS18B20-第2季第1部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第1个课程,主要讲解单片机系统中常用的温度传感器DS18B20。本课程的目标是让大家进一步掌握时序的分析和编程实现,学会移植和调试DS18B20的程序,能够读取温度。

    2173 人正在学习 去看看 朱有鹏

那我们现在就开始来学习我们的振动传感器


振动传感器

电路原理图如下:

原理:
管内有一跟固定的导线,在这根导线的周围有另一根较细的导线以螺旋状环绕它。可以想象为一个弹簧旁边有一跟导线。在不振动时,两根导线不会相碰,一旦振动发生,两根导线就会短接。所以我们只需判断导线是否短接了,就可以知道振动是否发生

检测方法
而如果要检测它是否能够使用,可设置与LED的使用,
即当轻敲振动传感器时,发光二极管L0-L7依次点亮。当振动传感器没有振动时,发光二极管L7-L0全灭


振动声光报警器

实验现象
通过振动实验板来控制无源蜂鸣器的发声和灯光的闪烁来达到报警的功能;报警产生后,通过按下按键key1来控制报警器的关闭

实验原理
即同时使用振动传感器与蜂鸣器,参照前面学过的即可

芯片引脚图:
在这里插入图片描述

代码解析
设计流程图如下:
在这里插入图片描述

流水灯,蜂鸣器,按键检测等部分前面提到过就不多做阐述

定义部分变量

uchar flag=1;                            //振动标志位
ucharcodetable[]=
{0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff}; 
//流水灯报警闪烁数组 

定时器中断

void timer0() interrupt 1
{
  beep=~beep;                      //beep翻转产生方波
}
2019-02-08 14:13:27 qq_42908042 阅读数 912
  • 温度传感器DS18B20-第2季第1部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第1个课程,主要讲解单片机系统中常用的温度传感器DS18B20。本课程的目标是让大家进一步掌握时序的分析和编程实现,学会移植和调试DS18B20的程序,能够读取温度。

    2173 人正在学习 去看看 朱有鹏

前言:之前一篇博客介绍了环境光传感器通过ADC的方式采集单通道的数据,现在介绍一下DMA方式采集多通道的数据。不过使用的是声音传感器,基本原理一样。
1.首先打开ADC1的两个通道IN11,IN12。使能两个通道。
在这里插入图片描述
2.ADC1配置:使能扫描转换模式(Scan Conversion Mode),使能连续转换模式(Continuous Conversion Mode),使能DMA连续请求。ADC规则组选择转换通道数为2(Number Of Conversion)。其他为默认设置。
在这里插入图片描述
3.打开中断。
在这里插入图片描述
4.添加DMA设置,设置为连续传输模式,数据长度为字。
在这里插入图片描述
5.端口通道配置完成在这里插入图片描述
6.时钟配置。在这里插入图片描述
7.项目管理。在这里插入图片描述
在这里插入图片描述
8.生成报告以及代码,编译程序。在adc.c文件中可以看到ADC初始化函数。在main函数前面添加变量。其中ADC_volume作为转换数据缓存数组,ad1,ad2存储PA6,PA7的电压值。

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint32_t ADC_volume[100];
uint8_t i;
uint32_t ad1,ad2;
/* USER CODE END PV */

9.在while(1)前面以DMA方式开启ADC转换。HAL_ADC_Start_DMA()函数第二个参数为数据存储的起始地址,第三个参数为DMA传输数据的长度。

 /* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_volume,100);
  /* USER CODE END 2 */

由于DMA采用了连续传输的模式,ADC采集到的数据会不断传到到存储器中(此处即为数组ADC_volume)。ADC采集的数据从ADC_volume[0]一直存储到ADC_volume[99],然后采集到的数据又重新存储到ADC_volume[0],一直到ADC_volume[99]。所以ADC_volume数组里面的数据会不断被刷新。这个过程中是通过DMA控制的,不需要CPU参与。我们只需读取ADC_volume里面的数据即可得到ADC采集到的数据。
其中ADC_volume[0]为通道6(PA6)采集的数据,ADC_volume[1]为通道7(PA7)采集的数据,ADC_volume[2]为通道6采集的数据,如此类推。数组偶数下标的数据为通道6采集数据,数组奇数下标的数据为通道7采集数据。

10.在while(1)循环中添加应用程序,将采集的数据装换为电压值并输出。

 /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		    HAL_Delay(500);
        for(i = 0,ad1 =0,ad2=0; i < 100;)
        {
            ad1 += ADC_volume[i++];
            ad2 += ADC_volume[i++];
        }
        ad1 /= 50;
        ad2 /= 50;
 
        printf("\r\n******** ADC DMA Example ********\r\n\r\n");
        printf(" AD1 volume = %1.3fV \r\n", ad1*3.3f/4096);
        printf(" AD2 volume = %1.3fV \r\n", ad2*3.3f/4096);
				HAL_Delay(1000);
  }
      /* USER CODE END 3 */

程序中将数组偶数下标数据加起来求平均值,实现均值滤波的功能,再将数据转换为电压值。
11.编译程序并下载到开发板。打开串口调试助手。设置波特率为115200.串口助手上会显示声音对应的电压值。现象如下:
在这里插入图片描述

没有更多推荐了,返回首页