⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 24c02.c

📁 meg16 的所有功能实例
💻 C
字号:
/****************************************Copyright (c)**************************************************
**                               ADEmbed Development Co.,LTD.                                    
**                                 http://www.adembed.com
**--------------File Info-------------------------------------------------------------------------------
** File name:			24c02.c
** Last modified Date:  2008-12-13
** Last Version:		1.0
** Descriptions:		24c02 Test.
** 
**------------------------------------------------------------------------------------------------------
** Created by:			junbolu
** Created date:		2008-12-13
** Version:				1.0
** Descriptions:		
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
**ICC-AVR application builder : 2008-12-13
**Target : M16
**Crystal: 7.3728Mhz
**PC0--->SCL		PC1--->SDA			  PD6--->Write_EN
**
**描述:按键K0被按下一次,数码管的最低位会加一,并存储在24C02中,下一次系统启动时,会读取此数据并显示。
**      此程序采用的软件模拟I2C方式完成的24C02的读写。
**
**涉及知识点:
**           软件模拟I2C
**           
**			
*******************************************************************************************************/

#include<iom16v.h>
#include<macros.h>
#include"Define.h"

#define		fose	                        7372800

#define     SCL                                 0
#define     SDA                                 1
 
#define 	i2c_ddr                         DDRC
#define 	i2c_port                        PORTC
#define 	i2c_pin                         PINC      

#define 	AT24C02_ADDR					0xA0  //EEPROM设备地址
//定义I2C的延迟参数
#define    DelayX	100			//7.3M=>1;	8.4M=>2.建议5,因为将来的ClockCPU可以是16M


#define    SCL_1    {i2c_port|=1<<SCL;Delay_us(DelayX);}
#define    SCL_0    {i2c_port&=~(1<<SCL);Delay_us(DelayX);}
#define    SDA_1    {i2c_port|=1<<SDA;Delay_us(DelayX);}
#define    SDA_0    {i2c_port&=~(1<<SDA);Delay_us(DelayX);}

#define	   Write_EN_DO        DDRD |= (1<<6);
#define	   Write_EN_1         PORTD|= (1<<6);
#define	   Write_EN_0         PORTD&=~(1<<6);


unsigned char DISP_NUM;							//显示的位数
unsigned char BitTab[]={0xFE,0xFD,0xFB,0xF7};	//三位位选码
unsigned char DispTab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //LED字形码
unsigned char DISP_DATA[4]={0,0,0,0};		    //显示的数字

void I2C_Ini(void);
 void IICStart(void);
 void IICStop(void);
 uint8 IICRecAck(void);
 uint8 IICReceiveByte(void);
 void IICSendByte(uint8 sendbyte);
 void IICNoAck(void);
 void IICACK(void);
 uint8 i2c_Read(uint8 subAddr,uint8 device);
 void i2c_Write(uint8 subAddr,uint8 device,uint8 data);



void Delay_us(unsigned int time)
{
while(time--);
}

void Delay_ms(unsigned int time)
{
while(time--)
	{
	Delay_us(1000);
	}
}
void INT0_Init()
{
 GIFR |=0X40;              //清楚标志位
 //MCUCR|=0X03; 			   //上升沿触发中断	
 MCUCR|=0X02;MCUCR&=~0X01; //下降沿触发中断	
 GICR |=0X40;  			   //使能外部中断0
}

#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
 DISP_DATA[3]++;
 if(DISP_DATA[3]>9)
     {
	 DISP_DATA[3]=0;
	 }
 Write_EN_0;
 i2c_Write(0x02,AT24C02_ADDR,DISP_DATA[3]);
 Write_EN_1;
}
//显示函数,DISP_NUM决定显示哪个LED
//采用共阴LED动态显示方法,定时中断函数里面调用
void Display(void)		
{
 PORTA=0x00;					   			//清除显示再位选
 PORTB=BitTab[DISP_NUM];					//PB口接位选
 PORTA=DispTab[DISP_DATA[DISP_NUM]];		//PA口接LED的段码

 
 DISP_NUM++;			//先显示高位,再显示低位
 if(DISP_NUM==4)
    DISP_NUM=0;
}

#pragma interrupt_handler timer0comp:20
void timer0comp (void)
{
 Display();
} 

void main(void)
{
 
 DDRA=0XFF;
 PORTA=0X00;
 DDRB=0X0F;
 PORTB=0X00;
 
 //按键0端口初始化
 DDRD &=~0x04;	   	//设置PD2为输入   	   						
 PORTD|=0x04;		//设置PD2为上拉
 
 INT0_Init();                 //TART初始化
 
 //t/c0初始化(10ms)
 TCCR0=0X0d;
 TCNT0=0X00;
 OCR0=0X48;
 TIMSK=0X02;

 //asm("sei");
 SEI();                       //全局中断使能
 
 I2C_Ini();
 
 Write_EN_DO;
 Write_EN_1;
 DISP_DATA[3]=i2c_Read(0x02,AT24C02_ADDR);

 for(;;)
	{ 
    
	}
}


//=======================================================================
//初始化端口
void I2C_Ini(void)
{
	i2c_ddr|=(1<<SCL);			//SCK为输出
	i2c_ddr|=(1<<SDA);		    //SDA为双向的,先设置为输出


}
//=======================================================================
//启动总线。根据IIC协议,SCL为1时,SDA从1转变为0。
void IICStart(void)
{   SCL_0;

	SDA_1;
	SCL_1;
	SDA_0;
	SCL_0;
}
//=======================================================================
//停止IIC总线。根据IIC协议,SCL为1时,SDA从0转变为1。
void IICStop(void)
{
	SCL_0;
	SDA_0;
	SCL_1;
	SDA_1;
	//SCL_0;
}
//=======================================================================
//检查应答位,向I2C写数据时,I2C设备(EEPROM)正常接受到数据后在第9周期发出0应答,
//如果不正常接受到数据,则不以0应答而进入待命状态。
//写数据后需检查I2C设备是否有0应答。
unsigned char IICRecAck(void)
{
	uint8 ack;

	SCL_0;
	SDA_0;
	SCL_1;
	
	i2c_ddr&=~(1<<SDA);			//设置SDA为输入
	i2c_port|=1<<SDA;			    //上拉
	ack=(i2c_pin & (1<<SDA));		//读SDA应答位
	i2c_ddr|=(1<<SDA);			    //恢复为输出
	
	SCL_0;
	return(ack);
}
//=======================================================================
//从IIC总线上读数据。
unsigned char IICReceiveByte(void)
{
	uint8 receivebyte=0,i=8;

	i2c_ddr&=~(1<<SDA);			    //设置SDA为输入
	i2c_port|=1<<SDA;		            //上拉
	i2c_port&=~(1<<SCL);
	
	while(i--)
	{
		SCL_1;
		receivebyte <<= 1;
		if(i2c_pin & (1<<SDA)) receivebyte |= 1;
		SCL_0;
	}
	
	i2c_ddr|=(1<<SDA);			       //恢复SDA为输出
	return(receivebyte);
}


//=======================================================================
//对IIC总线产生应答。读I2C设备时,如果下一步还要读则产生0应答。
void IICACK(void)
{
	SDA_0;
	SCL_1;
	SCL_0;
	
	SDA_1;
}
//=======================================================================
//不对IIC总线产生应答。读I2C设备时,如果下一步不需要读则产生1应答(即不应答)。
void IICNoAck(void)
{
	SDA_1;
	SCL_1;
	SCL_0;
}
//=======================================================================
//向IIC总线写数据。SCL=0时SDA的数据可改变,SCL=1时需保持SDA数据稳定。
void IICSendByte(unsigned char sendbyte)
{
	uint8 j=8;
	for(;j>0;j--)
	{
		SCL_0;
		
		if(sendbyte&0x80)	SDA_1		//SCL=0时写数据到SDA 
		else	            SDA_0
		  
		sendbyte<<=1;
		
		SCL_1;
	}
	SCL_0;
}

//=======================================================================
//通过I2C读STA013
unsigned char i2c_Read(unsigned char subAddr,uint8 device)
{   
	uint8 data=0;
	uint8 ErrorCount=10;
	//Delay_us(1200);
	
	while(ErrorCount--)
	{
		IICStart();
		IICSendByte(device);
		
		if(IICRecAck()) continue;			//如果为非0应答,重复写
		
 		IICSendByte(subAddr);	
 		if(IICRecAck()) continue;	//如果为非0应答,重复写
      	IICStart();
		IICSendByte(device | 0x01);	
		if(IICRecAck()) continue;
		
		
		data=IICReceiveByte();        //读数据,并发出1应答,表示不再读。
		IICNoAck();
		break;
	}
	IICStop();	
	return data;
}

//=======================================================================
void i2c_Write(unsigned char subAddr,unsigned char device,unsigned char data)
{
	uint8 ErrorCount=10;
	
	while(ErrorCount--)
	{
		IICStart();
		IICSendByte(device);	
		if(IICRecAck()) continue;			//如果为非0应答,重复写
 		IICSendByte(subAddr);	
 		if(IICRecAck()) continue;	//如果为非0应答,重复写
		
		IICSendByte(data);
   		IICACK();
   		
   		break;
    }
	
    IICStop();
	//Delay_us(1200);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -