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

📄 hard_i2c.c

📁 meg16 的所有功能实例
💻 C
字号:
/****************************************Copyright (c)**************************************************
**                               ADEmbed Development Co.,LTD.                                    
**                                 http://www.adembed.com
**--------------File Info-------------------------------------------------------------------------------
** File name:			Hard_I2C.c
** Last modified Date:  2008-12-13
** Last Version:		1.0
** Descriptions:		Hard_I2C 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);

#define rd_device_add                  0xa1
#define wr_device_add                  0xa0

//TWI状态定义
//MT 主方式传输  MR 主方式接收 
#define START 0x08  
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK  0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK  0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
//常用TWI操作(主模式写和主模式读)
#define Start()    	  (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define Stop()     	  (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define Wait()	   	  {while(!(TWCR&(1<<TWINT)));}     
#define TestAck() 	  (TWSR&0xf8)
#define SetAck()	  (TWCR|=(1<<TWEA))
#define SetNoAck()    (TWCR&=~(1<<TWEA))
#define Twi()	  	  (TWCR=(1<<TWINT)|(1<<TWEN))
#define Write8Bit(x)  {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} 
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);
unsigned char i2c_Write(unsigned char RomAddress,unsigned char Wdata);
unsigned char i2c_Read(unsigned char RomAddress);


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,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();
 TWSR = 0X03;							/* TWI clock prescaler (TWPS) value = 0 */	
 TWBR = 0X10;	

 TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
 
 Write_EN_DO;
 Write_EN_1;
 DISP_DATA[3]=i2c_Read(0x02);

 for(;;)
	{ 
	
	}
}


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


}

/******************************************
                I2C总线写一个字节
			    返回1:写成功
				返回非1:写失败
*******************************************/
unsigned char i2c_Write(unsigned char RomAddress,unsigned char Wdata) 
{unsigned char number=10;
 while(number--)
	  {
	  Start();//I2C启动
	  Wait();
	  if(TestAck()!=START) continue;//ACK
	  Write8Bit(wr_device_add);//写I2C从器件地址和写方式
	  Wait();
	  
	  if(TestAck()!=MT_SLA_ACK)
	  {putchar(0);
	   continue;//ACK
	  }
	  Write8Bit(RomAddress);//写24C02的ROM地址
	  Wait();
	  if(TestAck()!=MT_DATA_ACK) continue;//ACK
	  Write8Bit(Wdata);//写数据到24C02的ROM
	  Wait();
	  if(TestAck()!=MT_DATA_ACK) continue;//ACK
	  break;
	  }
	  Stop();//I2C停止
 	  Delay_ms(10);//延时10ms等EEPROM写完
	  return 1;
}
/******************************************
               I2C总线读一个字节
			   
*******************************************/
unsigned char i2c_Read(unsigned char RomAddress) 
 {char a=0x00;
  unsigned char temp=0;
  unsigned char number=10;
  
  while(number--)
	   {
	   Start();//I2C启动
	   Wait();
	   a=TestAck();
	  
	   if (a!=START) continue;//ACK	 
	   
	   Write8Bit(wr_device_add);//写I2C从器件地址和写方式
	   Wait(); 
   	   
	   if (TestAck()!=MT_SLA_ACK) continue;//ACK
	  

	   Write8Bit(RomAddress);//写STA013的ROM地址
	   Wait();
	   
	   if (TestAck()!=MT_DATA_ACK) continue;
	   Start();//I2C重新启动
	   Wait();
	   if (TestAck()!=RE_START)  continue;
	   
	   Write8Bit(rd_device_add);//写I2C从器件地址和读方式
	   Wait();
	   
	   if(TestAck()!=MR_SLA_ACK)  continue;//ACK
	   Twi();//启动主I2C读方式
	   
	   Wait();
	   
	   if(TestAck()!=MR_DATA_NOACK) continue;//ACK	
	   temp=TWDR;//读取I2C接收数据
	   
	   break;
	   }
       Stop();//I2C停止
	   
	   return temp;
	   
 }

⌨️ 快捷键说明

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