实验

下载程序后,插上DS18B20温度传感器,数码管显示检测的温度值,与PZ-HC05蓝牙进行配对,打开手机APP,采集的温度数据上传到手机APP显示。

main.c

# include "public.h"
# include "bluetooth.h"

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	bluetooth_control_init();

	while(1)
	{				
		bluetooth_control();	
	}		
}

smg.c(数码管)

# include "smg.h"


u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void smg_display(u8 dat[],u8 pos)
{
	u8 i=0;
	u8 pos_temp=pos-1;
	
	for(i=pos_temp;i<8;i++)
	{
		switch(i)
		{
				case 0:A0=1;A1=1;A2=1;break;//Y7//板子从左边数第一个数码管,下面以此类推
				case 1:A0=0;A1=1;A2=1;break;//Y6
				case 2:A0=1;A1=0;A2=1;break;//Y5
				case 3:A0=0;A1=0;A2=1;break;//Y4
				case 4:A0=1;A1=1;A2=0;break;//Y3
				case 5:A0=0;A1=1;A2=0;break;//Y2
				case 6:A0=1;A1=0;A2=0;break;//Y1
				case 7:A0=0;A1=0;A2=0;break;//Y0
		}
			SMG_A0_F_PORT=dat[i-pos_temp];//传送段选数据
			delay_10us(100);//延时1毫秒左右
			SMG_A0_F_PORT=0x00;//消影
	}
}

smg.h

# ifndef _smg_H
# define _smg_H

# include "public.h"

sbit A0=P2^2;
sbit A1=P2^3;
sbit A2=P2^4;
# define SMG_A0_F_PORT P0//宏定义数码管P0端口
extern u8 gsmg_code[17];  //注意要加extern 

void smg_display(u8 dat[],u8 pos);
# endif

ds18b20.c(温度传感器)

# include "ds18b20.h"
# include "intrins.h"

/*******************************************************************************
* 函 数 名         : ds18b20_reset
* 函数功能		   : 复位DS18B20  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void ds18b20_reset(void)
{
	DS18B20_PORT=0;	//拉低DQ
	delay_10us(75);	//拉低750us
	DS18B20_PORT=1;	//DQ=1
	delay_10us(2);	//20US
}

/*******************************************************************************
* 函 数 名         : ds18b20_check
* 函数功能		   : 检测DS18B20是否存在
* 输    入         : 无
* 输    出         : 1:未检测到DS18B20的存在,0:存在
*******************************************************************************/
u8 ds18b20_check(void)
{
	u8 time_temp=0;

	while(DS18B20_PORT&&time_temp<20)	//等待DQ为低电平
	{
		time_temp++;
		delay_10us(1);	
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	else time_temp=0;
	while((!DS18B20_PORT)&&time_temp<20)	//等待DQ为高电平
	{
		time_temp++;
		delay_10us(1);
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	return 0;
}

/*******************************************************************************
* 函 数 名         : ds18b20_read_bit
* 函数功能		   : 从DS18B20读取一个位
* 输    入         : 无
* 输    出         : 1/0
*******************************************************************************/
u8 ds18b20_read_bit(void)
{
	u8 dat=0;
	
	DS18B20_PORT=0;
	_nop_();_nop_();
	DS18B20_PORT=1;	
	_nop_();_nop_(); //该段时间不能过长,必须在15us内读取数据
	if(DS18B20_PORT)dat=1;	//如果总线上为1则数据dat为1,否则为0
	else dat=0;
	delay_10us(5);
	return dat;
} 

/*******************************************************************************
* 函 数 名         : ds18b20_read_byte
* 函数功能		   : 从DS18B20读取一个字节
* 输    入         : 无
* 输    出         : 一个字节数据
*******************************************************************************/
u8 ds18b20_read_byte(void)
{
	u8 i=0;
	u8 dat=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次读取一位,且先读低位再读高位
	{
		temp=ds18b20_read_bit();
		dat=(temp<<7)|(dat>>1);
	}
	return dat;	
}

/*******************************************************************************
* 函 数 名         : ds18b20_write_byte
* 函数功能		   : 写一个字节到DS18B20
* 输    入         : dat:要写入的字节
* 输    出         : 无
*******************************************************************************/
void ds18b20_write_byte(u8 dat)
{
	u8 i=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
	{
		temp=dat&0x01;//选择低位准备写入
		dat>>=1;//将次高位移到低位
		if(temp)
		{
			DS18B20_PORT=0;
			_nop_();_nop_();
			DS18B20_PORT=1;	
			delay_10us(6);
		}
		else
		{
			DS18B20_PORT=0;
			delay_10us(6);
			DS18B20_PORT=1;
			_nop_();_nop_();	
		}	
	}	
}

/*******************************************************************************
* 函 数 名         : ds18b20_start
* 函数功能		   : 开始温度转换
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void ds18b20_start(void)
{
	ds18b20_reset();//复位
	ds18b20_check();//检查DS18B20
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0x44);//转换命令	
}

/*******************************************************************************
* 函 数 名         : ds18b20_init
* 函数功能		   : 初始化DS18B20的IO口 DQ 同时检测DS的存在
* 输    入         : 无
* 输    出         : 1:不存在,0:存在
*******************************************************************************/ 
u8 ds18b20_init(void)
{
	ds18b20_reset();
	return ds18b20_check();	
}

/*******************************************************************************
* 函 数 名         : ds18b20_read_temperture
* 函数功能		   : 从ds18b20得到温度值
* 输    入         : 无
* 输    出         : 温度数据
*******************************************************************************/
float ds18b20_read_temperture(void)
{
	float temp;
	u8 dath=0;
	u8 datl=0;
	u16 value=0;

	ds18b20_start();//开始转换
	ds18b20_reset();//复位
	ds18b20_check();
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0xbe);//读存储器

	datl=ds18b20_read_byte();//低字节
	dath=ds18b20_read_byte();//高字节
	value=(dath<<8)+datl;//合并为16位数据

	if((value&0xf800)==0xf800)//判断符号位,负温度
	{
		value=(~value)+1; //数据取反再加1
		temp=value*(-0.0625);//乘以精度	
	}
	else //正温度
	{
		temp=value*0.0625;	
	}
	return temp;
}

ds18b20.h

# ifndef _ds18b20_H
# define _ds18b20_H

# include "public.h"

//管脚定义
sbit DS18B20_PORT=P3^7;	//DS18B20数据口定义


//函数声明
u8 ds18b20_init(void);
float ds18b20_read_temperture(void);

# endif

public.c(通用)

# include "public.h"

/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}

/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ms:ms延时时间
* 输    出    	 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
	u16 i,j;
	for(i=ms;i>0;i--)
		for(j=110;j>0;j--);
}

public.h

# ifndef _public_H
# define _public_H

# include "reg52.h"

typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;


void delay_10us(u16 ten_us);
void delay_ms(u16 ms);

# endif

uart.c(串口通信)

# include "uart.h"

# define RELOAD_COUNT 0xFA //宏定义波特率发生器的载入值 9600

void UART_Init(void)
{
	SCON|=0X50;			//设置为工作方式1
	TMOD|=0X20;			//设置计数器工作方式2
	PCON=0X80;			//波特率加倍
	TH1=RELOAD_COUNT;	//计数器初始值设置
	TL1=TH1;
	ES=0;				//关闭接收中断
	EA=1;				//打开总中断
	TR1=1;				//打开计数器
//	TI=1;          //发送中断标记位,如果使用printf函数的必须设置	
}

void UART_SendData(u8 dat)
{
	ES=0; //关闭串口中断
	TI=0; //清发送完毕中断请求标志位
	SBUF=dat; //发送
	while(TI==0); //等待发送完毕
	TI=0; //清发送完毕中断请求标志位
	ES=1; //允许串口中断
}

void UART_SendString(u8 *pbuf)
{
	while(*pbuf!='\0') //遇到空格跳出循环	
	{
		UART_SendData(*pbuf);
		delay_10us(5);
		pbuf++;	
	}
}

u8 UART_RX_BUF[UART_REC_LEN];     //接收缓冲,最大UART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 UART_RX_STA=0;       //接收状态标记	


//void UART_IRQn() interrupt 4
//{
//	u8 r;
//	static u8 i=0;
//	
//	if(RI)
//	{
//		RI=0;
//		UART_RX_BUF[i]=SBUF;//读取接收到的数据
//		if(UART_RX_BUF[0]=='+')i++;
//		else i=0;
//		if(i==10)
//		{
//			i=0;
//		}		  		
//	}	
//}

uart.h

# ifndef _uart_H
# define _uart_H

# include "public.h"
# include "stdio.h"


# define UART_REC_LEN  			10  	//定义最大接收字节数 50

extern u8  UART_RX_BUF[UART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 UART_RX_STA;         		//接收状态标记	


void UART_Init(void);
void UART_SendData(u8 dat);
void UART_SendString(u8 *pbuf);


# endif

bluetooth.c(蓝牙)

# include "bluetooth.h"
# include "ds18b20.h"
# include "uart.h"
# include "smg.h"


//定义LED1管脚
sbit LED1=P2^0;

//定义蓝牙控制命令
# define LED1_ON_CMD			0X11
# define LED1_OFF_CMD		0X10


//蓝牙控制初始化
void bluetooth_control_init(void)
{
	UART_Init();
	ds18b20_init();//初始化DS18B20
	ES=1;//允许串口中断	
}

//蓝牙控制
void bluetooth_control(void)
{
	long i=0;
   	int temp_value;
	u8 temp_buf[5];
	u8 bluetooth_send_buf[7];

	while(1)
	{
		i++;
		if(i%50==0)//间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间
			temp_value=ds18b20_read_temperture()*10;//保留温度值小数后一位
		if(temp_value<0)//负温度
		{
			temp_value=-temp_value;
			temp_buf[0]=0x40;//显示负号
			bluetooth_send_buf[0]='-';	
		}
		else
		{
			temp_buf[0]=0x00;//不显示
			bluetooth_send_buf[0]='+';
		}		
		temp_buf[1]=gsmg_code[temp_value/1000];//百位
		temp_buf[2]=gsmg_code[temp_value%1000/100];//十位
		temp_buf[3]=gsmg_code[temp_value%1000%100/10]|0x80;//个位+小数点
		temp_buf[4]=gsmg_code[temp_value%1000%100%10];//小数点后一位
		smg_display(temp_buf,4);
		if(i%100==0)
		{
			bluetooth_send_buf[1]=temp_value/1000+0x30;
			bluetooth_send_buf[2]=temp_value%1000/100+0x30;
			bluetooth_send_buf[3]=temp_value%1000%100/10+0x30;
			bluetooth_send_buf[4]='.';
			bluetooth_send_buf[5]=temp_value%1000%100%10+0x30;
			bluetooth_send_buf[6]='\0';
			UART_SendString(bluetooth_send_buf);//通过串口发送温度数据到APP	
		}		
	}				
}

//串口中断服务函数
//接收手机APP发送的信号后控制板载资源
void UART_IRQn() interrupt 4
{
	if(RI)
	{
		RI=0;
		UART_RX_BUF[0]=SBUF;//读取接收到的数据
		
		//蓝牙控制
		if(UART_RX_BUF[0]==LED1_ON_CMD)
			LED1=0;
		else if(UART_RX_BUF[0]==LED1_OFF_CMD)
			LED1=1;		
	}	
}

bluetooth.h

# ifndef _bluetooth_H
# define _bluetooth_H

# include "public.h"

void bluetooth_control_init(void);
void bluetooth_control(void);

# endif