【注意】
我在一开始由于第一次使用雅特力芯片,以为时钟脚和数据脚初始化为推挽输出也能用,但是这个芯片需要初始化为IIC复用功能,希望读者不要犯这个错误。
【硬件介绍】
AT24C64相信大家都不陌生,在学习51的时候相信大家都学过,在这边我就不多赘述了。直接点上代码。
【代码】
这是时钟脚和数据脚的初始化
文件名 at24c64.c
//引脚初始化
void IIC_Init(void)
{
gpio_init_type gpio_initstructure;
/* i2c periph clock enable */
crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE);
/* gpio configuration */
gpio_initstructure.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
gpio_initstructure.gpio_pull = GPIO_PULL_UP;
gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
/* configure i2c pins: scl */
gpio_initstructure.gpio_pins = GPIO_PINS_6;
gpio_init(GPIOF, &gpio_initstructure);
gpio_pin_mux_config(GPIOF, GPIO_PINS_SOURCE6, GPIO_MUX_0);
/* configure i2c pins: sda */
gpio_initstructure.gpio_pins = GPIO_PINS_7;
gpio_init(GPIOF, &gpio_initstructure);
gpio_pin_mux_config(GPIOF, GPIO_PINS_SOURCE7, GPIO_MUX_0);
}
//at24c64.c
#define SDAT_SET gpio_bits_set(GPIOF, GPIO_PINS_7)
#define SDAT_CLR gpio_bits_reset(GPIOF, GPIO_PINS_7)
#define TST_SDAT (gpio_input_data_bit_read(GPIOF, GPIO_PINS_7))
#define SCLK_SET gpio_bits_set(GPIOF, GPIO_PINS_6)
#define SCLK_CLR gpio_bits_reset(GPIOF, GPIO_PINS_6)
uchar i2c_i, i2c_cnt;
void SDA_Input_Mode()
{
gpio_init_type gpio_initstructure;
crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE);
gpio_initstructure.gpio_pins = GPIO_PINS_7;
gpio_initstructure.gpio_pull = GPIO_PULL_UP;
gpio_initstructure.gpio_mode = GPIO_MODE_INPUT;
gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
gpio_init(GPIOF, &gpio_initstructure);
}
void SDA_Output_Mode()
{
gpio_init_type gpio_initstructure;
crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE);
gpio_initstructure.gpio_pins = GPIO_PINS_7;
gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
gpio_initstructure.gpio_mode = GPIO_MODE_OUTPUT;
gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
gpio_init(GPIOF, &gpio_initstructure);
}
void SCL_Output_Mode()
{
gpio_init_type gpio_initstructure;
crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE);
gpio_initstructure.gpio_pins = GPIO_PINS_6;
gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
gpio_initstructure.gpio_mode = GPIO_MODE_OUTPUT;
gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
gpio_init(GPIOF, &gpio_initstructure);
}
void I2c_Delay(void)
{
delayInUs(5);
}
void Start(void)
{
SDA_Output_Mode();
SCL_Output_Mode();
SCLK_SET;
SDAT_SET;
I2c_Delay();
SDAT_CLR;
I2c_Delay();
SCLK_CLR;
}
void Stop(void)
{
SCLK_SET;
SDAT_CLR;
I2c_Delay();
SDAT_SET;
}
void Ack(void)
{
SDAT_CLR;
SCLK_SET;
I2c_Delay();
SCLK_CLR;
}
void NoAck(void)
{
SDAT_SET;
SCLK_SET;
I2c_Delay();
SCLK_CLR;
}
void I2c_Write_Byte(uchar wbyte)
{
for(i2c_i = 8; i2c_i > 0; i2c_i--)
{
if((wbyte & 0x80) == 0x80)
{
SDAT_SET;
}
else
{
SDAT_CLR;
}
SCLK_SET;
I2c_Delay();
SCLK_CLR;
wbyte <<= 1;
I2c_Delay();
}
I2c_Delay();
Ack();
}
uchar I2c_Read_Byte(void)
{
uchar rbyte;
rbyte = 0;
SDA_Input_Mode();
for(i2c_i = 0; i2c_i < 8; i2c_i++)
{
SCLK_SET;
rbyte <<= 1;
if(TST_SDAT)
{
rbyte |= 0x01;
}
I2c_Delay();
SCLK_CLR;
I2c_Delay();
}
SDA_Output_Mode();
return rbyte;
}
void I2c_Write_Data(uint addr, uchar wrbyte)
{
Start();
I2c_Write_Byte(0xa0);
I2c_Write_Byte(addr >> 8);
I2c_Write_Byte(addr & 0xff);
I2c_Write_Byte(wrbyte);
Stop();
delayInMs(6);
}
uchar I2c_Read_Data(uint addr)
{
Start();
I2c_Write_Byte(0xa0);
I2c_Write_Byte(addr >> 8);
I2c_Write_Byte(addr & 0xff);
Start();
I2c_Write_Byte(0xa1);
i2c_cnt = I2c_Read_Byte();
NoAck();
Stop();
return i2c_cnt;
}
void I2c_Write_Page(uint addr, uchar cnt, uchar *datapointer)
{
Start();
I2c_Write_Byte(0xa0);
I2c_Write_Byte(addr >> 8);
I2c_Write_Byte(addr & 0xff);
for(i2c_cnt = 0; i2c_cnt < cnt; i2c_cnt++)
{
I2c_Write_Byte(*datapointer);
datapointer++;
}
Stop();
delayInMs(5);
}
void I2c_Read_Page(uint addr, uchar cnt, uchar *datapointer)
{
Start();
I2c_Write_Byte(0xa0);
I2c_Write_Byte(addr >> 8);
I2c_Write_Byte(addr & 0xff);
Start();
I2c_Write_Byte(0xa1);
cnt -= 1;
for(i2c_cnt = cnt; i2c_cnt > 0; i2c_cnt--)
{
*datapointer = I2c_Read_Byte();
Ack();
datapointer++;
}
*datapointer = I2c_Read_Byte();
NoAck();
Stop();
}
void I2c_Write_Word(uint addr, uint wWord)
{
uchar tmpArr[2];
tmpArr[0] = (uchar)wWord;
tmpArr[1] = (uchar)wWord >> 8;
I2c_Write_Page(addr, 2, tmpArr);
}
uint I2c_Read_Word(uint addr)
{
uchar tmpArr[2];
uint rWord;
I2c_Read_Page(addr, 2, tmpArr);
rWord = tmpArr[1];
rWord = (rWord << 8) | tmpArr[0];
return rWord;
}
文件名 at24c64.h
#ifndef __AT24C64_H__
#define __AT24C64_H__
uchar I2c_Read_Data(uint addr);
void I2c_Write_Data(uint addr, uchar wrbyte);
void I2c_Write_Word(uint addr, uint wWord);
uint I2c_Read_Word(uint addr);
void I2c_Write_Page(uint addr, uchar cnt, uchar *datapointer);
void I2c_Read_Page(uint addr, uchar cnt, uchar *datapointer);
#endif
以上是本文全部内容,驱动代码都是测试正确的,需要的读者可以直接用,但是还是建议自己多实践才能真正理解。