PCF8591学习(二)-AD转换,算法,串口打印

<pre name="code" class="csharp">/*
项目名称:PCF8591AD和串口打印
项目内容:A/D转换,把转换的数字量
送给P0口控制LED的亮灭 ;
并把转换的数字逻辑
运算,送给串口,打印到电脑上。
这样就可以采样电压信号了,并处理。
可以扩展做出电压表,电流表等。
作者:YUAN
*/

#include <reg52.h>
#include <stdio.h>		//printf输出头文件
#include <intrins.h>	//_nop_()延时头文件
typedef unsigned char uChar8;
typedef unsigned int uInt16;
sbit SDA = P1^0;
sbit SCL = P1^1;
#define PCF8591Add 0x90	//PCF8591的器件地址和写操作
uChar8 gTemp;
float gfDataVal; 	//用在转载计算的数值,并发送给计算机

//延时函数
void DelayMS(uInt16 lValMS);
void Delay5us(void);
//IIC操作的几个函数
void IICInit(void);		//IIC初始化
void IICStart(void);	//起始信号
void IICStop(void);		//停止信号
void IICAck(void);		//应答信号
void IICReadAck(void);	//读应答信号
void IICWriteOneByte(uChar8 lByteVal);					//写一个字节
uChar8 IICReadOneByte(void);		//读一个字节
void PCF8591WriteRegulate(uChar8 lREGVal);	//Regulate控制器,这里写控制函数
uChar8  ReadDataPCF8591(void);
// 

//串口的几个程序
void UartInit(void);		//串口初始化
void UartPrint(float iVal);	//Printd打印,打印函数
								
void main()
{
	IICInit();
	UartInit();
	while(1)
	{	 
		/*写入控制字00,即模拟量输出关闭,选择通道0,
		不自动增加通道,模拟量输入围方式0*/
		 PCF8591WriteRegulate(0x00);
		 P0 = ReadDataPCF8591(); 
		 gTemp = P0; 	//用来中转的存储区
		 gfDataVal = (float)gTemp/255*5;   //强制转换
		 DelayMS(1000);
		 UartPrint(gfDataVal);
	}
}

void DelayMS(uInt16 lValMS)	//延时函数
{
	uInt16 luiVal,lujVal;
	for(luiVal = 0; luiVal < lValMS; luiVal++)
		for(lujVal = 0; lujVal < 113; lujVal++);
}
void Delay5us(void)
{
	_nop_();_nop_();_nop_();
	_nop_();_nop_();_nop_();
}
//IIC总线空闲时均为高电平
void IICInit(void)		//IIC初始化
{
  	SCL = 0;
	SDA=1;
	Delay5us();
	SCL=1;
}
//SCL高电平期间SDA由高到低的变化为起始信号
void IICStart(void)	//起始信号
{
	SCL = 0;
	Delay5us();
	SDA = 1;
	Delay5us();
	SCL = 1;
	Delay5us();
	SDA = 0;
	Delay5us();
	//防止接下来SDA数据变化导致IIC总线误判	
	SCL = 0;	 
}
//SCL高电平期间SDA由低到高的变化为终止信号
void IICStop(void)		//停止信号
{
	SCL = 0;
	Delay5us();
	SDA = 0;
	Delay5us();
	SCL = 1;
	Delay5us();
	SDA = 1;
	Delay5us();
	//防止接下来SDA数据变化导致IIC总线误判	
	SCL = 0;
}
//一个脉冲期间,SDA为低电平为应答
void IICAck(void)		//应答信号
{
	SCL = 0;
	Delay5us();
	SDA = 0;
	Delay5us();
	SCL = 1;
	Delay5us();
	SCL = 0; 		
}
/*cpu读应答信号,如果应答了则
继续传输数据,否则在一定时间里,
默认已经应答,继续传数据
*/
void IICReadAck(void)	//读应答信号
{
	uChar8 li = 0;
	SCL = 0;
	SDA = 1;  //确保读出的值为0,因此先送1
	Delay5us();
	SCL = 1;
	Delay5us();
	//如果没有应答或时间没有超过预定时间则停在此处
	while((1 == SDA)&&(li<255))li++;
	SCL = 0;
	Delay5us();		
	SDA = 1;			
}
/*
	写1个字节,先写高位。
*/
void IICWriteOneByte(uChar8 lByteVal)					//写一个字节
{
	uChar8 li,liVal;
	liVal = lByteVal;

	for(li=0;li<8;li++)	  
	{
		
		SCL = 0; 
		Delay5us();	
		SDA = (bit)(liVal&0x80);	//把数据准备好等待传送
		Delay5us();	
		SCL = 1;
		Delay5us();
		liVal <<= 1;
	} 
	SCL = 0; 
	Delay5us();	
	SDA = 1;
}
/*
读取一个字节并把读到的值返回
*/
uChar8 IICReadOneByte(void)
{
	uChar8 li,liVal;
	SCL = 0;
	SDA = 1;
	for(li=0;li<8;li++)
	{
		liVal <<= 1;
		SCL = 0;
		Delay5us();
		SCL = 1;
		Delay5us();
		liVal = (liVal|SDA);
	}
	SCL = 0; 
	return liVal;
}	
//Regulate控制器,这里写控制函数
void PCF8591WriteRegulate(uChar8 lREGVal)
{
	IICStart();
	IICWriteOneByte(PCF8591Add); 	//PCF8591的地址,写控制
	IICReadAck();
	IICWriteOneByte(lREGVal);		//写入控制字
	IICReadAck();
	IICStop();
}	
uChar8  ReadDataPCF8591(void)
{
	uChar8 liVal;
	IICStart();
	IICWriteOneByte(PCF8591Add|0x01); 	//PCF8591的地址,读控制	
	liVal = IICReadOneByte();
	IICAck();
	IICStop();
	return liVal; 	
} 
//串口的程序
void UartInit(void)
{
	TMOD &= 0x0f;	 //只改变要改变的
	TMOD |= 0x20;	//设置定时器0为工作方式2
	TL1 = 0xfd;
	TH1 = 0xfd;		//设置波特率为9600bps
	TR1 = 1;		//允许T1开始计数

	SCON &= 0x5f;
	SCON |= 0x50;	//设置串口工作在方式1,允许接收数据 
}
//把读出来的值打印到计算机上
void UartPrint(float iVal)
{
	TI=1;
	printf("测得电压为:%f\n",iVal);
	while(!TI);
	TI=0;
}



                
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值