天天看点

蓝桥杯单片机组学习总结(一)

由于疫情的原因比赛被推迟,本人在家比较懒。。所以定期写一次总结以防学习的知识忘记,废话不多说,第一次总结开始!!

(一)温度传感器DS18B20

DS18B20有三个管脚,DQ为数字信号输入\输出端;GND为电源地;VDD为外供电电源输入端。

DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、温度报警触发器TH和TL、配置寄存器。光刻ROM作用其实就是使每一个DS18B20都各不一样,以便实现一根总线上挂接多个的目的。

DS18B20的核心就是它的直接读数字的温度传感器。上电默认精度为12位(0.0625),总线控制器发出[44h]命令后,温度数据以两个字节的形式被存储到温度寄存器中,DS18B20继续保持等待状态。

[cch]:忽略ROM指令,在单点总线情况下使用该命令,器件无需发回64位ROM编码,从而节省了时间。

[44h]:这条命令用以启动一次温度转换。

[BEH]:这条命令读取暂存器的内容,读取将从字节0开始。

DS18B20的驱动代码比赛中会给出,所以自己只需要写一个读温度函数就好。

unsigned char TemperGet()
{
	unsigned char low,high;
	unsigned char Temp;

	Init_DS18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay500us();
	Init_DS18b20();
	Write_DS18B20(0xcc);
 	Write_DS18B20(0xbe);
 	
 	low=Read_DS18B20();
 	high=Read_DS18B20();
	
	//读出温度不需要小数点
	temp=high<<4;
	temp=(low>>4)|temp;
	
	//需要小数点保留4位时
	//temp=(high&0x0f);
	//temp<<=8;
	//temp|=low;
	//temp=temp*625;
	
	return temp;
}
           

驱动代码里的init_ds18b20()函数可以改为(针对比赛)

void Init_DS18B20()
{
	DQ=0;
	Delay500us();
	DQ=1;
	Delay500us();
}
           

若温度读出结果为0,可将驱动代码中读写函数里的的Delay_OneWire()函数改用为Delay80us();

若读出温度带小数点的话,函数返回类型改为long型且主函数里分位显示要注意。for example 21.1625℃函数会返回211625。

(二)DS1302时钟芯片

蓝桥杯单片机组学习总结(一)

X1 X2为晶振管脚,CE复位管脚(读写期间必须为高),SCLK串行时钟,I/O(三线接口时的双向数据线)

对DS1302的操作就是对其内部寄存器的操作,DS1302内部共有12个寄存器,7个寄存器与日历、时钟相关,存放的数据为压缩BCD码。

蓝桥杯单片机组学习总结(一)

写保护寄存器的BIT7:WP是写保护位,工作时出WP外的其他位都置为0,对时钟/日历寄存器或RAM进行写操作之前WP必须为0,当WP为高电平时不能对时钟/日历寄存器或RAM进行操作。

DS1302驱动代码比赛中会给出,自己写的函数如下,

void DS1302_Init()
{
	unsigned char i,add;
	add=0x80;

	Write_DS1302(0X8E,0X00);
	for(i=0;i<7;i++)
	{
		Write_DS1302(add,shijian[i]);
		add+=2;
	}
	Write_DS1302(0X8E,0X80);
}
           
void DS1302_Get()
{
	unsigned char i,add;
	add=0x81;
	Write_DS1302(0X8E,0X00);
	for(i=0;i<7;i++)
	{
		shijian[i]=Read_DS1302(add);
		add+=2;
	}
	Write_DS1302(0X8E,0X80);
}
           

注意:定义一个数组shijian[]={50,59,23,0,0,0,0},用来写入初始时间和存储读出时间数据。

Write_Ds1302()函数中注意写入数据应该变成((dat/10<<4)|(dat%10))。

Read_DS1302函数应注意返回的temp值应该分位处理,dat1=temp/16;dat2=temp%16;temp=dat1*10+dat2;

(三)PCF8591(8位A/D和D/A转换器)

PCF8591具有4个模拟输入(四路采集)、1个模拟输出(数模转换)和一个串行I2C总线接口。采用I2C总线串行输入/输出,采样速率取决于I2C总线速度。

AIN0、AIN1、AIN2、AIN3为模拟输入(analog inputs)引脚,A0、A1、A2用于编程硬件地址,允许将最多8个器件连接至I2C总线而不需要额外硬件。器件的地址、控制和数据通过两线双向I2C总线传输。

蓝桥杯单片机组学习总结(一)
蓝桥杯单片机组学习总结(一)

地址:I2C总线系统中的每一片PCF8591通过发送有效地址到该器件来激活,该地址包括固定部分和可编程部分。可编程部分必须根据地址引脚 A0、A1 和A2 来设置。在 I2C 总线协议中地址必须是起始条件后作为第一个字节发送。地址字节的最后一位是用于设置以后数据传输方向的读/写位,1读0写。

蓝桥杯单片机组学习总结(一)
蓝桥杯单片机组学习总结(一)

可以看到PCF8591芯片A0-A2全部接地,所以写操作时地址为0x90,读操作时地址为0x91.

控制字: 发送到 PCF8591 的第二个字节将被存储在控制寄存器,用于控制器件功能。如果是DA转换则第二位置1,AD转换第二位置0,三四位控制差分模式,此板子为00,第六位控制自动增量模式,一般不用置0,最后两位控制AD采集通道。

蓝桥杯单片机组学习总结(一)

IIC驱动代码比赛会给出,自己写的函数如下:

unsigned char AD_Read(unsigned char add)
{
	unsigned char temp;

	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WateAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
 	IIC_WaitAck();
 	temp=IIC_RecByte();
 	IIC_Stop();
 	
	return temp;
}
           
void AD_Write(unsigned char add,unsigned char dat)
{
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
 	 IIC_SendByte(add);
	 IIC_WateAck();
	 IIC_SendByte(dat);
 	 IIC_WateAck();
	 IIC_Stop();
}
           

有时候AD输出不准确时可以把驱动代码里的延时函数换成Delay6us().

四)二线制串行EEPROM-24c02

AT24C02是低工作电压的2K位串行电可擦除只读存储器,内部组织为256个字节每个字节8位。

板子上如图:

蓝桥杯单片机组学习总结(一)

板子上只搭载了一个AT24C02,其外设地址为0XA0。A0-A2引脚作用是器件地址输入,SDA为串行数据输入输出,SCL为串行时钟输入,WP为写保护,VCC电源,GND接地。

IIC驱动代码比赛给出,下面是需要写的函数,基本与AD转换函数一致:

void EEPROM_Write(unsigned char add,unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	 IIC_WaitAck();
	 IIC_SendByte(add);
	 IIC_WaitAck();
 	IIC_SendByte(dat);
 	IIC_WaitAck();
 	IIC_Stop();
}

unsigned char EEPROM_Read(unsigned char add)
{
	unsigned char temp;

	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();

 	IIC_Start();
 	IIC_SendByte(0xa1);
 	IIC_WaitAck();
 	temp=IIC_RecByte();
 	IIC_Stop();	

	return temp;
}
           

(五)超声波模块

采用HC-SR04超声波测距模块。

蓝桥杯单片机组学习总结(一)

VCC供5V电源,GND为地线,TRIG触发控制信号输入,ECHO回响信号输出。

蓝桥杯单片机组学习总结(一)
蓝桥杯单片机组学习总结(一)

板子上用跳线帽将13,24连起来了,所以P10口对应着TRIG,P11口对应着ECHO。超声波时序图如下:

蓝桥杯单片机组学习总结(一)

以上时序图表明你只需要提供一个10us以上的脉冲触发信号,该模块内部将发出8个40khz周期的电平并检测回波,一旦有回波信号则输出回响信号,可以通过发射信号到收到回响信号的时间间隔可计算得到距离。可以通过定时器来完成时间采集。

废话不多说上代码:

void Timer0Init()//初始化定时器,测距前先调用。
{
	TMOD|=0X00;
	TH1=0;
	TL1=0;
}

void ShengBo_Distance()//需要定义全局变量Distance
{
	uchar i,time;
	for(i=0;i<8;i++)
	{
		Trig=1;
		Delay12us();
		Trig=0;
		Delay12us();
	}

	TR1=1;//定时器启动
	while((Echo==1)&&(TF1==0));//等待回响信号(Echo检测到下降沿)或定时器溢出
	TR1=0;//关闭定时器
	
	if(TF1==0)
	{
		time=TH1;
		time=(time<<8)|TL1;
		Distance=time*17/1000;
	}
	else
	{
		TF1=0;
		Distance=99;
	}
	TH1=0;TL1=0;
}
           

(六)NE555方波发生器

原理图如下:

蓝桥杯单片机组学习总结(一)
蓝桥杯单片机组学习总结(一)

NE555N只留下了NET_SIG,用跳线帽将P34(定时器0引脚)和其连接。信号频率大小可以通过Rb3可调电位器改变。

需要用到两个定时器,定时器0计数定时器1定时。

void Timer0Init()
{
	AUXR|=0X80;
	TMOD|=0X05;
	TL0=0X00;
	TH0=0X00;
	TRO=0;
	TF0=0;
	ET0=0;
}

void Timer1Init(void)  //2毫秒@11.0592MHz
{
	 AUXR |= 0x40;  //定时器时钟1T模式
	 TMOD &= 0x0F;  //设置定时器模式
	 TL1 = 0x9A;  //设置定时初值
	 TH1 = 0xA9;  //设置定时初值
	 TF1 = 0;  //清除TF1标志
	 TR1 = 1;  //定时器1开始计时
	 ET1 = 1;
}

void 	timer1() interrupt 3
{
	if(Time==0)//变量Time主函数中定义
	{
		TR0=1;
		Time++;
	}
	else if(ALLTime<1000)
	{
		Time++;
	}
	else//2s到了
	{
		Time=0;
		TR0=0;
		FreqCnt=((uint)TH0<<8)|((uint)TL0)/2;
		TH0=0;
		TL0=0;
	}
}