标题: 用PCF8591接IIC总线直接输出DA的程序怎么写? [打印本页]
作者: liven丶 时间: 2018-11-20 20:28
标题: 用PCF8591接IIC总线直接输出DA的程序怎么写?
PCF8591的SCL和SDA随便接51单片机的两个I/O口上,A0-A1,AN0-AN3不接,能否输出想要的电压,程序应该怎么写好?
作者: zl2168 时间: 2018-11-21 10:58
本帖最后由 zl2168 于 2018-11-21 23:01 编辑
实例87 PCF8591 I2C串行D-A输出连续锯齿波
先Proteus仿真一下,确认有效。
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil C和Proteus》清华大学出版社ISBN 978-7-302-41682-1书中电路和程序设计有详细说明,程序语句条条有注解。
作者: liven丶 时间: 2018-11-21 19:34
#include<reg52.h>
//PCF8591相关定义
sbit SCL=P2^0;
sbit SDA=P2^1;
#define SCL_SET SCL=1
#define SCL_CLR SCL=1
#define SDA_SET SDA=1
#define SDA_CLR SDA=0
#define AddWr 0x90
#define AddRd 0x91
#define adCon 0x40
//LCD1602相关定义
sbit RS=P2^6;
sbit RW=P2^5;
sbit E=P2^7;
#define setRS RS=1
#define clrRS RS=0
#define setRW RW=1
#define clrRW RW=0
#define setE E=1
#define clrE E=0
unsigned int time=0;
unsigned char ADFlag=0;
unsigned char str[8]="Ai n.mv";
void delay(unsigned int cnt)
{
while(--cnt);
}
void delayms(unsigned int time)
{
unsigned int i;
for(i=0;i<time;i++)
delay(120);
}
void writeData(unsigned char Data)
{
setRS;
clrRW;
delay(1);
setE;
delay(1);
P0=Data;
delay(5);
clrE;
}
void writeCom(unsigned char Com)
{
clrRS;
clrRW;
delay(1);
setE;
delay(1);
P0=Com;
delay(5);
clrE;
}
//清屏函数
void clear_scr(void)
{
writeCom(0x01);
delayms(5);
}
void disStr(unsigned char x,unsigned char y,unsigned char *str)
{
if(y==0) writeCom(0x80+x); //第一行
else writeCom(0xc0+x); //第二行
while(*str)
{
writeData(*str);
str++;
}
}
void lcdlnitial()
{
writeCom(0x38); //显示模式设置
delayms(5);
writeCom(0x08); //显示关闭
clear_scr(); //清屏
writeCom(0x06); //显示光标移动设置
delayms(5);
writeCom(0x0C); //显示开及光标设置
}
void start()
{
SDA_SET;
delay(1);
SCL_SET;
delay(5);
SDA_CLR;
}
void stop()
{
SDA_CLR;
delay(1);
SCL_SET;
delay(5);
SDA_SET;
}
void ack()
{
SDA_CLR;
SCL_SET;
delay(1);
SCL_CLR;
}
void noAck()
{
SDA_SET;
SCL_SET;
delay(1);
SCL_CLR;
}
void send(unsigned char Data)
{
unsigned char i=0;
unsigned char temp=0;
temp=Data;
for(i=0;i<8;i++)
{
SCL_CLR;
delay(1);
if(temp&0x80)SDA_SET;
else SDA_CLR;
delay(1);
SCL_SET;
delay(1);
temp<<=1;
}
SCL_CLR;
}
unsigned char recive()
{
unsigned char i=0;
unsigned char temp=0;
SDA_SET;
for(i=0; i<8; i++)
{
SCL_CLR;
delay(1);
SCL_SET;
delay(2);
if(SDA) temp|=0x01;
else temp&=0xfe;
if(i<7) temp<<=1;
}
SCL_CLR;
return temp;
}
unsigned char read(unsigned char ch)
{
unsigned char temp=0;
start();
send(AddWr); //确认芯片
ack();
send(adCon|ch); //确认通道
ack();
//读出数据,放入temp
start();
send(AddRd);
ack();
temp=recive();
noAck();
stop();
return temp;
}
void DAC(unsigned char light)
{
start();
send(AddWr);
ack();
send(0x40); //写入控制位,使能DAC输出
ack();
send(light);
ack();
stop();
}
void dis(unsigned char *date)
{
float j;
unsigned int k;
unsigned char i=0;
unsigned char ch1, ch2, ch3;
for(i=0;i<4;i++)
{
j=date[i]*10/51;
k=(int)j;
ch1=i+48;
str[1]=ch1;
ch2=k/10+48;
str[3]=ch2;
ch3=k%10+48;
str[5]=ch3;
if(i>1) disStr(i*8-16,1,str);
else disStr(i*8,0,str);
}
}
void main()
{
unsigned char i=0;
unsigned char vot[4];
lcdlnitial();
while(1)
{
vot[3]=read(0);
vot[0]=read(1);
vot[1]=read(2);
vot[2]=read(3);
DAC(vot[0]);
dis(vot);
delayms(5);
}
}
这个程序是在百度里的,但仿真时,AOUT不会随A0的电压的改变而改变,有大神回答一下吗?
作者: liven丶 时间: 2018-11-22 14:02
完美的例子,谢谢
作者: liven丶 时间: 2018-11-22 14:04
是我自己打错了,这个程序是没问题的
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |