蓝桥杯单片机学习笔记03

1.单总线温度传感器DS18B20的基本操作

DS18B20温度模块使用单总线,只有一个数据口,与单片机P14相连。

1.关于DS18B20你应该知道

        在DS18B20的内部结构中,有一块高速暂存存储器,用于总线的数据交互。高速暂存存储器由9个字节组成,当温度转换命令发布后,经转换所得的温度值以二字节补码的形式存放在高速暂存存储器的第0和第1个字节,单片机可通过单线接口可以读取到该数据,读取时低位在前,高位在后。

       通过单线总线端口访问DS18B20操作流程如下:

        1.初始化:从机复位,主机判断从机是否响应。

        2.ROM操作:ROM指令+本指令需要的读写操作。

        3.功能操作:功能指令+本指令需要的读写操作。

        DS18B20单线通信功能是分时完成的,它有严格的时隙概念,如果出现序列混乱,器件将不响应主机,因此读写时序很重要。下面分别对其进行介绍:

1.1.1初始化

        主机将总线拉低至少480us,然后释放总线,等待15-60us后,存在的从机将会拉低总线60-240us以响应主机,之后从机将释放总线。

        底层驱动代码如下:

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(120);
  	DQ = 0;
  	Delay_OneWire(800);
  	DQ = 1;
  	Delay_OneWire(100); 
    initflag = DQ;     
  	Delay_OneWire(50);
  
  	return initflag;
}

1.1.2发送一位

        主机将总线拉低60-120us,然后释放总线,表示发送0;主机将总线拉低1-15us,然后释放总线,表示发送1。从机将在总线拉低30us后读取电平,整个时间片应大于60us。

        发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)。底层驱动代码如下:

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(50);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(50);
}

1.1.3接收1位

        主机将总线拉低1-15us,然后释放总线,并在拉低后15us内读取总线电平,读取为低电平则为接收0,读取为高电平则为接收1,整个时间片选应大于60us。

        接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)。底层驱动代码如下:

//从DS18B20读取一个字节
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(50);
	}
	return dat;
}

2.重要的DS18B20指令

1.CCH:跳过ROM指令,直接向DS18B20发起各种温度转换指令。

2.44H:温度转换指令,启动DS18B20进行温度转换,结果保存在高速RAM中。

3.BEH:读暂存器指令,读取高速暂存存储器9个字节的内容。

3.读取1次DS18B20温度的基本操作

1.主机对DS18B20进行复位初始化。

2.主机向DS18B20写0XCC命令,跳过ROM。

3.主机向DS18B20写0X44命令,开始进行温度转换。

4.等待温度转换完成。

5.主机对DS18B20进行复位初始化。

6.主机向DS18B20写0XCC命令,跳过ROM。

7.主机向DS18B20写0XBE指令,依次读取DS18B20发出的第0-8,共9个字节的数据。

具体代码如下:

unsigned long Temp_get(void)
{
	unsigned char low,high;
	unsigned long  temp;
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0X44);
	Delay_OneWire(200); 
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0XBE);

	low=Read_DS18B20();
	high=Read_DS18B20();
	
//精度为0.0625摄氏度   
	temp = (high&0x0f);
	temp <<= 8;
	temp |= low;
	
	return temp;
}

        因为我们只需要读取温度数据,所以我们在读完第0个和第1个数据后就不再读取DS18B20发出的数据。

        高字节的5个S为符号位,温度为正值时S=1,温度为负值时S=0;剩下的11位为温度数据位。

        当温度为正值时,直接将后面的11位二进制数转换为十进制,再乘以0.0625(12位分辨率),就可以得到温度值。

温度存储格式

2.实时时钟DS1302的基本操作

        DS1302时钟芯片的接线为SCLK,IO,RST三线,分别与单片机的P17,P23,P13相连。

1.什么是DS1302

        DS1302是美国DALLAS公司推出的高性能、低功耗的实时时钟,附加31字节的静态RAM,采用SP三线接口与MCU进行同步通信,并可采用突发方式一次传送多个字节的时钟参数和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小于31天时可以自动调整,并具有润年补偿功能。
        简单来说,DS1302可以理解为一个电子手表,里面带有一个31字节的内存。当然,基本的使用方法和我们平时使用电子手表差不多,你可以设定时间,也可以读取时间,只不过这些工作是通过SPI接口有MCU去完成而已。
        在DS1302中有两块存储器:日历时钟寄存器和今天RAM存储器。前者用于记录实时时间,后者用于记录其他数据。对于基本计时应用,重点关注的是日历时钟寄存器。设定时间参数就是往这些寄存器写入内容,读取实时时间也是从这些寄存器读出数据。

        在程序的最开始首先对需要用到的位变量进行定义,此外还定义了一个存储时间的全局变量Get_Time[i]。具体代码如下:

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位			

extern unsigned char Get_Time[7];
extern unsigned char Time_Set[7];

2.日历时钟寄存器

DS1302有关日历和时钟的寄存器有12个,我们最常用的有7个。

什么是BCD码?
就是用十六进制来表示十进制。什么意思?怎么理解?
例如,十六进制数0x13的值为整数19,但BCD码表示的是整数13

3.控制字的格式

DS1302将地址和读写控制放到一个字节里面,形成一个控制字,格式如下:

DS1302将地址和读写控制放到一个字节中,形成一个控制字,由于控制字中包含了读写控制位,所以DS1302读寄存器和写寄存器的地址是不一样的。

4.接口时序的实现

DS1302的基本操作只有两个:其一是设定时间参数,其二是读取实时时间。不管是哪个操作,MCU都需要通过SPI接口进行数据交互,而SPI接口有其规定的时序。

控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟信号的上升沿,数据被写入DS1302,数据的输入从最低位开始;在控制字指令输入后的下一个SCLK时钟信号的下降沿,数据从DS1302读出,数据的读出也是从最低位到最高位。下面分别对其进行介绍。

2.4.1单字节写的时序

底层驱动代码如下:

        函数第一个参数表示操作指令,第二个参数表示待写入的数据,两个8位数据从低位一次一位一位的通过I/O引脚写入DS1302。

2.4.2单字节读的时序

底层驱动代码如下:

函数的参数是操作指令,返回值为读取到的数据。

有了上面两个底层的SPI接口数据读写代码,那么DS1302的基本操作就很容易实现了。

2.4.3设置时间与读取时间函数

在实际调用上面两个函数时,指令实参一般是DS1302中写寄存器和读寄存器的地址,数据实参一般是数组中的元素。具体代码如下:

        由于时间在DS18B20芯片中是以BCD码的形式存储的,而在数组中的元素是十进制,所以我们要把十进制转化为BCD码再写入DS1302,读取时间则反过来把BCD码转化为十进制。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
数码管是一种常见的数字显示器件,可以用于显示各种数字、字母等字符。在单片机应用中,数码管通常用于显示计数器、计时器、温度、湿度等实时数据。 数码管的种类有很多,包括共阳数码管、共阴数码管、共阳共阴混合数码管等。其中,共阳数码管是最常见的一种,也是本文所涉及的数码管类型。 单片机控制数码管的原理是通过对数码管的各个管脚进行控制,使其显示相应的数字或字符。数码管的控制方式有两种,即静态显示和动态显示。 静态显示是指将要显示的数字或字符的每一位分别输出到数码管的每个管脚上,然后使其保持不变,从而实现显示效果。静态显示的缺点是需要使用大量的I/O口,且不能灵活地改变显示内容。 动态显示是指将要显示的数字或字符的每一位依次输出到数码管的每个管脚上,并在短时间内快速切换下一个数字或字符,从而形成连续的显示效果。动态显示的优点是可以使用较少的I/O口,且可以灵活地改变显示内容。 以下是一个简单的动态显示数码管的实现示例: 1. 定义数码管的引脚 ```c #define DIG_PORT P2 // 数码管位选端口 #define DIG_COM 0x00 // 数码管位选端口初始值 #define LED_PORT P0 // 数码管段选端口 ``` 2. 定义数码管显示的数字或字符 ```c unsigned char code ledChar[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; ``` 3. 实现数码管动态显示函数 ```c void display(unsigned char i) { unsigned char j, k; for (j = 0; j < 8; j++) { DIG_PORT = DIG_COM | (1 << j); // 选择数码管位(从左到右) for (k = 0; k < 100; k++); // 延时,视情况可调整 LED_PORT = ledChar[i]; // 显示数码管上的数字或字符 } } ``` 4. 调用数码管动态显示函数 ```c int main() { unsigned char i = 0; while (1) { display(i % 10); // 显示数字 i 的个位数 i++; } return 0; } ``` 以上就是一个简单的数码管动态显示的实现示例。需要注意的是,数码管的控制方式和具体实现方法可能因不同的硬件平台和编程语言而有所不同。因此,在具体应用中需要根据实际情况进行适当的调整和修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值