📄 i2c.c
字号:
/*
Important information of i2c
From the LPC2148 User Manual section 11.7.8:
I2C Bit Frequency = PCLK / (I2CSCLH + I2CSCLL)
PCLK is whatever you set it to when you set up when you set up VPBDIV
but that is based on CCLK which is set to some multiple of the crystal
frequency when you set up PLL0.
So, maybe the crystal is 12 MHz and the PLL multiplies by 5 so CCLK is
60 MHz. Then maybe VPBDIV is set to divide by 4 (if that is what you
want; it can divide by 1, 2 or 4) so PCLK is 15 MHz.
Now, maybe you want 100 kHz for the I2C bit frequency (slow I2C) so:
100,000 = (15000000) / (I2CSCLH + I2CSCLL)
400,000 = (30000000) / (I2CSCLH + I2CSCLL)
Then I2CSCLH + I2CSCLL = 30000000 / 400000 or 75.
100,000 = (30000000) / (I2CSCLH + I2CSCLL)
Then I2CSCLH + I2CSCLL = 30000000 / 100000 or 300.
Then is no reason the 2 values aren't the same so set them both for 75
to get 50% duty cycle on the clock. For a 400 kHz I2C, you need to
read the I2C spec to get the proper duty cycle. Google for it.
It all ties together but you have to start with crystal freq -> PLL
multiplication to get CCLK -> VPBDIV to get PCLK -> desired I2C clock
rate to get (I2CSCLH + I2CSCLL) -> I2C Spec to get the required duty
cycle if the I2C bit rate is not 100 kHz.
*/
#include "LPC21xx.h"
#include "i2c.h"
#include "myLib.h"
#include "uart.h"
/*
#define I2CONSET I2C->conset // Control Set Register
#define I2STAT I2C->stat // Status Register
#define I2DAT I2C->dat // Data Register
#define I2ADR I2C->adr // Slave Address Register
#define I2SCLH I2C->sclh // SCL Duty Cycle Register (high half word)
#define I2SCLL I2C->scll // SCL Duty Cycle Register (low half word)
#define I2CONCLR I2C->conclr // Control Clear Register
*/
void InitEEPROM(void)
{
// PCONP |= 0x00000080; //turn on power to I2C
PINSEL0 = (PINSEL0 & ~I2C_PINMASK) | I2C_PINSEL;
I2SCLH = 24;
I2SCLL = 50;
I2CONCLR = I2C_STA | I2C_STO | I2C_SI | I2C_AA;
I2CONSET = I2C_EN;
}//InitEEPROM
void AddressEEPROM(unsigned char ChipID, unsigned short Address)
{
do {
I2CONSET = I2C_STA | I2C_SI; //setup start condition
I2CONCLR = I2C_SI; //send start condition
while (~I2CONSET & I2C_SI); //wait for start to be sent
I2DAT = EEPROM_WRITE | (ChipID & 0x7) << 1; //load the EEPROM address
I2CONCLR = I2C_STA | I2C_SI; //send EEPROM address
while (~I2CONSET & I2C_SI); //wait for address to be sent
}while (I2STAT != 0x18); //repeat if no ACK received
I2DAT = (Address >> 8) & 0xFF; //load high address
I2CONCLR = I2C_SI; //send data
while (~I2CONSET & I2C_SI); //wait
I2DAT = Address & 0xFF; //load low address
I2CONCLR = I2C_SI; //send data
while (~I2CONSET & I2C_SI); //wait
}//AddressEEPROM
void WriteEEPROM(unsigned char ChipID, unsigned short Address, unsigned char Data)
{
AddressEEPROM(ChipID, Address);
I2DAT = Data; //load data
I2CONCLR = I2C_SI; //send data
while (~I2CONSET & I2C_SI); //wait for data to be sent
I2CONSET = I2C_STO; //setup stop condition
I2CONCLR = I2C_SI; //start sending stop
while (I2CONSET & I2C_STO); //wait for stop to be sent
}//WriteEEPROM
unsigned char ReadEEPROM (unsigned char ChipID)
{
unsigned char Data;
do
{
I2CONSET = I2C_STA | I2C_SI; //setup start condition
I2CONCLR = I2C_SI; //send start condition
while (~I2CONSET & I2C_SI); //wait for start to be sent
I2DAT = EEPROM_READ|(ChipID&0x07)<<1;//load address of eeprom
I2CONCLR = I2C_STA | I2C_SI; //start sending address
while (~I2CONSET & I2C_SI); //wait for address to be sent
} while (I2STAT != 0x40); //repeat if no ack received
I2CONCLR = I2C_SI; //start reading data
while (~I2CONSET & I2C_SI); //wait for data to be received
Data = I2DAT;
I2CONSET = I2C_STO; //setup stop condition
I2CONCLR = I2C_SI; //send stop condition
while (I2CONSET & I2C_STO); //wait for stop to be sent
return Data; //return the data
}//ReadEEPROM
unsigned long SizeEEPROM (unsigned char ChipID)
{
//This function returns the size of the EEPROM, in bytes
unsigned char TestByte;
unsigned long AddressPtr = 0x20000;
I2CONSET = I2C_STA | I2C_SI; //setup start condition
I2CONCLR = I2C_SI; //send start condition
while (~I2CONSET & I2C_SI); //wait for start to be sent
I2DAT = EEPROM_WRITE | (ChipID & 0x7) << 1; //load the EEPROM address
I2CONCLR = I2C_STA | I2C_SI; //send EEPROM address
while (~I2CONSET & I2C_SI); //wait for address to be sent
if (I2STAT != 0x18) //if chip does not ACK
return 0;
I2DAT = 0x00; //load high address
I2CONCLR = I2C_SI; //send data
while (~I2CONSET & I2C_SI); //wait
I2DAT = 0x00; //load low address
I2CONCLR = I2C_SI; //send data
while (~I2CONSET & I2C_SI); //wait
TestByte = ~ReadEEPROM(ChipID);
WriteEEPROM(ChipID, 0x0000, TestByte);
do {
AddressPtr >>=1;
AddressEEPROM(ChipID, AddressPtr);
} while (TestByte == ReadEEPROM(ChipID));
TestByte = ~TestByte;
WriteEEPROM(ChipID, 0x0000, TestByte);
do {
AddressPtr <<= 1;
AddressEEPROM(ChipID, AddressPtr);
} while (TestByte != ReadEEPROM(ChipID));
return AddressPtr;
}//SizeEEPROM
void testEEPROM(void)
{
WriteEEPROM(0,0,0xB5);
WriteEEPROM(0,1,'W');
WriteEEPROM(0,2,'I');
WriteEEPROM(0,3,'P');
uart0Puts("Data Write Successfully\r\n");
dlay(1000);
AddressEEPROM(0,0);
if (ReadEEPROM(0)==0xB5)
{
uart0Puts("First\r\n");
if (ReadEEPROM(0)== 'W')
{
uart0Puts("Second\r\n");
if (ReadEEPROM(0)== 'I')
{
uart0Puts("Third\r\n");
if (ReadEEPROM(0)== 'P')
{
uart0Puts("EEPROM Tested \r\n");
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -