1. 芯片
使用的PCF8591,同样是使用IIC通信协议,相关的底层驱动代码都会提供。包括
- 开始信号
- 终止信号
- 写应答
- 读应答
- 写一个字节
- 读一个字节
我们要写的是两个函数
- 写函数
- 读函数
2. 编程的步骤
(1)对于写函数(地址:0x90)要有两个形参,因为是写函数,就要知道往哪里写,写什么数据。
- 开始信号
- 发送地址(0x90)
- 写应答
- 发送想要写的地址
- 写应答
- 发送数据
- 写应答
- 终止信号
- 专用延时函数()
(2)对于读函数(地址:0x91)要有一个形参,并且带有返回值。因为是读函数,就要知道在哪里读,读到的数据放哪里。
- 开始信号
- 发送地址(0x90)
- 写应答
- 发送想要在哪里读的地址 (蓝桥杯一般用到两个 0x01 (光敏)0x03(电位器))
- 写应答
- 终止信号
- 开始信号
- 发送地址(0x91)
- 写应答
- 接收数据
- 延时
- 终止信号
/*==================================
功能:旋转Rb2 通过数码管 观察其示数的变化。
模块:ADDA
芯片:PCF8591
//==================================*/
#include <STC15F2K60S2.H>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define DELAY_TIME 5
unsigned char code SMG_NoDot[18] = {0xc0,0xf9,0xa4,
0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,
0xc0,0x86,0x8e,0xbf,0xff};
uchar ddat;
//==========IIC总线协议源代码====================
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_readAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_writeAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
void operate_delay(unsigned char t)
{
unsigned char i;
while(t--)
{
for(i=0; i<112; i++);
}
}
//===============================================
//=============PCF8591写函数=================
void PCF8591write (uchar add,uchar dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_writeAck();
IIC_SendByte(add);
IIC_writeAck();
IIC_SendByte(dat);
IIC_writeAck();
IIC_Stop();
operate_delay(10);
}
//===============================================
//=============PCF8591读函数=========================
uchar PCF8591read (uchar cmd)
{
uchar temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_writeAck();
IIC_SendByte(cmd);
IIC_writeAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_writeAck();
temp = IIC_RecByte();
IIC_readAck(1);
operate_delay(10);
IIC_Stop();
return temp;
}
//===============================================
//===========数码管显示函数及初始化函数===========
void HC138init (uchar n)
{
switch (n)
{
case 4:
P2 = (P2&0x1f)|0x80;
break;
case 5:
P2 = (P2&0x1f)|0xa0;
break;
case 6:
P2 = (P2&0x1f)|0xc0;
break;
case 7:
P2 = (P2&0x1f)|0xe0;
break;
}
}
void allinit ()
{
HC138init (4);
P0 = 0xff;
HC138init (5);
P0 = 0x00;
HC138init (6);
P0 = 0xff;
HC138init (7);
P0 = 0xff;
}
void displaybit (uchar pos,uchar dat)
{
HC138init (6);
P0 = (0x01<<(pos-1));
HC138init (7);
P0 = SMG_NoDot[dat];
}
void Delay_ms (uchar t)
{
uchar i,j;
for(i=t;i>0;i--)
for(j=845;j>0;j--);
}
void display (uchar dat)
{
displaybit (1,dat / 100);
Delay_ms (50);
displaybit (2,(dat / 10)%10);
Delay_ms (50);
displaybit (3,dat%10);
Delay_ms (50);
}
void delay_smg (uchar t)
{
while(t--)
{
display (ddat);
}
}
//===============================================
void main ()
{
allinit ();
while(1)
{
ddat = PCF8591read (0x03); // 读取电位器的电压
display (ddat);
delay_smg(100);
}
}