1.M24c08.c
#include "M24c08.h"
#include "Delay.h"
#define M24C08_READ_ADDR (0xA1) //M24C08的I2C地址(7Bit模式)
#define M24C08_WRITE_ADDR (0xA0)
#define I2C_DELAY() rt_hw_us_delay(2)
static void i2c_start(void)
{
M24C08_SCL_1;
M24C08_SDA_1;
I2C_DELAY();
M24C08_SDA_0;
I2C_DELAY();
M24C08_SCL_0;
I2C_DELAY();
}
static void i2c_stop(void)
{
M24C08_SDA_0;
I2C_DELAY();
M24C08_SCL_1;
I2C_DELAY();
M24C08_SDA_1;
I2C_DELAY();
}
static void i2c_ack(void)
{
M24C08_SDA_0;
I2C_DELAY();
M24C08_SCL_1;
I2C_DELAY();
M24C08_SCL_0;
I2C_DELAY();
M24C08_SDA_1;
I2C_DELAY();
}
static void i2c_nack(void)
{
M24C08_SDA_1;
I2C_DELAY();
M24C08_SCL_1;
I2C_DELAY();
M24C08_SCL_0;
I2C_DELAY();
}
static uint8_t i2c_write_byte(uint8_t byte)
{
uint8_t i, ack;
for (i = 0; i < 8; i++) {
if (byte & 0x80) {
M24C08_SDA_1;
} else {
M24C08_SDA_0;
}
I2C_DELAY();
M24C08_SCL_1;
I2C_DELAY();
M24C08_SCL_0;
I2C_DELAY();
byte <<= 1;
}
M24C08_SDA_1;
I2C_DELAY();
M24C08_SCL_1;
I2C_DELAY();
ack = M24C08_SDA_INPUT ? 0 : 1;
M24C08_SCL_0;
I2C_DELAY();
return ack;
}
static uint8_t i2c_read_byte(uint8_t ack)
{
uint8_t i, byte = 0;
M24C08_SDA_1;
for (i = 0; i < 8; i++) {
byte <<= 1;
M24C08_SCL_1;
I2C_DELAY();
if (M24C08_SDA_INPUT) {
byte |= 0x01;
}
M24C08_SCL_0;
I2C_DELAY();
}
if (ack) {
i2c_ack();
} else {
i2c_nack();
}
return byte;
}
/*
函数功能: 写一个字节
函数参数:
uint16_t addr 数据的位置(0~1023)
uint8_t data 数据范围(0~255)
*/
void M24C08_WriteOneByte(uint16_t addr,uint8_t data)
{
uint8_t read_device_addr=M24C08_READ_ADDR;
uint8_t write_device_addr=M24C08_WRITE_ADDR;
if(addr<256*1) //第一个块
{
write_device_addr|=0x0<<1;
read_device_addr|=0x0<<1;
}
else if(addr<256*2) //第二个块
{
write_device_addr|=0x1<<1;
read_device_addr|=0x1<<1;
}
else if(addr<256*3) //第三个块
{
write_device_addr|=0x2<<1;
read_device_addr|=0x2<<1;
}
else if(addr<256*4) //第四个块
{
write_device_addr|=0x3<<1;
read_device_addr|=0x3<<1;
}
addr=addr%256; //得到地址范围
i2c_start();//起始信号
i2c_write_byte(write_device_addr);//发送设备地址
i2c_write_byte(addr); //数据存放的地址
i2c_write_byte(data); //发送将要存放的数据
i2c_stop(); //停止信号
rt_hw_us_delay(10000); //等待写
}
/*
函数功能: 读一个字节
函数参数:
uint16_t addr 数据的位置(0~1023)
返回值: 读到的数据
*/
uint8_t M24C08_ReadOneByte(uint16_t addr)
{
uint8_t data=0;
uint8_t read_device_addr=M24C08_READ_ADDR;
uint8_t write_device_addr=M24C08_WRITE_ADDR;
if(addr<256*1) //第一个块
{
write_device_addr|=0x0<<1;
read_device_addr|=0x0<<1;
}
else if(addr<256*2) //第二个块
{
write_device_addr|=0x1<<1;
read_device_addr|=0x1<<1;
}
else if(addr<256*3) //第三个块
{
write_device_addr|=0x2<<1;
read_device_addr|=0x2<<1;
}
else if(addr<256*4) //第四个块
{
write_device_addr|=0x3<<1;
read_device_addr|=0x3<<1;
}
addr=addr%256; //得到地址范围
i2c_start();//起始信号
i2c_write_byte(write_device_addr);//发送设备地址
i2c_write_byte(addr); //将要读取数据的地址
i2c_start();//起始信号
i2c_write_byte(read_device_addr);//发送设备地址
data=i2c_read_byte(0);//读取数据
i2c_stop(); //停止信号
return data;
}
/*
函数功能: 从指定位置读取指定长度的数据
函数参数:
uint16_t addr 数据的位置(0~1023)
uint16_t len 读取的长度
uint8_t *buffer 存放读取的数据
返回值: 读到的数据
*/
void M24C08_ReadByte(uint16_t addr,uint16_t len,uint8_t *buffer)
{
uint16_t i=0;
uint8_t read_device_addr=M24C08_READ_ADDR;
uint8_t write_device_addr=M24C08_WRITE_ADDR;
if(addr<256*1) //第一个块
{
write_device_addr|=0x0<<1;
read_device_addr|=0x0<<1;
}
else if(addr<256*2) //第二个块
{
write_device_addr|=0x1<<1;
read_device_addr|=0x1<<1;
}
else if(addr<256*3) //第三个块
{
write_device_addr|=0x2<<1;
read_device_addr|=0x2<<1;
}
else if(addr<256*4) //第四个块
{
write_device_addr|=0x3<<1;
read_device_addr|=0x3<<1;
}
i2c_start();//起始信号
i2c_write_byte(write_device_addr);//发送设备地址
i2c_write_byte(addr); //将要读取数据的地址
i2c_start();//起始信号
i2c_write_byte(read_device_addr);//发送设备地址
for(i=0;i<len;i++)
{
buffer[i]=i2c_read_byte(i == len - 1 ? 0 : 1);//读取数据
}
i2c_stop(); //停止信号
}
/*
函数功能: M24C08页写函数
函数参数:
uint16_t addr 写入的位置(0~1023)
uint16_t len 写入的长度(每页16字节)
uint8_t *buffer 存放读取的数据
*/
void M24C08_PageWrite(uint16_t addr,uint16_t len,uint8_t *buffer)
{
uint16_t i=0;
uint8_t read_device_addr=M24C08_READ_ADDR;
uint8_t write_device_addr=M24C08_WRITE_ADDR;
if(addr<256*1) //第一个块
{
write_device_addr|=0x0<<1;
read_device_addr|=0x0<<1;
}
else if(addr<256*2) //第二个块
{
write_device_addr|=0x1<<1;
read_device_addr|=0x1<<1;
}
else if(addr<256*3) //第三个块
{
write_device_addr|=0x2<<1;
read_device_addr|=0x2<<1;
}
else if(addr<256*4) //第四个块
{
write_device_addr|=0x3<<1;
read_device_addr|=0x3<<1;
}
addr=addr%256; //得到地址范围
i2c_start();//起始信号
i2c_write_byte(write_device_addr);//发送设备地址
i2c_write_byte(addr); //数据存放的地址
for(i=0;i<len;i++)
{
i2c_write_byte(buffer[i]); //发送将要存放的数据
}
i2c_stop(); //停止信号
rt_hw_us_delay(10000); //等待写
}
/*
函数功能: 从指定位置写入指定长度的数据
函数参数:
uint16_t addr 数据的位置(0~1023)
uint16_t len 写入的长度
uint8_t *buffer 存放即将写入的数据
返回值: 读到的数据
*/
void M24C08_WriteByte(uint16_t addr,uint16_t len,uint8_t *buffer)
{
uint8_t page_byte=16-addr%16; //得到当前页剩余的字节数量
if(page_byte>len) //判断当前页剩余的字节空间是否够写
{
page_byte=len; //表示一次性可以写完
}
while(1)
{
M24C08_PageWrite(addr,page_byte,buffer); //写一页
if(page_byte==len)break; //写完了
buffer+=page_byte; //指针偏移
addr+=page_byte;//地址偏移
len-=page_byte;//得到剩余没有写完的长度
if(len>16)page_byte=16;
else page_byte=len; //一次可以写完
}
}
//void i2c_write(uint8_t addr, uint8_t *data, uint16_t len)
//{
// uint16_t i;
// i2c_start();
// i2c_write_byte(M24C08_I2C_ADDR << 1);
// i2c_write_byte(addr);
// for (i = 0; i < len; i++) {
// i2c_write_byte(data[i]);
// }
// i2c_stop();
//}
//void M24C08_Write(uint8_t addr, uint8_t *data, uint16_t len)
//{
// uint16_t In,Re;
// In = (uint16_t)(len/16);
// Re = (uint16_t)(len%16);
// for(uint16_t i = 0;i < In;i++)
// {
// i2c_write(addr+0x10*i,&data[i*16],16);
// }
// i2c_write(addr+0x10*In,&data[In*16],Re);
//}
//void i2c_read(uint8_t addr, uint8_t *data, uint16_t len)
//{
// uint16_t i;
// i2c_start();
// i2c_write_byte(M24C08_I2C_ADDR << 1);
// i2c_write_byte(addr);
// i2c_start();
// i2c_write_byte((M24C08_I2C_ADDR << 1) | 0x01);
// for (i = 0; i < len; i++) {
// data[i] = i2c_read_byte(i == len - 1 ? 0 : 1);
// }
// i2c_stop();
//}
2.M24co8.h
#ifndef __M24C08_H__
#define __M24C08_H__
#include <stdint.h>
#include "System.h"
#define M24C08_WRITE_0 PDout(12)=0
#define M24C08_WRITE_1 PDout(12)=1
#define M24C08_SCL_0 PDout(13)=0
#define M24C08_SCL_1 PDout(13)=1
#define M24C08_SDA_0 PDout(14)=0
#define M24C08_SDA_1 PDout(14)=1
#define M24C08_SDA_INPUT HAL_GPIO_ReadPin(GPIOD,M24C04_SDA_Pin)
//void i2c_write(uint8_t addr, uint8_t *data, uint16_t len);
//void i2c_read(uint8_t addr, uint8_t *data, uint16_t len);
//void M24C08_Write(uint8_t addr, uint8_t *data, uint16_t len);
uint8_t M24C08_ReadOneByte(uint16_t addr);
void M24C08_WriteOneByte(uint16_t addr,uint8_t data);
void M24C08_ReadByte(uint16_t addr,uint16_t len,uint8_t *buffer);
void M24C08_WriteByte(uint16_t addr,uint16_t len,uint8_t *buffer);
#endif
具体的IIC管脚只需在.h文件配置即可。