PCF8591 +MQ3 +LCD1602+89C51RC(酒精传感器)

本文档展示了如何使用80C51微控制器通过IIC通信协议与PCF8591模拟数字转换器及LCD1602显示器进行交互。代码详细解释了初始化、检测BF位状态、写数据和命令等功能,用于在LCD1602上显示信息。
摘要由CSDN通过智能技术生成

PCF8591

环境:

软件:

  • uVision
  • proteus

芯片

  • 80c51
  • PCF8591、LCD1602

仿真图

在这里插入图片描述

相关函数编写电平时

代码

1602

头文件
#include<reg51.h>
#include<intrins.h> //使用_nop_();
#include<string.h>
宏定义
// RS为寄存器选择,高电平时选择寄存器,低电平时选择指令寄存器
sbit RS = P2^0;
// RW为读写信号线,高电平时进行读操作,低电平时进行写操作 
sbit RW = P2^1;
// EN为使能端,当EN端由高电平跳变成低电平时,液晶模块执行命令
sbit EN = P2^2;
初始化
/**
* LCD初始化
*
* @return
*/
void init()
{
	/*
	  0011_1000 置功能
 	  DL=1 --> 8位总线
	  N=0  --> 单行显示
	  F=0  -->	显示5x7的点阵字符
	*/	
	write_cmd(0x38);
	
	/*
	  0000_0001 清显示
	  指令码01H,光标复位到地址00H位置
	*/ 
	write_cmd(0x01);
	
	/*
	  0000_0110 置输入模式
	  I/D=1 --> 光标右移
	  S=0   --> 屏幕上所有文字左移或右移
	*/
	write_cmd(0x06);
	
	/*
	  0000_1100	显示开/关控制
	  D=1 --> 开显示
	  C=0 --> 无光标
	  B=0 --> 光标不闪烁
	*/
	write_cmd(0x0C);
}
检测BF(busy flag)位状态
/*
* 检测BF(busy flag)位状态
*  防止不能识别,需用延时函数代替
* @return
*/
void test_BF()
{
	unsigned char LCD_status;
	do{
		P0 = 0xFF; // LCD1602读取状态数据,必须有一个上拉电平
		EN = 0; RS = 0; RW = 1; // RS为0时,P0的数据为命令
		EN=1;// 让RS和RW设置有效
		LCD_status = P0;
		_nop_(); _nop_();
		EN = 0;
	}while(LCD_status&0x80); // 1000_0000 忙碌状态
}
写数据
/*
* 写数据(一位一位的写)
*
* @param data8 八位数据
* @return
*/
void write_data(unsigned char data8)
{
	test_BF();
	EN = 0; RS = 1; RW = 0;
	P0 = data8;
	EN = 1; _nop_(); EN = 0;
}
写命令
/*
* 写命令
*
* @param cmd8 八位命令
* @return
*/
void write_cmd(unsigned char cmd8)
{
	test_BF();
	EN = 0; RS = 0; RW = 0;
	P0 = cmd8;
	EN = 1; _nop_(); EN = 0;
}
写字符串
/**
* 写字符串
*
* @param r row 0---第一行  1---第二行
* @param c column
* @param str 字符串
* @return
*/
void write_str(int r, int c, char *str)
{
	int i=0;	
	unsigned char Addressx[] = {0x80, 0xC0};
	unsigned char StartAdd = (Addressx[r] | c);//按位或

	write_cmd(StartAdd);
	
	for(i = 0; i < 16; i++){
		if(str[i]==0) break;
		write_data(str[i]);
	}
	// 如果不够16位,用空格填充
	for(;i < 16; i++){
		write_data(' '); 	
	}
}

LCD1602.c

#include<reg51.h>
#include<intrins.h> //使用_nop_();
#include<string.h>

/*
* 宏定义
*/
// RS为寄存器选择,高电平时选择寄存器,低电平时选择指令寄存器
sbit RS = P1^0;
// RW为读写信号线,高电平时进行读操作,低电平时进行写操作 
sbit RW = P1^1;
// EN为使能端,当EN端由高电平跳变成低电平时,液晶模块执行命令
sbit EN = P1^2;


/*
* 延时(不准确延时)
*
* @param ms
* @return  
*/
void delay_ms(int ms)
{
	while(ms--){
		int i = 100;
		while(i--){}
	}
}

/*
* 检测BF(busy flag)位状态
* 
* @return
*/
void test_BF()
{
	//unsigned char sta;
  // P2  = 0xFF;
  // RS = 0;
  // RW = 1;
  // do {
  //     EN = 1;
  //     sta = P2; //读取状态字
  //     EN = 0;
  // }while (sta & 0x80); //bit7 等于 1 表示液晶正忙,重复检测直到其等于 0 为止
	delay_ms(20);
}

/*
* 写数据(一位一位的写)
*
* @param data8 八位数据
* @return
*/
void write_data(unsigned char data8)
{
	test_BF();
	EN = 0; RS = 1; RW = 0;
	P2 = data8;
	EN = 1; _nop_(); EN = 0;
}

/*
* 写命令
*
* @param cmd8 八位命令
* @return
*/
void write_cmd(unsigned char cmd8)
{
	test_BF();
	EN = 0; RS = 0; RW = 0;
	P2 = cmd8;
	EN = 1; _nop_(); EN = 0;
}

/**
* 写字符串
*
* @param r row
* @param c column
* @param str 字符串
* @return
*/
void LcdShowStr(int r, int c, char *str)
{
	int i=0;	
	unsigned char Addressx[] = {0x80, 0xC0};
	unsigned char StartAdd = (Addressx[r] | c);//按位或

	write_cmd(StartAdd);
	
	while (*str != '\0') //连续写入字符串数据,直到检测到结束符
	{
		write_data(*str++); //先取 str 指向的数据,然后 str 自加 1
	}
}

/**
* LCD初始化
*
* @return
*/
void InitLcd1602()
{
	 /*
	  0011_1000 置功能
 	  DL=1 --> 8位总线
	  N=0  --> 单行显示
	  F=0  -->	显示5x7的点阵字符
	*/	
	write_cmd(0x38);
	/*
	  0000_0001 清显示
	  指令码01H,光标复位到地址00H位置
	*/ 
	write_cmd(0x01);
	/*
	  0000_0110 置输入模式
	  I/D=1 --> 光标右移
	  S=0   --> 屏幕上所有文字左移或右移
	*/
	write_cmd(0x06);
	/*
	  0000_1100	显示开/关控制
	  D=1 --> 开显示
	  C=0 --> 无光标
	  B=0 --> 光标不闪烁
	*/
	write_cmd(0x0C);
}

IIC.h

#include<intrins.h>
//总线引脚定义
sbit SCL = P3^6;  /* 数据线 */
sbit SDA = P3^7;  /* 时钟线 */

void iic_Delay()  {_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();}

//开始
void iic_Start()
{
	 SCL = 1;
	 SDA = 1;
	 iic_Delay();
	 SDA = 0;
	 iic_Delay();
	 SCL = 0;
}

//停止
void iic_Stop()
{
	SCL = 0;
	SDA = 0;
	iic_Delay();
	SCL = 1;
	iic_Delay();
	SDA = 1;
	iic_Delay();
}


/*读、写操作*/	
bit iic_SendByte(unsigned char byt)
{	
	bit ack = 0;	
	unsigned char mask;
							   	
	for(mask=0x80;mask!=0;mask>>=1)
	{
		if((byt&mask) == 0) 
			SDA = 0;
		else
			SDA = 1;

		iic_Delay();
		SCL = 1;
		iic_Delay();
		SCL = 0;
	}
		SDA = 1;
		iic_Delay();
		SCL = 1;
		ack = SDA;
		iic_Delay();
		SCL = 0;

	return ack;			
}

/*读数据并且继续下去*/
unsigned char iic_readNAK()
{
	unsigned char mask;
	unsigned char dat;

	SDA = 1;
	SCL = 0;
	for(mask=0x80;mask!=0;mask>>=1)
	{
		iic_Delay();
		SCL = 1;
		if(SDA == 1) dat |= mask;
		else  dat &= (~mask);
		iic_Delay();
		SCL = 0;
	}
	SDA = 1;
	iic_Delay();
	SCL = 1;
	iic_Delay();
	SCL = 0;

	return dat;
}

/*读数据但不再下去*/	
unsigned char iic_readACK()
{
	unsigned char mask;
	unsigned char dat;

	SDA = 1;
	SCL = 0;
	for(mask=0x80;mask!=0;mask>>=1)
	{
		iic_Delay();
		SCL = 1;
		if(SDA == 1) dat |= mask;
		else  dat &= (~mask);
		iic_Delay();
		SCL = 0;
	}
	SDA = 0;
	iic_Delay();
	SCL = 1;
	iic_Delay();
	SCL = 0;

	return dat;
}

详情代码 点击下载

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

洛尘~~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值