Multisim怎么添加pcf8591 怎么接

基于DS1302、PCF8591、EEPROM的智能灌溉系统 - STM32/STM8技术论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
基于DS1302、PCF8591、EEPROM的智能灌溉系统
09:58:26  
& && && && && && && && && && && && && && && && &模拟智能灌溉系统
& & 实现土壤湿度测量、土壤湿度和时间显示、湿度阈值设定及存储等基本功能。
1、通过电位器输出电压信号模拟湿度传感器的输出信号,再通过PCF8591采集完成土壤湿度的测量。
2、DS1302提供时间信息,并在数码管上显示。
3、按键设置湿度阈值,并存储到EEPROM中。
4、继电器模拟灌溉设备。
5、自动模式:系统测量湿度,并根据湿度阈值判断打开或关闭灌溉设备。
& &&&手动模式:系统测量湿度,并根据湿度阈值判断是否提示湿度过低。提示后,需要人为打开灌溉设备。
智能灌溉系统的基本功能:& && && && && && &
1、系统上电后处于自动工作状态,系统初始温度阈值为50%,
& &低于则设备打开,高于则设备关闭,L1亮指示;
2、手动工作状态,通过按键控制或打开设备,L2亮指示;
& &系统处于手动工作状态时,若湿度低于阈值,蜂鸣器发出提示音,
& &可通过按键S6关闭提醒功能;
3、按键S7为系统工作状态切换按键;
& &手动工作状态:S6控制蜂鸣器启动与关闭;
& && && && && &&&S5打开设备;
& & & & & & & & & & & & & & & &&&S4关闭设备;
& &自动工作状态:S6为温度阈值调整按键,进入或退出调整界面;
& & & & & & & & & & & & & & & &&&S5阈值加1;
& & & & & & & & & & & & & & & &&&S4阈值减1;
4、DS1302提供实时时钟,初始时间08时30分;
模拟智能灌溉系统编译的.hex文件在附件中。
本文提供智能灌溉系统的主要源码:
#include&reg52.h&
#include&intrins.h&
#include&IIC.h&
#include&DS1302.h&
#include&KEY.h&
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};
//& & & & & & & & & & & & & & & & & & & & & & & & & & & &&&0& & & && & 1& & & & 2& & & &&&3& & & && &4& & & && & 5& & & & 6& & & &&&7& & & && &8& & & && & 9& & & & & & & &&&-
unsigned char dspbuf[8]={10,10,10,10,10,10,10,10};
unsigned char dspcom,flag,
& & & & & & & & & & & & & & & & & & & & & & & && &//当前湿度值
unsigned int hnumi_& & & & & & & & & & & & & & & & & & & & & & & && &//整型当前湿度值
unsigned int hnumidity_& & & & & & & & & & & & & & & & & & & && &//整型湿度阈值
& & & & & & & & & & & & & & & & & & & && &
unsigned char EEPROM_
sbit S7=P3^0;
void Timer_Init();& & & & & & & &
void Display();
void Hnumidity_Judge();& & & & & & & &&&//湿度值判断
void Display_Pro0();& & & & & & & & & & & &&&//显示数据处理
void Display_Pro1();& & & & & & & & & & & &&&//显示数据处理
void System_Change()
&&& & & & if(S7==0)
& & & && & if(S7==0)
& & & && & {
& & & & & & & && &AUTO_flag=~AUTO_
& & & & & & & && &while(!S7);
& & & && & }
void main()
& &&&Timer_Init();& & & & & & & & & & & && & //初始化定时器0,用于显示
& & & &&&ADC_Init();& & & & & & & & & & & && & //初始化ADC,用于采样湿度
& & & &&&DS1302_Init();& & & && && && && &//初始化DS1302,用于产生时间
& & & &&&DS1302_SetTime(Init);& & & & & & & && & //设置初始时间
& & & &&&EEPROM_Write(0x00,hnumidity);&&//设置初始湿度
& & & &&&while(1)
& & & &&&{
& & & & & & & & while(!AUTO_flag)& &//自动模式
& & & & & & & & {
& & & & & & & && & LED_temp=0;
& & & & & & & && & LED_Pro();& & & & & & & && && && && && & //指示灯L1亮
& & & & & & & && && & KEY_Scan();& & & & & & & & & & & && && && && &//按键扫描
& & & & & & & && && & if(!Display_flag)
& & & & & & & & & & & && &{
& & & & & & & & & & & && && &Display_Pro1();& && && && && && & //处理时间与当前湿度值数据等待显示
& & & & & & & & & & & & & & & &&&EEPROM_Write(0x00,hnumidity1);
& & & & & & & & & & & && &}
& & & & & & & && & if(flag&&set_flag)& & & & & & & & & & & & & & & & & & & & & & & && & //每200ms处理一次
& & & & & & & && & {
& & & & & & & && && & flag=0;
& & & & & & & & & & & && &hnumidity=EEPROM_Read(0x00);& & & && & //读取湿度阈值
& & & & & & & & & & & && &DS1302_GetTime();& & & & & & & && && && && &//读取当前时间
& & & & & & & & & & & && &hnumi=ADC_Read();& & & & & & & && && && && &//读取当前湿度值
& & & & & & & & & & & && &if(Display_flag)
& & & & & & & & & & & && &{
& & & & & & & & & & & && && &Display_Pro0();& && && && && && & //处理时间与当前湿度值数据等待显示
& & & & & & & & & & & && &}
& & & & & & & & & & & && &Hnumidity_Judge();& & & && && && && &//判断当前湿度值
& & & & & & & & & & & && &P0=0x00;& && && && && &//清楚LED数据对蜂鸣器、继电器的影响
& & & & & & & & & & & && &RELAY_Pro();& & & & & & & && && && && && & //启动还是关闭继电器
& & & & & & & && & }
& & & & & & & & }
& & & & & & & & while(AUTO_flag)& & & & //手动模式
& & & & & & & & {
& & & & & & & && & LED_temp=1;
& & & & & & & && & LED_Pro();& & & & & & & & & & & & & & & & & & & && & //指示灯L2亮
& & & & & & & && & hnumidity=EEPROM_Read(0x00);& & & && & //读取湿度阈值
& & & & & & & && &
& & & & & & & && & if(flag)& & & & & & & & & & & & & & & & & & & & & & & && & //每200ms处理一次
& & & & & & & && & {
& & & & & & & && && & flag=0;
& & & & & & & & & & & && &DS1302_GetTime();& & & & & & & &&&//读取当前时间
& & & & & & & & & & & && &hnumi=ADC_Read();& & & & & & & &&&//读取当前湿度值
& & & & & & & & & & & && &Display_Pro0();& && && &//处理时间与当前湿度值数据等待显示
& & & & & & & & & & & && &Hnumidity_Judge();& & & &&&//判断当前湿度值
& & & & & & & & & & & && &P0=0x00;& && && && && &//清楚LED数据对蜂鸣器、继电器的影响
& & & & & & & & & & & && &KEY_Scan();& & & & & & & & & & & && && && && &//按键扫描
& & & & & & & && && & BUZZER_Pro();& & & & & & & & & & & &&&//是否启动蜂鸣器
& & & & & & & & & & & && &RELAY_Pro();& & & & & & & && && &//启动还是关闭继电器
& & & & & & & && & }
& & & & & & & & }
& & & &&&}
void T0_Ser() interrupt 1
& &TH0=()/256;
& &TL0=()%256;
& &Display();
& &//EEPROM_Write(0x00,hnumidity);
& &System_Change();
& &if(++num==100)
& & & && &flag=1;
& & & && &num=0;
void Hnumidity_Judge()
& &if(hnumi&hnumidity)//湿度小于50%
& && &if(!AUTO_flag)//自动模式
& & & && &{
& & & && && &RELAY_temp=0;& & & & & & & & & & & &&&//启动设备
& & & && &}
& & & && &if(AUTO_flag&&count==1)//手动模式
& & & && &{
& & & && && &BUZZER_temp=0;& & & & & & & && && &//启动蜂鸣器
& & & && &}
& &if(hnumi&hnumidity|hnumi==hnumidity)//湿度大于50%
& & & && &if(!AUTO_flag)//自动模式
& & & && &{
& & & && && & RELAY_temp=1;& & & & & & & & & & & &&&//关闭设备
& & & && &}
& & & && &if(AUTO_flag&&count==1)//手动模式
& & & && &{
& & & && && & count=1;
& & & && &}
void Display_Pro0()
& &hnumi_int=(unsigned int)hnumi/2.56;
& &dspbuf[0]=now[2]/16;& & & & & & & & & & & & //时
& &dspbuf[1]=now[2]%16;
& &dspbuf[2]=11;
& &dspbuf[3]=now[0]/16;& & & & & & & & & & & & //分
& &dspbuf[4]=now[0]%16;
& &dspbuf[5]=10;
& &dspbuf[6]=hnumi_int/10;& & & & & & & & & & & & //当前湿度
& &dspbuf[7]=hnumi_int%10;
void Display_Pro1()
& &hnumidity_int=(unsigned int)hnumidity1/2.56;
& &dspbuf[0]=11;& & & & & & & &
& &dspbuf[1]=11;
& &dspbuf[2]=10;
& &dspbuf[3]=10;& & & & & & & & & & & & //分
& &dspbuf[4]=10;
& &dspbuf[5]=10;
& &dspbuf[6]=hnumidity_int/10;& & & & & & & & & & & & //当前湿度
& &dspbuf[7]=hnumidity_int%10;
void Timer_Init()
& &P2=((P2&0x1f)|0xa0);
& &P0&=0x00;& & & & & & & & & & & & & & & & & & & & //关闭蜂鸣器,继电器
& &P2&=0x1f;
& &TMOD|=0x01;
& &TH0=()/256;
& &TL0=()%256;
void Display()
& &P2=((P2&0x1f)|0xe0);
& &P2=((P2&0x1f)|0xc0);
& &P0=0x01&&
& &P2=((P2&0x1f)|0xe0);
& &P0=table[dspbuf[dspcom]];
& &P2&=0x1f;
& &if(++dspcom==8)dspcom=0;
由于篇幅的限制,基本的模块驱动这里省略,希望大家自己添加。
本帖子中包含更多资源
才可以下载或查看,没有帐号?
高级工程师
10:19:44  
20:37:02  
参考参考参考参考
12:18:16  
楼主发帖辛苦了,谢谢分享!!!!!!!!!!!!
助理工程师
09:15:34  
谢谢楼主的分享了哟
等待验证会员
09:59:58  
楼主发帖辛苦了,谢谢分享!!!!!!!!!!!
22:21:52  
good............................
工程师职场
Powered by
供应链服务
版权所有 (C) 深圳华强聚丰电子科技有限公司AD/DA转换 芯片PCF8591驱动 求助 - 单片机/MCU论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
AD/DA转换 芯片PCF8591驱动 求助
21:26:25  
俺的51开发板上的AD芯片是PCF8591,IIC总线的,想将AD转换的值实时显示在数码管上,同时还想利用LED灯亮度的变换来反映DA效果。结果数码管值总是不变化,LED灯也不亮,请大家帮忙找找问题,下面上图上代码
#include &reg52.h&
#include &intrins.h&
sbit SDA=P2^0;
sbit SCL=P2^1;
sbit DU=P2^6;// 段 码
sbit WE=P2^7;//位码
#define uchar unsigned char
#define uint&&unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
& && && && && && && && &0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delayms(uchar ms)
while(ms--)
&&for(i=0;i&120;i++);
void display(uint k)
P0=table[k/1000];
delayms(1);
P0=table[k%];
delayms(1);
P0=table[k%100/10];
delayms(1);
P0=table[k%10];
delayms(1);
void delayus(void)
_nop_();_nop_();
_nop_();_nop_();
_nop_();_nop_();
_nop_();_nop_();
void IIC_Start(void)
delayus();
delayus();
delayus();
void IIC_Stop(void)
delayus();
delayus();
delayus();
void IIC_Ack(void)
uchar i=0;
delayus();
while((SDA==1)&&(i&250))
delayus();
void IIC_NoAck(void)
delayus();
delayus();
delayus();
void IIC_WriteOneByte(uchar dat)
for(i=0;i&8;i++)
&&delayus();
&&if(dat&0x80)
&&dat=dat&&1;
&&delayus();
delayus();
delayus();
uchar IIC_ReadOneByte(void)
delayus();
delayus();
for(i=0;i&8;i++)
&&delayus();
&&dat&&=1;
&&dat|=(uchar)SDA;
&&delayus();
void DAC(uchar dat)
IIC_Start();
IIC_WriteOneByte(0x90);
IIC_Ack();
IIC_WriteOneByte(0x40);
IIC_Ack();
IIC_WriteOneByte(dat);
IIC_Ack();
IIC_Stop();
uchar ReadADC(unsigned char Chl)
& && & unsigned char D
& &&&IIC_Start();& && &&&//写入芯片地址
& &&&//Send(AddWr);
& &IIC_WriteOneByte(0x90);
& &&&IIC_Ack();
& && &IIC_WriteOneByte(0x40|Chl);//写入选择的通道,本程序只用单端输入,差分部分需要自行添加
& && && && && && &&&//Chl的值分别为0、1、2、3,分别代表1-4通道
& &&&IIC_Ack();
& &&&IIC_Start();
& &&&IIC_WriteOneByte(0X91);& & //读入地址
& &&&IIC_Ack();
& &&&Data=IIC_ReadOneByte();& & //读数据
& &&&SCL=0;
& &&&IIC_NoAck();
& &&&IIC_Stop();
& &&&return D& &//返回值
void main()
uchar temp,
DAC(temp);
&&ad=ReadADC(2)
&&display(ad);
本帖子中包含更多资源
才可以下载或查看,没有帐号?
21:41:00  
/*******************************************************************************
* 实验名& & & & & & & & & & & && & :AD和DA实验
* 使用的IO& & & && && &:
* 实验效果& && & :LCD1602显示读取到的AD值
*& & & & 注意& & & & & & & & & & & & & & & & & & & &&&:
*******************************************************************************/
#include&reg51.h&
#include&i2c.h&
#include&lcd.h&
#define&&WRITEADDR 0x90
#define&&READADDR&&0x91
void Pcf8591SendByte(unsigned char channel);
unsigned char Pcf8591ReadByte();
void Pcf8591DaConversion(unsigned char value);
/*******************************************************************************
* 函数名& && && &: main
* 函数功能& & & & & & & && & : 主函数
* 输入& && && &&&: 无
* 输出& && && && & & &&&: 无
*******************************************************************************/
void main()
& & & & unsigned int adNum[5];
& & & & float value0;
& & & & LcdInit();
& & & & while(1)
& & & & {& & & &
& & & & & & & & //--显示电位器电压--//
& & & & & & & & Pcf8591SendByte(0);& && && && & //发送电位器转换命令
& & & & & & & & //--由于8591在第一次读取的时候是读取到的上次转换的结果--//
& & & & & & & & //--所以我们先读一次,只是读到的数据不做处理--//
& & & & & & & & adNum[0]=& & & & Pcf8591ReadByte()*2;//将前一次转换结果读走
& & & & & & & & //--在读走上一次转换结果之后,才开始启动下一次转换,需要一点时间--//
& & & & & & & & //--为了不浪费单片机的资源,让单片机空着,我们直接发送给我们下次--//
& & & & & & & & //--要读取的命令,做一些数据处理和显示当做延时--//
& & & & & & & & LcdWriteCom(0x80+0x46);& & & & & & & & & & & && && & //发送显示坐标
& & & & & & & & LcdWriteData('0'+adNum[3]/1000);& & & && &//发送显示数据
& & & & & & & & LcdWriteData('0'+adNum[3]%);
& & & & & & & & LcdWriteData('0'+adNum[3]%100/10);
& & & & & & & & LcdWriteData('0'+adNum[3]%10);
& & & & & & & & Pcf8591SendByte(1);& && && && & //发送热敏转换命令
& & & & & & & & adNum[0]=& & & & Pcf8591ReadByte()*2;//读取电位器转换结果
& & & & & & & & //--读取走了,上一次转换结果就是电位器的转换结果之后,热敏的转换开始--//
& & & & & & & & //--我们继续做一些处理当延时。--//
& & & & & & & & //--我们8591每读取到一个1就表示5/256V,所以要知道电压值就乘以0.01953--//
& & & & & & & & value0=adNum[0]/2*0.01953;&&//转为电压值
& & & & & & & & adNum[0]=value0*100;& && &&&//保留两位小数
& & & & & & & & LcdWriteCom(0x80);
& & & & & & & & LcdWriteData('0'+adNum[0]%);
& & & & & & & & LcdWriteData('.');
& & & & & & & & LcdWriteData('0'+adNum[0]%100/10);
& & & & & & & & LcdWriteData('0'+adNum[0]%10);
& & & & & & & & LcdWriteData('V');
& & & & & & & & Pcf8591SendByte(2); & & & && && & //发送光敏转换命令
& & & & & & & & adNum[1]=Pcf8591ReadByte()*2; //ADC1读取热敏
& & & & & & & & //--一下读取的方式跟上面一样处理--//
& & & & & & & & //--读光敏--//
& & & & & & & & LcdWriteCom(0x86);
& & & & & & & & LcdWriteData('0'+adNum[1]/1000);& & & &
& & & & & & & & LcdWriteData('0'+adNum[1]%);
& & & & & & & & LcdWriteData('0'+adNum[1]%100/10);
& & & & & & & & LcdWriteData('0'+adNum[1]%10);
& & & & & & & &
& & & & & & & & Pcf8591SendByte(3);& & & && && && && &//发送外部输入电压转换命令
& & & & & & & & adNum[2]=Pcf8591ReadByte()*2;&&//ADC2读取光敏
& & & & & & & & //--读取外部输入电压--//
& & & & & & & & LcdWriteCom(0x80+0x40);
& & & & & & & & LcdWriteData('0');
& & & & & & & & LcdWriteData('0'+adNum[2]/1000);& & & &
& & & & & & & & LcdWriteData('0'+adNum[2]%);
& & & & & & & & LcdWriteData('0'+adNum[2]%100/10);
& & & & & & & & LcdWriteData('0'+adNum[2]%10);
& & & & & & & & adNum[3]=Pcf8591ReadByte()*2;&&//ADC3读取外部输入电压
& & & & & & & & //--DA输出--//
& & & & & & & & adNum[4]=adNum[0];
& & & & & & & & Pcf8591DaConversion(adNum[4]/2); //DAC& & & && &数模转换
& & & & & & & &
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &
& & & & & & & & & & & & & & & &&&
/*******************************************************************************
* 函数名& && && &: Pcf8591SendByte
* 函数功能& & & & & & & && & : 写入一个控制命令
* 输入& && && &&&: channel(转换通道)
* 输出& && && && & & &&&: 无
*******************************************************************************/
void Pcf8591SendByte(unsigned char channel)
& & & & I2cStart();
& & & & I2cSendByte(WRITEADDR);//发送写器件地址
& & & & I2cSendByte(0x40|channel);//发送控制寄存器
& & & & I2cStop();
/*******************************************************************************
* 函数名& && && &: Pcf8591ReadByte
* 函数功能& & & & & & & && & : 读取一个转换值
* 输入& && && &&&: 无
* 输出& && && && & & &&&: dat
*******************************************************************************/
unsigned char Pcf8591ReadByte()
& & & & I2cStart();
& & & & I2cSendByte(READADDR);//发送读器件地址
& & & & dat=I2cReadByte();//读取数据
& & & & I2cStop();& && && & //结束总线
/*******************************************************************************
* 函数名& && && &: Pcf8591DaConversion
* 函数功能& & & & & & & && & : PCF8591的输出端输出模拟量
* 输入& && && &&&: value(转换的数值)
* 输出& && && && & & &&&: 无
*******************************************************************************/
void Pcf8591DaConversion(unsigned char value)
& & & & I2cStart();
& & & & I2cSendByte(WRITEADDR);//发送写器件地址
& & & & I2cSendByte(0x40);//开启DA写到控制寄存器
& & & & I2cSendByte(value);//发送转换数值
& & & & I2cStop();& & & &
21:41:27  
你参考一下 ,哈
01:22:58  
15:10:18  
666666,,,& && &
22:14:31  
等待验证会员
22:57:04  
我也遇到和你一样的问题
等待验证会员
15:45:54  
我也遇到和你一样的问题
感觉很吊的样子
Powered by
供应链服务
版权所有 (C) 深圳华强聚丰电子科技有限公司PCF8591 AD转换程序
> PCF8591 AD转换程序
PCF8591 AD转换程序
//-----------------------函数声明,变量定义------------------------#include #include sbit SCL=P1^2; // 将p1.2口模拟时钟口sbit SDA=P1^3; // 将p1.3口模拟数据口#define uchar unsigned char#define uint unsigned int#define disdata P0 //显示数据码输出口sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;本文引用地址:uint data dis[4]={0x00,0x00,0x00,0x00}; //定义3个显示数据单元和1个数据存储单元uchar code dis4[] = {"1- . V 2- . V"};uchar code dis5[] = {"3- . V 4- . V"};#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};bit bdata SystemE //从机错误标志位/*********************** PCF8591专用变量定义 ***********************/#definePCF8591_WRITE0x90#definePCF8591_READ 0x91#define NUM 4
//接收和发送缓存区的深度uchar idata receivebuf[NUM]; //数据接收缓冲区/*******************************************************************//* *//* 延时函数 *//* *//*******************************************************************/void delay(int ms){ while(ms--){ for(i=0;i<250;i++) { _nop_();_nop_();_nop_();_nop_(); }}}/*******************************************************************//* *//*检查LCD忙状态 *//*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 *//* *//*******************************************************************/bit lcd_busy(){ LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP(); result = (bit)(P0&0x80); LCD_EN = 0; return(result);}/*******************************************************************//* *//*写指令数据到LCD *//*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 *//* *//*******************************************************************/void lcd_wcmd(uchar cmd){ while(lcd_busy()); LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; _nop_(); _nop_(); P0 = delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0;}/*******************************************************************//* *//*写显示数据到LCD *//*RS=H,RW=L,E=高脉冲,D0-D7=数据。 *//* *//*******************************************************************/void lcd_wdat(uchar dat){ while(lcd_busy()); LCD_RS = 1; LCD_RW = 0; LCD_EN = 0; P0 = delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0;}/*******************************************************************//* *//* LCD初始化设定 *//* *//*******************************************************************/void lcd_init(){ delay(15); lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据 delay(5); lcd_wcmd(0x38); delay(5); lcd_wcmd(0x38); delay(5); lcd_wcmd(0x0c); //显示开,关光标 delay(5); lcd_wcmd(0x06); //移动光标 delay(5); lcd_wcmd(0x01); //清除LCD的显示内容 delay(5);}/*******************************************************************//* *//* 设定显示位置 *//* *//*******************************************************************/void lcd_pos(uchar pos){ lcd_wcmd(pos | 0x80); //数据指针=80+地址变量}/******************************************************************//* *//* 数据处理与显示 *//* 将采集到的数据进行16进制转换为ASCLL码。 *//* *//******************************************************************/show_value(uchar ad_data){ dis[2]=ad_data/51; //AD值转换为3为BCD码,最大为5.00V。 dis[2]=dis[2]+0x30; //转换为ACSII码 dis[3]=ad_data%51; //余数暂存 dis[3]=dis[3]*10; //计算小数第一位 dis[1]=dis[3]/51; dis[1]=dis[1]+0x30; //转换为ACSII码 dis[3]=dis[3]%51; dis[3]=dis[3]*10; //计算小数第二位 dis[0]=dis[3]/51; // dis[0]=dis[0]+0x30; //转换为ACSII码}//-------------------------------------------------------------------// 函数名称: iic_start()// 函数功能: 启动I2C总线子程序//-------------------------------------------------------------------void iic_start(void){ //时钟保持高,数据线从高到低一次跳变,I2C通信开始SDA = 1;SCL = 1;delayNOP(); // 延时5us SDA = 0;delayNOP(); SCL = 0;}//-------------------------------------------------------------------// 函数名称: iic_stop()// 函数功能: 停止I2C总线数据传送子程序//-------------------------------------------------------------------void iic_stop(void){ SDA = 0;
//时钟保持高,数据线从低到高一次跳变,I2C通信停止SCL = 1;delayNOP();SDA = 1;delayNOP(); SCL = 0;}//------------------------------------------------------------------// 函数名称: iicInit_()// 函数功能: 初始化I2C总线子程序//------------------------------------------------------------------void iicInit(void) { SCL = 0; iic_stop(); }//-------------------------------------------------------------------// 函数名称: slave_ACK// 函数功能: 从机发送应答位子程序//-------------------------------------------------------------------void slave_ACK(void){SDA = 0;SCL = 1;delayNOP();SCL = 0;}//-------------------------------------------------------------------// 函数名称: slave_NOACK// 函数功能: 从机发送非应答位子程序,迫使数据传输过程结束//-------------------------------------------------------------------void slave_NOACK(void){SDA = 1;SCL = 1;delayNOP();SDA = 0; SCL = 0;}//-------------------------------------------------------------------// 函数名称: check_ACK// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束//-------------------------------------------------------------------void check_ACK(void){
SDA = 1; // 将p1.1设置成输入,必须先向端口写1SCL = 1;askflag = 0;delayNOP();if(SDA == 1) // 若SDA=1表明非应答,置位非应答标志askflag askflag = 1; SCL = 0;}//-------------------------------------------------------------------// 函数名称: IICSendByte// 入口参数: ch// 函数功能: 发送一个字节//-------------------------------------------------------------------void IICSendByte(uchar ch){ unsigned char idata n=8; // 向SDA上发送一位数据字节,共八位while(n--){if((ch&0x80) == 0x80) // 若要发送的数据最高位为1则发送位1 { SDA = 1; // 传送位1SCL = 1; delayNOP();//SDA = 0;SCL = 0; }else{SDA = 0; // 否则传送位0SCL = 1;delayNOP(); SCL = 0;}ch = ch<<1; // 数据左移一位}}//-------------------------------------------------------------------// 函数名称: IICreceiveByte// 返回接收的数据// 函数功能: 接收一字节子程序//-------------------------------------------------------------------uchar IICreceiveByte(void){uchar idata n=8; // 从SDA线上读取一上数据字节,共八位uchar tdata=0;while(n--){ SDA = 1; SCL = 1; tdata =tdata<<1; //左移一位 if(SDA == 1) tdata = tdata|0x01; // 若接收到的位为1,则数据的最后一位置1else tdata = tdata&0 // 否则数据的最后一位置0 SCL = 0; } return(tdata);}//-------------------------------------------------------------------// 函数名称: DAC_PCF8591// 入口参数: slave_add从机地址,n要发送的数据个数// 函数功能: 发送n位数据子程序//-------------------------------------------------------------------void DAC_PCF8591(uchar controlbyte,uchar w_data){iic_start(); // 启动I2CdelayNOP();IICSendByte(PCF8591_WRITE); // 发送地址位check_ACK(); // 检查应答位 if(askflag == 1) {SystemError = 1; // 若非应答,置错误标志位 } IICSendByte(controlbyte&0x77);//Control bytecheck_ACK(); //检查应答位 if(askflag == 1) {SystemError = 1; // 若非应答,置错误标志位 } IICSendByte(w_data); //data bytecheck_ACK(); // 检查应答位 if(askflag == 1) {SystemError = 1; // 若非应答表明器件错误或已坏,置错误标志位SystemError }iic_stop(); // 全部发完则停止delayNOP();delayNOP();delayNOP();delayNOP();}//-------------------------------------------------------------------// 函数名称: ADC_PCF8591// 入口参数: controlbyte控制字// 函数功能: 连续读入4路通道的A/D转换结果到receivebuf//-------------------------------------------------------------------void ADC_PCF8591(uchar controlbyte){ uchar idata receive_da,i=0;iic_start();IICSendByte(PCF8591_WRITE);//控制字check_ACK();if(askflag == 1){SystemError = 1;}IICSendByte(controlbyte);//控制字check_ACK();if(askflag == 1){SystemError = 1;} iic_start(); //重新发送开始命令 IICSendByte(PCF8591_READ);//控制字check_ACK();if(askflag == 1){SystemError = 1;} IICreceiveByte(); //空读一次,调整读顺序 slave_ACK(); //收到一个字节后发送一个应答位while(i<4){ receive_da=IICreceiveByte(); receivebuf[i++]=receive_ slave_ACK(); //收到一个字节后发送一个应答位}slave_NOACK(); //收到最后一个字节后发送一个非应答位iic_stop();}//-------------------------------------------------------------------// 函数名称: main// 函数功能: 主程序//-------------------------------------------------------------------main(){ uchar i,l; delay(10); //延时 lcd_init(); //初始化LCD lcd_pos(0); //设置显示位置为第一行的第1个字符 i = 0; while(dis4[i] != ) { //显示字符 lcd_wdat(dis4[i]); i++; } lcd_pos(0x40); //设置显示位置为第二行第1个字符 i = 0; while(dis5[i] != ) { lcd_wdat(dis5[i]); //显示字符 i++; } while(1) {iicInit(); //I2C总线初始化 ADC_PCF);if(SystemError == 1) //有错误,重新来 { iicInit(); //I2C总线初始化 ADC_PCF); }for(l=0;l<4;l++) { show_value(receivebuf[0]); //显示通道0 lcd_pos(0x02); lcd_wdat(dis[2]); //整数位显示 lcd_pos(0x04); lcd_wdat(dis[1]); //第一位小数显示 lcd_pos(0x05); lcd_wdat(dis[0]); //第二位小数显示 show_value(receivebuf[1]); //显示通道1 lcd_pos(0x0b); lcd_wdat(dis[2]); //整数位显示 lcd_pos(0x0d); lcd_wdat(dis[1]); //第一位小数显示 lcd_pos(0x0e); lcd_wdat(dis[0]); //第二位小数显示 show_value(receivebuf[2]); //显示通道2
lcd_pos(0x42); lcd_wdat(dis[2]); //整数位显示 lcd_pos(0x44); lcd_wdat(dis[1]); //第一位小数显示 lcd_pos(0x45); lcd_wdat(dis[0]); //第二位小数显示 show_value(receivebuf[3]); //显示通道3 lcd_pos(0x4b); lcd_wdat(dis[2]); //整数位显示 lcd_pos(0x4d); lcd_wdat(dis[1]); //第一位小数显示 lcd_pos(0x4e); lcd_wdat(dis[0]); //第二位小数显示 iicInit();
//I2C总线初始化 DAC_PCF,receivebuf[0]); //D/A输出 if(SystemError == 1) //有错误,重新来 {
iicInit(); //I2C总线初始化 DAC_PCF,receivebuf[0]); //D/A输出 } //delay(50); //延时 } }}
分享给小伙伴们:
我来说两句……
最新技术贴
微信公众号二
微信公众号一}

我要回帖

更多关于 pcf8591怎么用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信