STC12驱动MLX90614红外测温模块在LCD1602显示

1、基本简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、通信方式

通过芯片手册我们可以了解到这个模块的输出有PWM和SMBus方式,PWM长期做嵌入式开发的已经很熟悉了,那么什么是SMBus呢?
SMBus(系统管理总线),最早由Intel提出,应用于移动PC和桌面PC系统中的低速率通信,是一种两线的接口。通过它,各设备之间以及系统的其他部分可以之间可以相互通信,它是基于IIC原理,接口和数据格式类似与IIC,同样有两个接口(1个时钟、一个数据),7位数据。可以说SMBus是IIC的一个子集
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、参考STC12例程

#include <STC12C5A60S2.H>
#include <intrins.h>
#include <stdio.h>

/*=================================================
 * 时钟宏定义
 *=================================================*/
#define MAIN_Fosc		11059200L			//宏定义主时钟HZ
//#define MAIN_Fosc		12000000L

/*=================================================
 * 自定义数据类型
 *=================================================*/
typedef unsigned char uchar;
typedef unsigned int uint;

//LCD1602硬件接口
#define LCD1602_DB P0			//LCD1602数据总线
sbit LCD1602_RS = P3^5;	 //RS端
sbit LCD1602_RW = P3^6;	 //RW端
sbit LCD1602_EN = P3^4;	 //EN端

//I2C模拟硬件接口定义
sbit SCL = P0^6;
sbit SDA = P0^7;

/*I2C常用变量宏定义*/
#define I2cRead 		1			//I2C读方向位
#define I2cWrite 		0			//I2C写方向

/*全局变量定义*/
uchar DataH,DataL,Pecreg;


/*============================自主适应时钟延时函数===========================================*/
//基于STC12单片机1us延时函数
//函数说明:内部调用
static void Delaym1us()
{
	# if MAIN_Fosc == 11059200L
	//晶振11.0592MHz
	_nop_();
	
	#elif MAIN_Fosc == 12000000L
	//晶振12.000000MHZ
	_nop_();
	_nop_();
	
	#endif
}

//基于STC12单片机us延时函数
//函数说明:外部调用
void Delay_us(uint time)
{
	int i;
	for(i=0; i<time; i++)
	{
		Delaym1us();
	}
}

//基于STC12单片机ms延时函数
//函数说明:外部调用
void Delay_ms(uint time)
{
	int i;
	for(i=0; i<time; i++)
	{
		Delay_us(1000);
	}
}

/*============================IIC===========================================*/
//I2C延时5us函数
void I2cDelay_5us(void)
{
	Delay_us(5);
}

//I2C总线起始信号
void I2cStart(void)
{
	SCL = 1;
	SDA = 1;
	I2cDelay_5us();//状态保持5us
	SDA = 0;
	I2cDelay_5us();//状态保持5us
}

//I2C总线停止信号
void I2cStop(void)
{
	SCL = 0;
	SDA = 0;
	SCL = 1;
	I2cDelay_5us();//状态保持5us
	SDA = 1;
	I2cDelay_5us();//状态保持5us
}

/********************************
 *函数名称:ReadACK(void)
 *函数输入:无
 *函数返回:1非应答,0应答
 *函数说明:I2C总线读从机应答信号
 ********************************/
bit ReadACK(void)
{
	uint i;
	
	SCL = 0;//拉低时钟总线,允许从机控制SDA
	SCL = 1;//拉高,读SDA
	I2cDelay_5us();
	while((SDA==1) && (i<250))//等待SDA应答,或者超过时间默认应答
		i++;
	SCL = 0;
	I2cDelay_5us();
	return(0);//返回0应答
}

/***************************************
 *函数名称:SendACK(bit i)
 *函数输入:1主机发送非应答,0发送应答
 *函数返回:无
 *函数说明:主机发送应答信号
 ***************************************/
void SendACK(bit i)
{
	SCL = 0;	//拉低时钟总线,允许主机控制SDA
	if(i)		//发送非应答
		SDA = 1;
	else
		SDA = 0;
	SCL = 1;	//拉高总线,让从机读SDA
	I2cDelay_5us();
	SCL = 0;	//拉低时钟总线,允许SDA释放
	SDA = 1;	//释放数据总线
}

/***************************************
 *函数名称:I2cSendByte(uchar DAT)
 *函数输入:DAT需要发送的数据
 *函数返回:无
 *函数说明:I2C发送一个字节数据
 ***************************************/
void I2cSendByte(uchar DAT)
{
	uchar i;
	for(i=0; i<8; i++)	//分别写8次,每次写1位
	{
		SCL = 0;		//拉低时钟总线,允许SDA变化
		_nop_();
		if(DAT & 0x80)	//先写数据最高位
		{
			SDA = 1;  	//写1
			_nop_();
		}
		else
		{
			SDA = 0;  	//写0
			_nop_();
		}
		SCL = 1;	  	//拉高时钟,让从机读SDA
		_nop_();
		DAT <<= 1;	  	//为发送下一位左移1位
	}
	SCL = 0;			//拉低时钟总线,允许SDA释放
	_nop_();
	SDA = 1;			//释放数据总线
	_nop_();
}

/*====================================
函数	:I2cReadByte()
参数	:无
返回值	:返回读出的一字节数据
描述	:I2C总线读一字节数据
====================================*/
uchar I2cReadByte(void)
{
	uchar i, DAT;

	SCL = 0;
	_nop_();
	SDA = 1;
	_nop_();
	for(i=0; i<8; i++)//分别读8次,每次读一位
	{
		DAT <<= 1; //数据左移1位,准备接收一位
		SCL = 0;   //拉低时钟总线,允许从机控制SDA变化
		_nop_();
		SCL = 1;   //拉高时钟总线,读取SDA上的数据
		_nop_();
		if(SDA)
			DAT |= 0X01;//为1则写1,否则不行执行写1,通过左移补0
		_nop_();
	}
	return(DAT); //返回读出的数据
}

//读取温度数据
uint temperatureRead(void)
{
	I2cStart();
	I2cSendByte(0xB4);//Send SlaveAddress(写从设备地址)
	ReadACK();
	I2cSendByte(0x07);//Send Command(写命令)
	ReadACK();
	
	I2cStart();
	I2cSendByte(0x01);
	DataL = I2cReadByte();
	SendACK(0);
	DataH = I2cReadByte();
	SendACK(0);
	Pecreg = I2cReadByte();
	I2cStop();
	return(DataH*256+DataL);
}

//读取到最终温度
//程序涉及到温度计算,详细参考芯片手册
float SMBus_ReadTemp(void)
{
	float temp;
	temp = temperatureRead();
	temp = temp * 0.02 - 273.15;
	return temp;
}

/*============================LCD1206===========================================*/
/*=================================================
*函数名称:Read_Busy
*函数功能:判断1602液晶忙,并等待
=================================================*/
void Read_Busy()
{
	uchar busy;
	LCD1602_DB = 0xff;//复位数据总线
	LCD1602_RS = 0;	  //拉低RS+
	LCD1602_RW = 1;	  //拉高RW读
	do
	{
		LCD1602_EN = 1;//使能EN
		busy = LCD1602_DB;//读回数据
		LCD1602_EN = 0;	 //拉低使能以便于下一次产生上升沿
	}while(busy & 0x80); //判断状态字BIT7位是否为1,为1则表示忙,程序等待
}
/*=================================================
*函数名称:LCD1602_Write_Cmd
*函数功能:写LCD1602命令
*调用:Read_Busy();
*输入:cmd:要写的命令
=================================================*/
void LCD1602_Write_Cmd(uchar cmd)
{
	Read_Busy();	 //判断忙,忙则等待
	LCD1602_RS = 0;
	LCD1602_RW = 0;	//拉低RS、RW操作时序情况1602课件下中文使用说明基本操作时序章节
	LCD1602_DB = cmd;//写入命令
	LCD1602_EN = 1;	 //拉高使能端 数据被传输到LCD1602内
	LCD1602_EN = 0;	 //拉低使能以便于下一次产生上升沿
}
/*=================================================
*函数名称:LCD1602_Write_Dat
*函数功能:写LCD1602数据
*调用:Read_Busy();
*输入:dat:需要写入的数据
=================================================*/
void LCD1602_Write_Dat(uchar dat)
{
	Read_Busy();
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	LCD1602_DB = dat;
	LCD1602_EN = 1;
	LCD1602_EN = 0;
}

/*=================================================
*函数名称:LCD1602_Dis_Str
*函数功能:在指定位置显示字符串
*调用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();
*输入:x:要显示的横坐标取值0-40,y:要显示的行坐标取值0-1(0为第一行,1为第二行)
		*str:需要显示的字符串
=================================================*/
void LCD1602_Dis_Str(uchar x, uchar y, uchar *str)
{
	if(y) x |= 0x40;
	x |= 0x80;
	LCD1602_Write_Cmd(x);
	while(*str != '\0')
	{
		LCD1602_Write_Dat(*str++);
	}
}
/*=================================================
*函数名称:Init_LCD1602
*函数功能:1602初始化
*调用:	LCD1602_Write_Cmd();
=================================================*/
void Init_LCD1602()
{
	LCD1602_Write_Cmd(0x38); //	设置16*2显示,5*7点阵,8位数据接口
	LCD1602_Write_Cmd(0x0c); //开显示
	LCD1602_Write_Cmd(0x06); //读写一字节后地址指针加1
	LCD1602_Write_Cmd(0x01); //清除显示
}

void main()
{
	float Temperature = 0;			//温度数据变量(浮点型)
	char TempValue[10] = {0};		//温度值(字符串)
	
	uchar TestStr[] = {"Temp:"};
	Init_LCD1602();							//1602初始化
	LCD1602_Dis_Str(0, 0, &TestStr[0]);		//显示字符串
	
	while(1)
	{
		Temperature = SMBus_ReadTemp();
		Delay_ms(100);
		sprintf(TempValue, "%.1f", Temperature);//浮点型转换字符串
		LCD1602_Dis_Str(6, 0, &TempValue[0]);
	}
}

请添加图片描述

参考文献

[1] MLX90614中文资料

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个简单的代码示例,可以实现你所描述的功能: ```c #include <reg52.h> #include <intrins.h> #define FOSC 11059200L #define BAUD 9600 typedef unsigned char uchar; typedef unsigned int uint; sbit SCL=P2^1; sbit SDA=P2^0; sbit E=P1^7; sbit RW=P1^6; sbit RS=P1^5; // I2C总线相关操作 void delay5us() _naked { _asm nop nop nop nop _endasm; } void i2c_start() { SDA = 1; delay5us(); SCL = 1; delay5us(); SDA = 0; delay5us(); SCL = 0; delay5us(); } void i2c_stop() { SDA = 0; delay5us(); SCL = 1; delay5us(); SDA = 1; delay5us(); } void i2c_ack() { SDA = 0; delay5us(); SCL = 1; delay5us(); SCL = 0; delay5us(); SDA = 1; delay5us(); } void i2c_nack() { SDA = 1; delay5us(); SCL = 1; delay5us(); SCL = 0; delay5us(); SDA = 1; delay5us(); } uchar i2c_write_byte(uchar dat) { uchar i, ack_bit; for(i=0; i<8; i++) { SDA = (dat & 0x80) >> 7; dat <<= 1; delay5us(); SCL = 1; delay5us(); SCL = 0; delay5us(); } SDA = 1; delay5us(); SCL = 1; delay5us(); ack_bit = SDA; SCL = 0; delay5us(); return ack_bit; } uchar i2c_read_byte() { uchar i, dat = 0; SDA = 1; delay5us(); for(i=0; i<8; i++) { dat <<= 1; SCL = 1; delay5us(); dat |= SDA; SCL = 0; delay5us(); } return dat; } // MLX90614红外测温模块相关操作 void mlx90614_init() { i2c_start(); i2c_write_byte(0xB4); i2c_write_byte(0x01); i2c_write_byte(0x60); i2c_stop(); } float mlx90614_get_temp() { uchar i, temp_h, temp_l; float temp; i2c_start(); i2c_write_byte(0xB4); i2c_write_byte(0x07); i2c_stop(); i2c_start(); i2c_write_byte(0xB5); temp_h = i2c_read_byte(); temp_l = i2c_read_byte(); i2c_nack(); i2c_stop(); temp = (temp_h << 8) | temp_l; temp *= 0.02; temp -= 273.15; return temp; } // LCD1602显示模块相关操作 void lcd_write_cmd(uchar cmd) { RS = 0; RW = 0; P0 = cmd; E = 1; _nop_(); _nop_(); E = 0; } void lcd_write_data(uchar dat) { RS = 1; RW = 0; P0 = dat; E = 1; _nop_(); _nop_(); E = 0; } void lcd_init() { lcd_write_cmd(0x38); lcd_write_cmd(0x0C); lcd_write_cmd(0x06); lcd_write_cmd(0x01); } void lcd_display_temp(float temp) { uchar i, temp_int, temp_dec; temp_int = (uchar)temp; temp_dec = (uchar)((temp - temp_int) * 100); lcd_write_cmd(0x80); lcd_write_data('T'); lcd_write_data('e'); lcd_write_data('m'); lcd_write_data('p'); lcd_write_data(':'); lcd_write_data(' '); lcd_write_data(temp_int / 10 + '0'); lcd_write_data(temp_int % 10 + '0'); lcd_write_data('.'); lcd_write_data(temp_dec / 10 + '0'); lcd_write_data(temp_dec % 10 + '0'); lcd_write_data('C'); } // 主函数 void main() { float temp; TMOD = 0x20; TH1 = TL1 = -(FOSC/12/32/BAUD); TR1 = 1; SCON = 0x50; ES = 1; EA = 1; lcd_init(); mlx90614_init(); while(1) { temp = mlx90614_get_temp(); lcd_display_temp(temp); delay_ms(500); } } // 串口中断服务函数 void uart_isr() interrupt 4 { RI = 0; TI = 0; } ``` 这段代码使用了STC89C52单片机,通过I2C总线与MLX90614红外测温模块进行通信,读取人体温度值,然后通过LCD1602显示模块将温度值显示出来。 注意,这段代码中串口通信部分还没有实现,如果需要使用串口通信功能,需要自己添加相关代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小明n.n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值