标题:
分享一个 PCF8591 AD转换文件
[打印本页]
作者:
miaomi_love
时间:
2018-6-18 13:08
标题:
分享一个 PCF8591 AD转换文件
用12864显示,AD芯片采用IIC通讯方式,需要用多路时要做小许修改。
#include<reg52.h>
#include<intrins.h>
//P0口为12864数据输出口
#define uchar unsigned char
#define uint unsigned int
#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
sbit PM=P1^0;
sbit SCL=P1^1; //I2C时钟引脚
sbit SDA=P1^2;//I2C数据输入输出引脚
uchar Recv_Buffer[4];//数据接收缓冲
uint Voltage[]={'0','0','0'};//数据分解为电压x.xx
bit bdata IIC_ERROR; //I2C错误标志位
uchar LCD_Line_1[]={"1- . V 2- . V"};
uchar LCD_Line_2[]={"3- . V 4- . V"};
//延时
void delay(int ms)
{
uchar i;
while(ms--) for(i=0;i<250;i++) Delay4us();
}
//LCD忙检测
bit LCD_Busy_Check()
{
bit Result;
LCD_RS=0;LCD_RW=1;
LCD_EN=1;Delay4us();Result=(bit)(P0&0x80);
LCD_EN=0;
return Result;
}
//写指令
void LCD_Write_Command(uchar cmd)
{
while(LCD_Busy_Check());
LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();
P0=cmd;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
// 写数据
void LCD_Write_Data(uchar dat)
{
while(LCD_Busy_Check());
LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
//初始化
void LCD_Initialise()
{
LCD_Write_Command(0x38);delay(5);
LCD_Write_Command(0x0c);delay(5);
LCD_Write_Command(0x06);delay(5);
LCD_Write_Command(0x01);delay(5);
}
//设置显示位置
void LCD_Set_Position(uchar pos)
{
//LCD_Write_Command(pos|0x80);
LCD_Write_Command(pos);
}
//显示一行
void LCD_Display_A_Line(uchar Line_Addr,uchar s[])
{
uchar i;
LCD_Set_Position(Line_Addr);
for(i=0;i<16;i++)LCD_Write_Data(s[i]);
}
// 将模数转换后得到的值分解存入缓存
void Convert_To_Voltage(uchar val)
{
uchar Tmp; //最大值为255,对应5V,255/5=51
Voltage[2]=val/51+'0';//整数部分
Tmp=val%51*10;// 第一位小数
Voltage[1]=Tmp/51+'0';
Tmp=Tmp%51*10;
Voltage[0]=Tmp/51+'0';
}
//启动I2C总线
void IIC_Start()
{
SDA=1;
SCL=1;
Delay4us();
SDA=0;
Delay4us();
SCL=0;
}
//停止I2C总线
void IIC_Stop()
{
SDA=0;
SCL=1;
Delay4us();
SDA=1;
Delay4us();
SCL=0;
}
// 从机发送应答位
void Slave_ACK()
{
SDA=0;
SCL=1;
Delay4us();
SCL=0;
SDA=1;
}
// 从机发送非应答位
void Slave_NOACK()
{
SDA=1;
SCL=1;
Delay4us();
SCL=0;
SDA=0;
}
//发送一字节
void IIC_SendByte(uchar wd)
{
uchar i;
for(i=0;i<8;i++) //循环移入8位
{
SDA=(bit)(wd&0x80);_nop_();_nop_();
SCL=1;Delay4us();SCL=0;wd<<=1;
}
Delay4us();
SDA=1; //释放总线并准备读取应答
SCL=1;
Delay4us();
IIC_ERROR=SDA;//IIC_ERROR=1表示无应答
SCL=0;
Delay4us();
}
//接收一字节
uchar IIC_ReceiveByte()
{
uchar i,rd=0x00;
for(i=0;i<8;i++)
{
SCL=1;
rd<<=1;
rd|=SDA;
Delay4us();
SCL=0;
Delay4us();
}
SCL=0;
Delay4us();
return rd;
}
//连续读入4路通道的A/D转换结果并保存到Recv_Buffer
void ADC_PCF8591(uchar CtrlByte)
{
uchar i;
IIC_Start();
//PCF8591地址定义1001****,高四位固定1001
//第3,2,1位对应A2,A1,A0第0位为读写标志位,1为读0为写
//下面代码中0x90,0x91分别为10010000,10010001
IIC_SendByte(0x90);// 发送写地址
if(IIC_ERROR==1)return;
// IIC_SendByte(CtrlByte);//发送控制字节
//if(IIC_ERROR==1)return;
//屏蔽上面两行会产生警告
IIC_Start();//重新发送开始命令
IIC_SendByte(0x91);// 发送读地址
if(IIC_ERROR==1)return;
IIC_ReceiveByte();//空读一次,调整读顺序
Slave_ACK(); //收到一字节后发送一个应答位
/*------------------------------
个人认为下面句子有问题,但是不知道怎么改,如果把
Recv_Buffer[i++]=IIC_ReceiveByte();中的++去掉,整个四组都是一个结果
但是加上好像有些重复,并且13组相同,还是不很好啊
*/
for(i=0;i<4;i++)
{
Recv_Buffer[i++]=IIC_ReceiveByte();
Slave_ACK();//收到一个字节后发送一个应答位
}
Slave_NOACK();
IIC_Stop();//收到一个字节后发送一个非应答位
}
// 向 PCF8591发送1字节进行AD转换
void DAC_PCF8591(uchar CtrlByte,uchar dat)
{
IIC_Start();
Delay4us();//启动I2C
IIC_SendByte(0x90); //发送地址字节
if(IIC_ERROR==1)return;
IIC_SendByte(CtrlByte); //发送控制字节
if(IIC_ERROR==1)return;
IIC_SendByte(dat);//发送待转换为模拟量的数值
if(IIC_ERROR==1)return;
IIC_Stop();
Delay4us();
Delay4us();
}
void timer0init()
{
PM=0;//传感器的输入信号
TMOD=0x11;//设置定时器0为工作方式1
TH0=(65536-40)/256;
TL0=(65536-40)%256;
ET0=1;//开定时器0中断
TR0=1;//启动定时器0
EA=0; //开总中断
}
//主程序
/*
PCF8591控制字节定义:0***0***,第3,7位固定为0
第6位取0时为模拟输入,取1时为模拟输出
第4,5位为00表示4路单端的模拟输入
第二位为自动递增标志,取1时自动递增
第0,1位取值为00,01,10,11分别表示通道0,1,2,3
调用ADC_PCF8591时参数为00000100,即0x04
调用DAC_PCF8591时参数为01000000,即0x40
*/
void main()
{
LCD_Initialise();
timer0init();
while(1)
{
ADC_PCF8591(0x04);
Convert_To_Voltage(Recv_Buffer[0]);
LCD_Line_1[2]=Voltage[2];
LCD_Line_1[4]=Voltage[1];
LCD_Line_1[5]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[1]);
LCD_Line_1[11]=Voltage[2];
LCD_Line_1[13]=Voltage[1];
LCD_Line_1[14]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[2]);
LCD_Line_2[2]=Voltage[2];
LCD_Line_2[4]=Voltage[1];
LCD_Line_2[5]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[3]);
LCD_Line_2[11]=Voltage[2];
LCD_Line_2[13]=Voltage[1];
LCD_Line_2[14]=Voltage[0];
// 液晶两行显示四个通道的转换结果
LCD_Display_A_Line(0x80, LCD_Line_1);
LCD_Display_A_Line(0x90, LCD_Line_2);
// 将0通道模拟转换后的数值重新转换为模拟量并从Aout输出
//通过LED亮度表现出来
// DAC_PCF8591(0x40,Recv_Buffer[0]);
}
}
void timer0() interrupt 1
{
int N;
TH0=(65536-40)/256;
TL0=(65536-40)%256;
N++;
//if(N==7)
//PM=1;
if(N==8)
PM=0;
if(N>=250)
{
PM=1;
N=0;
}
}
复制代码
pcf8591.zip
2018-6-18 13:05 上传
点击文件名下载附件
下载积分: 黑币 -5
2.4 KB, 下载次数: 12, 下载积分: 黑币 -5
主要文件,工程需自建
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1