【单片机学习笔记】(六)———IIC协议介绍、PCF8591、AT24C02

一、IIC协议介绍

总线启动:

SCL为高电平时,SDA由高电平向低电平变化

总线停止:

SCL为高电平时,SDA由低电平向高电平变化

应答信号:

在SCL为高电平时,接受设备将SDA拉为低电平表示传输正确,产生应答,否则为非应答。

IIC总线数据位的有效性规定:

IIC总线进行数据传送时,时钟信号SCL为高电平期间,数据线上的信号SDA必须保持稳定。只有SCL为低电平期间SDA上的电平才允许变化。因此在显示数据时,要在SCL为低的时候改变SDA。读数据时要在SCL为高的时候读SDA。

 

二、PCF8591

PCF8591地址定义

高四位固定不变

R/W:读1写0

器件地址:读0x91 写0x90

 

PCF8591读时序 A/D转换输出:

 

PCF8591写时序 D/A转换输出:


 

三、AT24C02

数据手册

Byte Write

Current Address Read

 Device Address

 

 

四、代码实现

AT24C02 将开机次数显示在数码管上

#include <STC15F2K60S2.h>
#include <iic.h>

void display();
void Timer0Init(void);
void write_eeprom(unsigned char add,unsigned char val);
unsigned char read_eeprom(unsigned char add);

code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共阳数码管段码
unsigned char dspbuf[]={11,11,11,11,11,11,11,11};//数据缓冲区
unsigned char dspcom=0;

//主函数
void main()
{
	unsigned char reset_cnt=0;//开机次数存储,最大存储值为255
	
	Timer0Init();
	EA=1;//打开总中断
	ET0=1;//打开定时器中断
	
//	write_eeprom(0x00,0x30);//EEPROM中存储的数据需要进行初始化
	
	reset_cnt=read_eeprom(0x10);//从AT24C02地址0x10中读取数据
	reset_cnt++;
	write_eeprom(0x10,reset_cnt);//向AT24C02地址0x10中写入数据
//	write_eeprom(0x10,0x00);

	//更新显示数据
	dspbuf[5]=reset_cnt/100;
	dspbuf[6]=reset_cnt%100/10;
	dspbuf[7]=reset_cnt%10;
	
	while(1);
}

void write_eeprom(unsigned char add,unsigned char val)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(val);
	IIC_WaitAck();
	IIC_Stop();
}

unsigned char read_eeprom(unsigned char add)
{
	unsigned char da;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	da=IIC_RecByte();
	IIC_SendAck(0);
	IIC_Stop();
	
	return da;
}

//定时器0初始化
void Timer0Init(void)		//2毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x9A;		//设置定时初值
	TH0 = 0xA9;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

//定时器0中断服务函数
void isr_timer_0(void)interrupt 1
{
	display();
}

//显示函数
void display()
{
	//消隐
	P2=((P2&0x1f)|0xe0);
	P0=0xff;
	P2&=0x1f;
	
	//位控制
	P2=((P2&0x1f)|0xc0);
	P0=(1<<dspcom);
	P2&=0x1f;
	
	//段选
	P2=((P2&0x1f)|0xe0);
	P0=tab[dspbuf[dspcom]];
	P2&=0x1f;
	
	if (++dspcom==8)
		dspcom=0;
}

PCF8591

#include <STC15F2K60S2.h>
#include <intrins.h>
#include <iic.h>

void display();
void Timer0Init(void);
void Delay10us();
void init_pcf8591(unsigned char channel);
unsigned char read_pcf8591(void);


code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0x7f};//共阳数码管段码
unsigned char dspbuf[]={11,11,11,11,11,11,11,11};//数据缓冲区
unsigned char dspcom=0;
unsigned char intr,ad_value;
unsigned int v_value;
bit flag_100;

//主函数
void main()
{
	
	Timer0Init();
	EA=1;//打开总中断
	ET0=1;//打开定时器中断
	
	while(1)
	{
		if (flag_100)
		{
			flag_100=0;
			init_pcf8591(0x03);
			ad_value=read_pcf8591();
			v_value=ad_value*100/51;
			
			//更新显示数据
			dspbuf[4]=v_value/100;
			dspbuf[5]=12;
			dspbuf[6]=v_value%100/10;
			dspbuf[7]=v_value%10;
		}
	}
}

void init_pcf8591(unsigned char channel)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(channel);
	IIC_WaitAck();
	IIC_Stop();
	Delay10us();
}

unsigned char read_pcf8591(void)
{
	unsigned char temp;
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	temp=IIC_RecByte();
	IIC_SendAck(0);
	IIC_Stop();
	return temp;
}

void Delay10us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 25;
	while (--i);
}


//定时器0初始化
void Timer0Init(void)		//2毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x9A;		//设置定时初值
	TH0 = 0xA9;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

//定时器0中断服务函数
void isr_timer_0(void)interrupt 1
{
	if (++intr==50)
	{
		intr=0;
		flag_100=1;
	}
	display();
}

//显示函数
void display()
{
	//消隐
	P2=((P2&0x1f)|0xe0);
	P0=0xff;
	P2&=0x1f;
	
	//位控制
	P2=((P2&0x1f)|0xc0);
	P0=(1<<dspcom);
	P2&=0x1f;
	
	//段选
	P2=((P2&0x1f)|0xe0);
	P0=tab[dspbuf[dspcom]];
	P2&=0x1f;
	
	if (++dspcom==8)
		dspcom=0;
}

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EstherYoo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值