#define uint8 unsigned char
#define uint16 unsigned int
#define uint32 unsigned long
#define SETBIT(x, y) (x |= y)
#define CLEARBIT(x, y) (x &= ~y)
#define CHECKBIT(x, y) (x & y)
#define PCBIT7 0x80
#define PCBIT6 0x40
#define PCBIT5 0x20
#define PCBIT4 0x10
#define PCBIT3 0x08
#define PCBIT2 0x04
#define PCBIT1 0x02
#define PCBIT0 0x01
/*-------------
FM24C256
--------------*/
#define SCL PCBIT0
#define SDA PCBIT1
#define I2CPORT PORTC
#define I2CPORTD DDRC
#define I2CPORTIN PINC
/*-------------------------------------------------------------
2010-04-16
CPU:Atmega32
晶振:4MHz
FM24C256-GTR
I/O模拟I2C时序控制铁电子程序
---------------------------------------------------------------*/
#define I2CReadCMD 0xa1
#define I2CWriteCMD 0xa0
#define SomeNops NOP();NOP();NOP()
uint8 I2CSlaveAckFlag=0;
void I2CPORTInit (void)
{
SETBIT(I2CPORTD,SCL); //设置SCL为输出
NOP();NOP();NOP();
SETBIT(I2CPORTD,SDA); //设置SDA为输出
NOP();NOP();NOP();
SETBIT(I2CPORT,SCL); //SCL=1
NOP();NOP();NOP();
SETBIT(I2CPORT,SDA); //SDA=1
NOP();NOP();NOP();
}
void I2CStart (void)
{
SETBIT(I2CPORTD,SDA); //设置SDA为输出
NOP();NOP();NOP();
SETBIT(I2CPORT,SCL); //SCL=1
SomeNops;
SETBIT(I2CPORT,SDA); //SDA=1
SomeNops;
CLEARBIT(I2CPORT,SDA); //SDA=0
SomeNops;
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
}
void I2CStop (void)
{
SETBIT(I2CPORTD,SDA); //设置SDA为输出
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
CLEARBIT(I2CPORT,SDA); //SDA=0
SomeNops;
SETBIT(I2CPORT,SCL); //SCL=1
SomeNops;
SETBIT(I2CPORT,SDA); //SDA=1
SomeNops;
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
}
void I2CHostAck (void)
{
SETBIT(I2CPORTD,SDA); //设置SDA为输出
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
CLEARBIT(I2CPORT,SDA); //SDA=0
SomeNops;
SETBIT(I2CPORT,SCL); //SCL=1
SomeNops;
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
}
void I2CSlaveAck (void)
{
SETBIT(I2CPORTD,SDA); //设置SDA为输出
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
SETBIT(I2CPORT,SDA); //SDA=1
SomeNops;
SETBIT(I2CPORT,SCL); //SCL=1
CLEARBIT(I2CPORTD,SDA); //设置SDA为输入
SomeNops;
I2CSlaveAckFlag=(I2CPORTIN&0x02);
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
}
void I2CNoAck(void)
{
SETBIT(I2CPORTD,SDA); //设置SDA为输出
SETBIT(I2CPORT,SDA); //SDA=1
SomeNops;
SETBIT(I2CPORT,SCL); //SCL=1
SomeNops;
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
}
/*-----------------------------------------------
读一个字节从I2C总线上
-----------------------------------------------*/
uint8 Read1Byte2I2c (void)
{
uint8 I2CByte=0;
uint8 I2CByteTemp=0;
uint8 i=0;
SETBIT(I2CPORTD,SDA); //设置SDA为输出
SETBIT(I2CPORT,SDA); //SDA=1
SomeNops;
CLEARBIT(I2CPORTD,SDA); //设置SDA为输入
SomeNops;
for(i=0;i<8;i++)
{
I2CByte<<=1;
SETBIT(I2CPORT,SCL); //SCL=1
SomeNops;
I2CByteTemp=(I2CPORTIN&0x02);
I2CByteTemp>>=1 ;
I2CByte |= I2CByteTemp;
CLEARBIT(I2CPORT,SCL); //SCL=0
SomeNops;
}
return (I2CByte);
}
/*-----------------------------------------------
写一个字节到I2C总线上
-----------------------------------------------*/
void Write1Byte2I2C (uint8 I2CByte)
{
uint8 i=0;
SETBIT(I2CPORTD,SDA); //设置SDA为输出
for(i=0;i<8;i++)
{
CLEARBIT(I2CPORT,SCL); //SCL=0
if( (I2CByte&0x80) == 0x80 )
SETBIT(I2CPORT, SDA); //SDA=1
else
CLEARBIT(I2CPORT,SDA); //SDA=0
NOP();NOP();
SETBIT(I2CPORT,SCL); //SCL=1
SomeNops;
I2CByte<<=1;
}
}
/*----------------------------------------------
从FM24C256中读出单个个字节
-----------------------------------------------*/
uint8 FM24C256Read1Byte (uint16 Address)
{
uint8 I2CByte=0;
I2CStart();
Write1Byte2I2C(I2CWriteCMD);
I2CSlaveAck();
Write1Byte2I2C(Address/256);
I2CSlaveAck();
Write1Byte2I2C(Address%256);
I2CSlaveAck();
I2CStart();
Write1Byte2I2C(I2CReadCMD);
I2CSlaveAck();
I2CByte=Read1Byte2I2c();
I2CNoAck();
I2CStop();
return (I2CByte);
}
/*----------------------------------------------
从FM24C256中读出多个个字节
-----------------------------------------------*/
void FM24C256Read (uint16 Address , uint16 ByteNumber , uint8 * DataPoint)
{
uint8 I2CDataTemp=0;
uint16 i=0;
I2CStart();
Write1Byte2I2C(I2CWriteCMD);
I2CSlaveAck();
Write1Byte2I2C(Address/256);
I2CSlaveAck();
Write1Byte2I2C(Address%256);
I2CSlaveAck();
I2CStart();
Write1Byte2I2C(I2CReadCMD);
I2CSlaveAck();
for(i=0;i<(ByteNumber-1);i++)
{
* (DataPoint+i)=Read1Byte2I2c();
I2CHostAck();
}
* (DataPoint+ByteNumber-1)=Read1Byte2I2c();
I2CNoAck();
I2CStop();
}
/*-----------------------------------------------
向FM24C256中写入单个或多个个字节
-----------------------------------------------*/
void FM24C256Write (uint16 Address , uint16 ByteNumber , uint8 * DataPoint)
{
uint16 i=0;
I2CStart();
Write1Byte2I2C(I2CWriteCMD);
I2CSlaveAck();
Write1Byte2I2C(Address/256);
I2CSlaveAck();
Write1Byte2I2C(Address%256);
I2CSlaveAck();
for(i=0;i<ByteNumber;i++)
{
Write1Byte2I2C( * (DataPoint+i) );
I2CSlaveAck();
}
I2CStop();
}
//ICC-AVR application builder : 2010-4-20 9:19:00
// Target : M32
// Crystal: 4.0000Mhz
#include <iom32v.h>
#include <macros.h>
#include <AVRdef.h>
#include "PUBLIC.H"
#include "MAIN.H"
extern void I2CPORTInit (void);
extern uint8 FM24C256Read1Byte (uint16 Address);
extern void FM24C256Read (uint16 Address , uint16 ByteNumber , uint8 * DataPoint);
extern void FM24C256Write (uint16 Address , uint16 ByteNumber , uint8 * DataPoint);
#define TestAddress 0x0010
uint8 TestTemp1=0;
uint8 TestTemp2=0;
uint8 TestArray1[10]={0,0,0,0,0,0,0,0,0,0};
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//
void main(void)
{
init_devices();
//SETBIT(I2CPORTD,SDA);
//SETBIT(I2CPORT,SDA);
//CLEARBIT(I2CPORTD,SDA);
//if( CHECKBIT(I2CPORTIN,SDA) )
//TestTemp1=0;
I2CPORTInit();
TestTemp2=FM24C256Read1Byte(TestAddress);
TestTemp1=0;
TestTemp1=0x0f;
FM24C256Write(TestAddress,1,&TestTemp1);
TestTemp1=0;
TestTemp2=FM24C256Read1Byte(TestAddress);
TestTemp1=0;
TestTemp1=0;
}
------------------------------------------------------------------
以上是我的程序,现在从任何地址读出一个字节都是0xff,写入0x0f后读出还是0xff,一开始我认为是读对了,因为一般储存器没写过应该是0xff的,但是仔细观察有无应答信号,在读FM24C256单个字节的函数(FM24C256Read1Byte)那里设了断点,发现就只有发送第一个命令字节是有正确应答的(低电平),后边都是高电平。所以好像读也不对。SomeNops试过5个NOP也不行,我用的4MHZ,那么一条NOP就是1/4微妙,看了FM24C256数据手册,最快能支持1MHZ。有用过铁电的朋友请发表下看法。谢谢。
我用的ICCAVR 7.22+AVRStudio最新版+JTAG ICE
主函数我用的向导生成然后加入自己的代码,因为看见向导那里可以设置晶振频率。 |
|