目录
一、竞赛板PCF8591相关资料解析
PCF8591是一款I2C总线的存储器芯片,竞赛现场提供了电路接口(竞赛板的店原理图)、PCF8591芯片资料(英文版)、基础程序模块(I2C总线驱动程序)。下面从竞赛的视角地掌握这些,快速地写出应用程序。
1、PCF8591硬件接口
从图中可见,PCF8591的与CPU芯片接口电路用了2个I/O口线:P2.0时钟线,P2.1数据线。在编写程序时对它们进行设置。图中AIN0~AIN3为模拟量输入端,AIN0接在J3的18引脚,作为外部接入信号输入。AIN1输入光强度信号,AIN3输入电位器调压信号。模拟量输出引脚(DAC)接到J3的19引脚。
2、PCF8591模块程序
竞赛现场提供了底层驱动程序,根据I2C总线的操作时序以C语言形式编写,具体模块如下:
void i2c_delay(unsigned char i);//I2C总线中一些必要的延时函数
void i2c_start(void);//产生I2C总线启动条件
void i2c_stop(void);//产生I2C总线停止条件
void operate_delay(unsigned char t);//读写操作过程中一些必要的延时
void i2c_sendbyte(unsigned char byt);//I2C发送一个字节的数据
unsigned char i2c_waitack(void); //等待应答
unsigned char i2c_receivebyte(void); //I2C接收一个字节数据
void i2c_sendack(unsigned char ackbit);//发送应答
在了解PCF8591芯片资料和操作时序后就可以根据上述函数快速地编写应用程序。
3、PCF8591芯片资料解读
(1)器件读写地址
上图是从PCF8591资料上截取的器件地址格式,由8位二进制数构成,高4位是固定的1001,A2、A1、A0是芯片的引脚地址,与芯片的工作电路有关,最低位是读/写,R/W=0为写操作地址,R/W=1为读操作地址。
结合前面的硬件接口电路,竞赛板上的PCF8591的写操作地址为:90h。读操作地址为91h。
(2)PCF8591控制字
PCF8591控制字为8位二进制数,其格式及定义如下:(PCF8591资料上截取)
其中的D7、D3位为0。
D1、D0:A/D通道选择,4个组合对应4个人通道。
D2:自动增量标志,1有效,对4个A/D通道自动循环转换。
D5、D4:A/D输入模式设置位。
4个单端输入方式,即4路输入对应4个通道。
3路差分输入,AIN3作为公共端,与其它3路构成差分输入,分别对应0、1、2通道。
单端和差分混合模式,AIN0、AIN1单端输入,对应通道0、1,AIN2与AIN3构成差分输入,对应通道2。
2路差分输入,AIN0与AIN1构成差分输入,对应通道0,AIN2与AIN3构成差分输入,对应通道1。
D6:模拟量输出使能标志,1有效。
结合硬件接口电路,竞赛板上的PCF8591A/D输入模式只能是4路单端输入模式。
(3)PCF8591工作时序
上图为PCF8591D/A转换时序,时序如下:
启动—发送写地址—等待应答—发送控制字—等待应答—发送数据—等待应答—停止
上图为PCF8591A/D转换时序的再次启动读部分,前面需加上开始启动部分,本例以1个通道的A/D转换为例,具体时序如下:
启动—发送写地址—等待应答—发送控制字—等待应答—启动—发送读地址—等待应答—读字节—发送应答非—停止
二、程序设计
1、完善I2C总线模块程序
(1)新建i2C.C模块同名的头文件
在头文件中对C函数进行声明,程序如下:
#ifndef __I2C_H
#define __I2C_H
//函数声明
void i2c_delay(unsigned char i);//I2C总线中一些必要的延时函数
void i2c_start(void);//产生I2C总线启动条件
void i2c_stop(void);//产生I2C总线停止条件
void operate_delay(unsigned char t);//读写操作过程中一些必要的延时
void i2c_sendbyte(unsigned char byt);//I2C发送一个字节的数据
unsigned char i2c_waitack(void); //等待应答
unsigned char i2c_receivebyte(void); //I2C接收一个字节数据
void i2c_sendack(unsigned char ackbit);//发送应答
//新增PCF8591操作函数
//PCF8591 A/D转换
unsigned char adc_pcf8591(void);
//PCF8591 D/A转换
void dac_pcf8591(unsigned char dat);
#endif
(2)在i2C.C文件添加对PCF8591的操作函数
引用寄存器定义头文件,硬件P2.0、P2.1进行定义,本例新增加2个函数:
新增部分程序如下:
#include "stc15f2k60s2.h"
#include "intrins.h"
#include "i2c.h"
#define DELAY_TIME 5
/** 定义I2C总线时钟线和数据线 */
sbit scl = P2^0;
sbit sda = P2^1;
//PCF8591 A/D转换 通道3
unsigned char adc_pcf8591(void)
{
unsigned char temp;
i2c_start(); //启动
i2c_sendbyte(0x90); //发送器件写地址
i2c_waitack(); //等待应答
i2c_sendbyte(0x03); //ADC通道3
i2c_waitack(); //等待应答
i2c_stop(); //停止
i2c_start(); //再次启动
i2c_sendbyte(0x91); //发送器件读地址
i2c_waitack(); //等待应答
temp = i2c_receivebyte(); //读A/D结果
i2c_sendack(1); //发送应答
i2c_stop(); //停止
return temp; //返回数据
}
//PCF8591 D/A转换
void dac_pcf8591(unsigned char dat)
{
i2c_start(); //启动
i2c_sendbyte(0x90); //发送器件写地址
i2c_waitack(); //等待应答
i2c_sendbyte(0x40); //DAC输出模式
i2c_waitack(); //等待应答
i2c_sendbyte(dat); //发送8位二进制数
i2c_waitack(); //等待应答
i2c_stop(); //停止
operate_delay(10); //延时
}
2、主函数功能修改
本例检测AIN3输入,结果在数码管上显示,结果正确的话数值在0~255之间。同时把A/D检测数据作为D/A转换的数据,用万用表检测J3的19引脚电压,调节电位器Rb2观察电压变化与数码管数据变化。程序如下:
#include "stc15f2k60s2.h"
#include "dis.h"
#include "key.h"
#include "i2c.h"
void main()
{
while(1)
{
dis();//数码管显示
key();//键盘
Vol=adc_pcf8591(); //A/D转换
dac_pcf8591(Vol); //D/A转换
}
}
3、数码管显示程序修改
在数码管程序的开头,将测量的A/D值送显示。修改程序如下:
Led1=10; //灭
Led2=10; //灭
Led3=10; //灭
Led4=10; //灭
Led5=10; //灭
Led6=Vol/100; //百位
Led7=Vol%100/10; //十位
Led8=Vol%10; //个位