<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;
}
PCF8591学习(二)-AD转换,算法,串口打印
最新推荐文章于 2023-03-17 19:03:09 发布