嵌入式linux开发笔记: I2C

嵌入式linux开发笔记: I2C

1. 初步编程框架

为了实现I2C Controller对I2C Device之间的通信,程序框架可以分拆为4个子程序。

1> I2C_controller.c
 


/* 有一个i2c_controller数组用来存放各种不同芯片的操作结构体 */
void register_i2c_controller()
{
}

/* 根据名字来选择某款I2C控制器 */
void select_i2c_controller(char *name)
{
}

/* 实现 i2c_transfer 接口函数 */

int i2c_transfer(i2c_msg msgs, int num)
{

}

2> S3C2440_I2C_controller.c

/* 实现i2c_controller
          .init
          .master_xfer
          .name
 */

3>I2C_test.c

void i2c_test(void)
{
	/* 初始化: 选择I2C控制器 */

	/* 提供菜单供测试 */
}

4> at24cxx.c

int at24cxx_write(unsigned int addr, unsigned char *data, int len)
{
	/* 构造i2c_msg */

	/* 调用i2c_transfer */
}


int at24cxx_read(unsigned int addr, unsigned char *data, int len)
{
	/* 构造i2c_msg */

	/* 调用i2c_transfer */
}

2. I2C controller程序框架

1> i2c_controller.h

//首先设计几个结构体,这些结构体应包含在头文件i2c_controller.h中。


#ifndef _I2C_CONTROLLER_H
#define _I2C_CONTROLLER_H

typedef struct i2c_msg {
	unsigned int addr;  /* 7bits */
	int flags;  /* 0 - write, 1 - read */
	int len;
	int cnt_transferred;
	unsigned char *buf;
}i2c_msg, *p_i2c_msg;

typedef struct i2c_controller {
	int (*int)(void);
	int (*master_xfer)(i2c_msg msgs, int num);
	char *name;
}i2c_controller, *p_i2c_controller;


#endif /* _I2C_CONTROLLER_H */


2> i2c_controller.c


#include "i2c_controller.h"

#define I2C_CONTROLLER_NUM 10

/* 有一个i2c_controller数组用来存放各种不同芯片的操作结构体 */
static p_i2c_controller p_i2c_controllers[I2C_CONTROLLER_NUM];
static p_i2c_controller p_i2c_con_selected;


void register_i2c_controller(p_i2c_controller *p)
{
	int i;
	for (i = 0; i < I2C_CONTROLLER_NUM; i++)
	{
		if (!p_i2c_controllers[i])
		{
			p_i2c_controllers[i] = p;
			return;
		}
	}
}

/* 根据名字来选择某款I2C控制器 */
int select_i2c_controller(char *name)
{
	int i;
	for (i = 0; i < I2C_CONTROLLER_NUM; i++)
	{
		if (p_i2c_controllers[i] && !strcmp(name, p_i2c_controllers[i]->name))
		{
			p_i2c_con_selected = p_i2c_controllers[i];
			return 0;
		}
	}
	return -1;
}

/* 实现 i2c_transfer 接口函数 */

int i2c_transfer(i2c_msg msgs, int num)
{
	return p_i2c_con_selected->master_xfer(msgs, num);
}


void i2c_init(void)
{
	/* 注册下面的I2C控制器 */
	s3c2440_i2c_con_add();

	/* 选择某款I2C控制器 */

	/* 调用它的init函数 */
}

3> s3c2440_i2c_controller.c

#include "i2c_controller.h"
#include "../s3c2440_soc.h"


void i2c_interrupt_func(int irq)
{
	/* 每传输完一个数据将产生一个中断 */

	/* 对于每次传输, 第1个中断是"已经发出了设备地址" */

	
}


void s3c2440_i2c_con_init(void)
{
	/* 设置时钟 */
	/* [7] : IIC-bus acknowledge enable bit, 1-enable in rx mode
	 * [6] : 时钟源, 0: IICCLK = fPCLK /16; 1: IICCLK = fPCLK /512
	 * [5] : 1-enable interrupt
	 * [4] : 读出为1时表示中断发生了, 写入0来清除并恢复I2C操作
	 * [3:0] : Tx clock = IICCLK/(IICCON[3:0]+1).
	 * Tx Clock = 100khz = 50Mhz/16/(IICCON[3:0]+1)
	 */
	IICCON = (0<<6) | (1<<5) | (30<<0);

	/* 注册中断处理函数 */
	register_irq(27, i2c_interrupt_func);
}

void do_master_tx(p_i2c_msg msg)
{
	msg->cnt_transferred = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 master tx mode */
		
	/* 2. 把从设备地址写入IICDS */
	IICDS = msg->addr<<1;
	
	/* 3. IICSTAT = 0xf0 , 数据即被发送出去, 将导致中断产生 */
	IICSTAT = 0xf0;
	

	/* 后续的传输由中断驱动 */

	/* 循环等待中断处理完毕 */
	while (msg->cnt_transferred != msg->len);
}

void do_master_rx(p_i2c_msg msg)
{
	msg->cnt_transferred = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 Master Rx mode */
		
	/* 2. 把从设备地址写入IICDS */
	IICDS = (msg->addr<<1)|(1<<0);
	
	/* 3. IICSTAT = 0xb0 , 从设备地址即被发送出去, 将导致中断产生 */
	IICSTAT = 0xb0;
	

	/* 后续的传输由中断驱动 */

	/* 循环等待中断处理完毕 */
	while (msg->cnt_transferred != msg->len);
}

int s3c2440_master_xfer(p_i2c_msg msgs, int num)
{
	int i;
	for (i = 0; i < num; i++)	
	{
		if (msgs[i]->flags == 0)/* write */
			do_master_tx(msgs[i]);
		else
			do_master_rx(msgs[i]);
	}
}

/* 实现i2c_controller
          .init
          .master_xfer
          .name
 */

static i2c_controller s3c2440_i2c_con = {
	.name = "s3c2440",
	.init = s3c2440_i2c_con_init,
	.master_xfer = s3c2440_master_xfer,
};

void s3c2440_i2c_con_add(void)
{
	register_i2c_controller(&s3c2440_i2c_con);
}

4> at24cxx.c

int at24cxx_write(unsigned int addr, unsigned char *data, int len)
{
	/* 构造i2c_msg */

	/* 调用i2c_transfer */
}


int at24cxx_read(unsigned int addr, unsigned char *data, int len)
{
	/* 构造i2c_msg */

	/* 调用i2c_transfer */
}

5> i2c_test.c

void i2c_test(void)
{
	/* 初始化: 选择I2C控制器 */

	/* 提供菜单供测试 */
}

3. I2c 中断

1> i2c_controller.h

#ifndef _I2C_CONTROLLER_H
#define _I2C_CONTROLLER_H

typedef struct i2c_msg {
	unsigned int addr;  /* 7bits */
	int flags;  /* 0 - write, 1 - read */
	int len;
	int cnt_transferred;
	int err;
	unsigned char *buf;
}i2c_msg, *p_i2c_msg;

typedef struct i2c_controller {
	int (*int)(void);
	int (*master_xfer)(i2c_msg msgs, int num);
	char *name;
}i2c_controller, *p_i2c_controller;


#endif /* _I2C_CONTROLLER_H */

2> i2c_controller.c

#include "i2c_controller.h"

#define I2C_CONTROLLER_NUM 10

/* 有一个i2c_controller数组用来存放各种不同芯片的操作结构体 */
static p_i2c_controller p_i2c_controllers[I2C_CONTROLLER_NUM];
static p_i2c_controller p_i2c_con_selected;


void register_i2c_controller(p_i2c_controller *p)
{
	int i;
	for (i = 0; i < I2C_CONTROLLER_NUM; i++)
	{
		if (!p_i2c_controllers[i])
		{
			p_i2c_controllers[i] = p;
			return;
		}
	}
}

/* 根据名字来选择某款I2C控制器 */
int select_i2c_controller(char *name)
{
	int i;
	for (i = 0; i < I2C_CONTROLLER_NUM; i++)
	{
		if (p_i2c_controllers[i] && !strcmp(name, p_i2c_controllers[i]->name))
		{
			p_i2c_con_selected = p_i2c_controllers[i];
			return 0;
		}
	}
	return -1;
}

/* 实现 i2c_transfer 接口函数 */

int i2c_transfer(i2c_msg msgs, int num)
{
	return p_i2c_con_selected->master_xfer(msgs, num);
}


void i2c_init(void)
{
	/* 注册下面的I2C控制器 */
	s3c2440_i2c_con_add();

	/* 选择某款I2C控制器 */

	/* 调用它的init函数 */
}

3> s3c2440_i2c_controller.c

#include "i2c_controller.h"
#include "../s3c2440_soc.h"

static p_i2c_msg p_cur_msg;

void i2c_interrupt_func(int irq)
{
	int index;
	unsigned int iicstat = IICSTAT;

	p_cur_msg->cnt_transferred++;
	
	/* 每传输完一个数据将产生一个中断 */

	/* 对于每次传输, 第1个中断是"已经发出了设备地址" */

	if (p_cur_msg->flags == 0)	/* write */
	{
		/* 对于第1个中断, 它是发送出设备地址后产生的
		 * 需要判断是否有ACK
		 * 有ACK : 设备存在
		 * 无ACK : 无设备, 出错, 直接结束传输
		 */
		if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
		{
			if (iicstat & (1<<0))
			{ /* no ack */
				/* 停止传输 */
				IICSTAT = 0xd0;
				IICCON &= ~(1<<4);
				p_cur_msg->err = -1;
				delay(1000);
				return;
			}
		}

		if (p_cur_msg->cnt_transferred < p_cur_msg->len)
		{
			/* 对于其他中断, 要继续发送下一个数据
			 */
			IICDS = p_cur_msg->buf[p_cur_msg->cnt_transferred];
			IICCON &= ~(1<<4);
		}
		else
		{
			/* 停止传输 */
			IICSTAT = 0xd0;
			IICCON &= ~(1<<4);
			p_cur_msg->err = -1;
			delay(1000);
		}
	}
	else /* read */
	{
		/* 对于第1个中断, 它是发送出设备地址后产生的
		 * 需要判断是否有ACK
		 * 有ACK : 设备存在, 恢复I2C传输, 这样在下一个中断才可以得到第1个数据
		 * 无ACK : 无设备, 出错, 直接结束传输
		 */
		if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
		{
			if (iicstat & (1<<0))
			{ /* no ack */
				/* 停止传输 */
				IICSTAT = 0x90;
				IICCON &= ~(1<<4);
				p_cur_msg->err = -1;
				delay(1000);
				return;
			}
			else  /* ack */
			{
				/* 恢复I2C传输 */
				IICCON &= ~(1<<4);
				return;
			}
		}

		/* 非第1个中断, 表示得到了一个新数据
		 * 从IICDS读出、保存
		 */
		if (p_cur_msg->cnt_transferred < p_cur_msg->len)
		{
			index = p_cur_msg->cnt_transferred - 1;
			p_cur_msg->buf[index] = IICDS;
			/* 恢复I2C传输 */
			IICCON &= ~(1<<4);
		}
		else
		{
			/* 发出停止信号 */
			IICSTAT = 0x90;
			IICCON &= ~(1<<4);
			delay(1000);
		}
	}
}


void s3c2440_i2c_con_init(void)
{
	/* 设置时钟 */
	/* [7] : IIC-bus acknowledge enable bit, 1-enable in rx mode
	 * [6] : 时钟源, 0: IICCLK = fPCLK /16; 1: IICCLK = fPCLK /512
	 * [5] : 1-enable interrupt
	 * [4] : 读出为1时表示中断发生了, 写入0来清除并恢复I2C操作
	 * [3:0] : Tx clock = IICCLK/(IICCON[3:0]+1).
	 * Tx Clock = 100khz = 50Mhz/16/(IICCON[3:0]+1)
	 */
	IICCON = (1<<7) | (0<<6) | (1<<5) | (30<<0);

	/* 注册中断处理函数 */
	register_irq(27, i2c_interrupt_func);
}

int do_master_tx(p_i2c_msg msg)
{
	p_cur_msg = msg;
	
	msg->cnt_transferred = -1;
	msg->err = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 master tx mode */
		
	/* 2. 把从设备地址写入IICDS */
	IICDS = msg->addr<<1;
	
	/* 3. IICSTAT = 0xf0 , 数据即被发送出去, 将导致中断产生 */
	IICSTAT = 0xf0;
	

	/* 后续的传输由中断驱动 */

	/* 循环等待中断处理完毕 */
	while (!msg->err && msg->cnt_transferred != msg->len);

	if (msg->err)
		return -1;
	else
		return 0;
}

int do_master_rx(p_i2c_msg msg)
{
	p_cur_msg = msg;

	msg->cnt_transferred = -1;
	msg->err = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 Master Rx mode */
		
	/* 2. 把从设备地址写入IICDS */
	IICDS = (msg->addr<<1)|(1<<0);
	
	/* 3. IICSTAT = 0xb0 , 从设备地址即被发送出去, 将导致中断产生 */
	IICSTAT = 0xb0;
	

	/* 后续的传输由中断驱动 */

	/* 循环等待中断处理完毕 */
	while (!msg->err && msg->cnt_transferred != msg->len);

	if (msg->err)
		return -1;
	else
		return 0;
}

int s3c2440_master_xfer(p_i2c_msg msgs, int num)
{
	int i;
	int err;
	
	for (i = 0; i < num; i++)	
	{
		if (msgs[i]->flags == 0)/* write */
			err = do_master_tx(msgs[i]);
		else
			err = do_master_rx(msgs[i]);
		if (err)
			return err;
	}
	return 0;
}

/* 实现i2c_controller
          .init
          .master_xfer
          .name
 */

static i2c_controller s3c2440_i2c_con = {
	.name = "s3c2440",
	.init = s3c2440_i2c_con_init,
	.master_xfer = s3c2440_master_xfer,
};

void s3c2440_i2c_con_add(void)
{
	register_i2c_controller(&s3c2440_i2c_con);
}

4> at24cxx.c

int at24cxx_write(unsigned int addr, unsigned char *data, int len)
{
	/* 构造i2c_msg */

	/* 调用i2c_transfer */
}


int at24cxx_read(unsigned int addr, unsigned char *data, int len)
{
	/* 构造i2c_msg */

	/* 调用i2c_transfer */
}

5> i2c_test.c

void i2c_test(void)
{
	/* 初始化: 选择I2C控制器 */

	/* 提供菜单供测试 */
}

5. Final OK

1> I2ccontroller.h

#ifndef _I2C_CONTROLLER_H
#define _I2C_CONTROLLER_H

typedef struct i2c_msg {
	unsigned int addr;  /* 7bits */
	int flags;  /* 0 - write, 1 - read */
	int len;
	int cnt_transferred;
	int err;
	unsigned char *buf;
}i2c_msg, *p_i2c_msg;

typedef struct i2c_controller {
	int (*init)(void);
	int (*master_xfer)(p_i2c_msg msgs, int num);
	char *name;
}i2c_controller, *p_i2c_controller;


#endif /* _I2C_CONTROLLER_H */

2> i2c_controller.c

#include "i2c_controller.h"

#define I2C_CONTROLLER_NUM 10

/* 有一个i2c_controller数组用来存放各种不同芯片的操作结构体 */
static p_i2c_controller p_i2c_controllers[I2C_CONTROLLER_NUM];
static p_i2c_controller p_i2c_con_selected;


void register_i2c_controller(p_i2c_controller *p)
{
	int i;
	for (i = 0; i < I2C_CONTROLLER_NUM; i++)
	{
		if (!p_i2c_controllers[i])
		{
			p_i2c_controllers[i] = p;
			return;
		}
	}
}

/* 根据名字来选择某款I2C控制器 */
int select_i2c_controller(char *name)
{
	int i;
	for (i = 0; i < I2C_CONTROLLER_NUM; i++)
	{
		if (p_i2c_controllers[i] && !strcmp(name, p_i2c_controllers[i]->name))
		{
			p_i2c_con_selected = p_i2c_controllers[i];
			return 0;
		}
	}
	return -1;
}

/* 实现 i2c_transfer 接口函数 */

int i2c_transfer(p_i2c_msg msgs, int num)
{
	return p_i2c_con_selected->master_xfer(msgs, num);
}


void i2c_init(void)
{
	/* 注册下面的I2C控制器 */
	s3c2440_i2c_con_add();

	/* 选择某款I2C控制器 */
	select_i2c_controller("s3c2440");

	/* 调用它的init函数 */
	p_i2c_con_selected->init();
}

3> s32440_controller.c

#include "i2c_controller.h"
#include "../s3c2440_soc.h"

static p_i2c_msg p_cur_msg;

int isLastData(void)
{
	if (p_cur_msg->cnt_transferred == p_cur_msg->len - 1)
		return 1;  /* 正要开始传输最后一个数据 */
	else 
		return 0;
}

void resume_iic_with_ack(void)
{
	unsigned int iiccon = IICCON;
	iiccon |= (1<<7); /* 回应ACK */
	iiccon &= ~(1<<4); /* 恢复IIC操作 */
	IICCON =  iiccon;
}

void resume_iic_without_ack(void)
{
	unsigned int iiccon = IICCON;
	iiccon &= ~((1<<7) | (1<<4)); /* 不回应ACK, 恢复IIC操作 */
	IICCON =  iiccon;
}


void i2c_interrupt_func(int irq)
{
	int index;
	unsigned int iicstat = IICSTAT;
	unsigned int iiccon;

	//printf("i2c_interrupt_func! flags = %d\n\r", p_cur_msg->flags);

	p_cur_msg->cnt_transferred++;
	
	/* 每传输完一个数据将产生一个中断 */

	/* 对于每次传输, 第1个中断是"已经发出了设备地址" */

	if (p_cur_msg->flags == 0)	/* write */
	{
		/* 对于第1个中断, 它是发送出设备地址后产生的
		 * 需要判断是否有ACK
		 * 有ACK : 设备存在
		 * 无ACK : 无设备, 出错, 直接结束传输
		 */
		if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
		{
			if (iicstat & (1<<0))
			{ /* no ack */
				/* 停止传输 */
				IICSTAT = 0xd0;
				IICCON &= ~(1<<4);
				p_cur_msg->err = -1;
				printf("tx err, no ack\n\r");
				delay(1000);
				return;
			}
		}

		if (p_cur_msg->cnt_transferred < p_cur_msg->len)
		{
			/* 对于其他中断, 要继续发送下一个数据
			 */
			IICDS = p_cur_msg->buf[p_cur_msg->cnt_transferred];
			IICCON &= ~(1<<4);
		}
		else
		{
			/* 停止传输 */
			IICSTAT = 0xd0;
			IICCON &= ~(1<<4);
			delay(1000);
		}
	}
	else /* read */
	{
		/* 对于第1个中断, 它是发送出设备地址后产生的
		 * 需要判断是否有ACK
		 * 有ACK : 设备存在, 恢复I2C传输, 这样在下一个中断才可以得到第1个数据
		 * 无ACK : 无设备, 出错, 直接结束传输
		 */
		if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
		{
			if (iicstat & (1<<0))
			{ /* no ack */
				/* 停止传输 */
				IICSTAT = 0x90;
				IICCON &= ~(1<<4);
				p_cur_msg->err = -1;
				printf("rx err, no ack\n\r");
				delay(1000);
				return;
			}
			else  /* ack */
			{
				/* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
				/* 恢复I2C传输 */
				if (isLastData())
				{
					resume_iic_without_ack();
				}
				else
				{
					resume_iic_with_ack();
				}
				return;
			}
		}

		/* 非第1个中断, 表示得到了一个新数据
		 * 从IICDS读出、保存
		 */
		if (p_cur_msg->cnt_transferred < p_cur_msg->len)
		{
			index = p_cur_msg->cnt_transferred - 1;
			p_cur_msg->buf[index] = IICDS;

			/* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
			/* 恢复I2C传输 */
			if (isLastData())
			{
				resume_iic_without_ack();
			}
			else
			{
				resume_iic_with_ack();
			}
		}
		else
		{
			/* 发出停止信号 */
			IICSTAT = 0x90;
			IICCON &= ~(1<<4);
			delay(1000);
		}
	}
}


void s3c2440_i2c_con_init(void)
{
	/* 配置引脚用于I2C*/
	GPECON &= ~((3<<28) | (3<<30));
	GPECON |= ((2<<28) | (2<<30));
	
	/* 设置时钟 */
	/* [7] : IIC-bus acknowledge enable bit, 1-enable in rx mode
	 * [6] : 时钟源, 0: IICCLK = fPCLK /16; 1: IICCLK = fPCLK /512
	 * [5] : 1-enable interrupt
	 * [4] : 读出为1时表示中断发生了, 写入0来清除并恢复I2C操作
	 * [3:0] : Tx clock = IICCLK/(IICCON[3:0]+1).
	 * Tx Clock = 100khz = 50Mhz/16/(IICCON[3:0]+1)
	 */
	IICCON = (1<<7) | (0<<6) | (1<<5) | (30<<0);

	/* 注册中断处理函数 */
	register_irq(27, i2c_interrupt_func);
}

int do_master_tx(p_i2c_msg msg)
{
	p_cur_msg = msg;
	
	msg->cnt_transferred = -1;
	msg->err = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 master tx mode */
	IICCON |= (1<<7); /* TX mode, 在ACK周期释放SDA */
	IICSTAT = (1<<4);
		
	/* 2. 把从设备地址写入IICDS */
	IICDS = msg->addr<<1;
	
	/* 3. IICSTAT = 0xf0 , 数据即被发送出去, 将导致中断产生 */
	IICSTAT = 0xf0;
	

	/* 后续的传输由中断驱动 */

	/* 循环等待中断处理完毕 */
	while (!msg->err && msg->cnt_transferred != msg->len);

	if (msg->err)
		return -1;
	else
		return 0;
}

int do_master_rx(p_i2c_msg msg)
{
	p_cur_msg = msg;

	msg->cnt_transferred = -1;
	msg->err = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 Master Rx mode */
	IICCON |= (1<<7); /* RX mode, 在ACK周期回应ACK */
	IICSTAT = (1<<4);
		
	/* 2. 把从设备地址写入IICDS */
	IICDS = (msg->addr<<1)|(1<<0);
	
	/* 3. IICSTAT = 0xb0 , 从设备地址即被发送出去, 将导致中断产生 */
	IICSTAT = 0xb0;
	

	/* 后续的传输由中断驱动 */

	/* 循环等待中断处理完毕 */
	while (!msg->err && msg->cnt_transferred != msg->len);

	if (msg->err)
		return -1;
	else
		return 0;
}

int s3c2440_master_xfer(p_i2c_msg msgs, int num)
{
	int i;
	int err;
	
	for (i = 0; i < num; i++)	
	{
		if (msgs[i].flags == 0)/* write */
			err = do_master_tx(&msgs[i]);
		else
			err = do_master_rx(&msgs[i]);
		if (err)
			return err;
	}
	return 0;
}

/* 实现i2c_controller
          .init
          .master_xfer
          .name
 */

static i2c_controller s3c2440_i2c_con = {
	.name = "s3c2440",
	.init = s3c2440_i2c_con_init,
	.master_xfer = s3c2440_master_xfer,
};

void s3c2440_i2c_con_add(void)
{
	register_i2c_controller(&s3c2440_i2c_con);
}

4>at24cxx.c

#include "i2c_controller.h"

#define AT24CXX_ADDR 0x50

int at24cxx_write(unsigned int addr, unsigned char *data, int len)
{
	i2c_msg msg;
	int i;
	int err;
	unsigned char buf[2];

	
	for (i = 0; i < len; i++)
	{
		buf[0] = addr++;
		buf[1] = data[i];
		
		/* 构造i2c_msg */
		msg.addr  = AT24CXX_ADDR;
		msg.flags = 0; /* write */
		msg.len   = 2;
		msg.buf   = buf;
		msg.err   = 0;
		msg.cnt_transferred = -1;

		/* 调用i2c_transfer */
		err = i2c_transfer(&msg, 1);
		if (err)
			return err;
	}
	
	return 0;
}

5> i2c_test.c

void do_write_at24cxx(void)
{
	unsigned int addr;
	unsigned char str[100];
	int err;
	
	/* 获得地址 */
	printf("Enter the address of sector to write: ");
	addr = get_uint();

	if (addr > 256)
	{
		printf("address > 256, error!\n\r");
		return;
	}

	printf("Enter the string to write: ");
	gets(str);

	printf("writing ...\n\r");
	err = at24cxx_write(addr, str, strlen(str)+1);
	printf("at24cxx_write ret = %d\n\r", err);
}

void do_read_at24cxx(void)
{
	unsigned int addr;
	int i, j;
	unsigned char c;
	unsigned char data[100];
	unsigned char str[16];
	int len;
	int err;
	int cnt = 0;
	
	/* 获得地址 */
	printf("Enter the address to read: ");
	addr = get_uint();

	if (addr > 256)
	{
		printf("address > 256, error!\n\r");
		return;
	}

	/* 获得长度 */
	printf("Enter the length to read: ");
	len = get_int();

	err = at24cxx_read(addr, data, len);
	printf("at24cxx_read ret = %d\n\r", err);

	printf("Data : \n\r");
	/* 长度固定为64 */
	for (i = 0; i < 4; i++)
	{
		/* 每行打印16个数据 */
		for (j = 0; j < 16; j++)
		{
			/* 先打印数值 */
			c = data[cnt++];
			str[j] = c;
			printf("%02x ", c);
		}

		printf("   ; ");

		for (j = 0; j < 16; j++)
		{
			/* 后打印字符 */
			if (str[j] < 0x20 || str[j] > 0x7e)  /* 不可视字符 */
				putchar('.');
			else
				putchar(str[j]);
		}
		printf("\n\r");
	}
}


void i2c_test(void)
{
	char c;

	/* 初始化 */
	i2c_init();

	while (1)
	{
		/* 打印菜单, 供我们选择测试内容 */
		printf("[w] Write at24cxx\n\r");
		printf("[r] Read at24cxx\n\r");
		printf("[q] quit\n\r");
		printf("Enter selection: ");

		c = getchar();
		printf("%c\n\r", c);

		/* 测试内容:
		 * 3. 编写某个地址
		 * 4. 读某个地址
		 */
		switch (c)		 
		{
			case 'q':
			case 'Q':
				return;
				break;
				
			case 'w':
			case 'W':
				do_write_at24cxx();
				break;

			case 'r':
			case 'R':
				do_read_at24cxx();
				break;
			default:
				break;
		}
	}
}

I2C 硬件原理

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值