i2c驱动app

本文介绍了I2C总线的基本概念,包括其由Philips公司开发的背景、在电子设计中的应用,如电压和温度监控、EEPROM数据读写等。I2C总线只需两根线SCL和SDA,通过上拉电阻连接。随后,文章展示了C语言实现I2C通信的结构体和函数,包括打开、关闭设备,读写数据等功能。最后,给出了一个用于24C08 EEPROM读写的示例程序,演示了如何读取和写入数据。
摘要由CSDN通过智能技术生成

I2C总线 

I2C即Inter IC,由Philips公司开发,是当今电子设计中应用非常广泛的串行总线之一,主要用于电压、温度监控,EEPROM(电可擦可编程只读存储器)数据的读写,光模块的管理等。I2C总线只有两根线,SCL和SDA,SCL即Serial Clock,串行时钟,SDA即Serial Data,串行数据。

硬件连接

I2C仅需两根线就可以支持一主多从或者多主连接,I2C使用两个双向开漏线,配合上拉电阻进行连接,关于上拉电阻阻值大小有最大值和最小值的限制,具体计算请参考 I2C-上拉电阻计算。

SDA:串行数据线
SCL:串行时钟线

24cXX.c:


#ifndef _24CXX_H_
#define _24CXX_H_
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
 
#define EEPROM_TYPE_UNKNOWN 0
#define EEPROM_TYPE_8BIT_ADDR   1
#define EEPROM_TYPE_16BIT_ADDR  2
 
struct eeprom
&#123;
    char *dev;  // device file i.e. /dev/i2c-N
    int addr;   // i2c address
    int fd;     // file descriptor
    int type;   // eeprom type
&#125;;
 
/*
 * opens the eeprom device at [dev_fqn] (i.e. /dev/i2c-N) whose address is
 * [addr] and set the eeprom_24c32 [e]
 */
int eeprom_open(char *dev_fqn, int addr, int type, struct eeprom*);
/*
 * closees the eeprom device [e] 
 */
int eeprom_close(struct eeprom *p_device_struct);
/*
 * read and returns the eeprom byte at memory address [mem_addr] 
 * Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address) 
 */
int eeprom_read_byte(struct eeprom* p_device_struct, __u16 mem_addr);
/*
 * read the current byte
 * Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address) 
 */
int eeprom_read_current_byte(struct eeprom *p_device_struct);
/*
 * writes [data] at memory address [mem_addr] 
 * Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address) 
 */
int eeprom_write_byte(struct eeprom *p_device_struct, __u16 mem_addr, __u8 data);
 
#endif

eeprog.c

#include <stdio.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "24cXX.h"

#define DEVICE_FILE_STRING "/dev/i2c/0"
#define DEVICE_ADDRESS 0x50

#define usage_if(a) do { do_usage_if( a , __LINE__); } while(0);
void do_usage_if(int b, int line) {
	const static char *eeprog_usage = 
		"I2C-24C08(256 bytes) Read/Write Program, ONLY FOR TEST!\n"
		"FriendlyARM Computer Tech. 2009\n";
	if(!b)
		return;
	fprintf(stderr, "%s\n[line %d]\n", eeprog_usage, line);
	exit(1);
}


#define die_if(a, msg) do { do_die_if( a , msg, __LINE__); } while(0);
void do_die_if(int b, char* msg, int line) {
	if(!b)
		return;
	fprintf(stderr, "Error at line %d: %s\n", line, msg);
	fprintf(stderr, "	sysmsg: %s\n", strerror(errno));
	exit(1);
}


static int read_from_eeprom(struct eeprom *e, int addr, int size) {
	int ch, i;
	for(i = 0; i < size; ++i, ++addr) {
		die_if((ch = eeprom_read_byte(e, addr)) < 0, "read error");
		if( (i % 16) == 0 ) 
			printf("\n %.4x|  ", addr);
		else if( (i % 8) == 0 ) 
			printf("  ");
		printf("%.2x ", ch);
		fflush(stdout);
	}
	fprintf(stderr, "\n\n");
	return 0;
}

static int write_to_eeprom(struct eeprom *e, int addr) {
	int i;
	for(i=0, addr=0; i<256; i++, addr++) {
		if( (i % 16) == 0 ) 
			printf("\n %.4x|  ", addr);
		else if( (i % 8) == 0 ) 
			printf("  ");
		printf("%.2x ", i);
		fflush(stdout);
		die_if(eeprom_write_byte(e, addr, i), "write error");
	}
	fprintf(stderr, "\n\n");
	return 0;
}

int main(int argc, char** argv) {
	struct eeprom e;
	int op;

	op = 0;

	usage_if(argc != 2 || argv[1][0] != '-' || argv[1][2] != '\0');
	op = argv[1][1];
	
	//TODO: 
	write(STDOUT_FILENO, "APP for 123456789012345 ...\n", strlen("APP for 123456789012345 ...\n"));
	fprintf(stderr, "Open %s with 8bit mode\n", DEVICE_FILE_STRING);
	die_if(eeprom_open(DEVICE_FILE_STRING, DEVICE_ADDRESS, EEPROM_TYPE_8BIT_ADDR, &e) < 0,
			"unable to open eeprom device file "
			"(check that the file exists and that it's readable)");
	switch(op) {
	case 'r':
		fprintf(stderr, "  Reading 256 bytes from 0x0\n");
		read_from_eeprom(&e, 0, 256);
		break;
	case 'w':
		fprintf(stderr, "  Writing 0x00-0xff into 24C06 \n");
		write_to_eeprom(&e, 0);
		break;
	default:
		usage_if(1);
		exit(1);
	}
	eeprom_close(&e);

	return 0;
}

直接编译
make
arm-linux-gnueabihf-gcc -c -o eeprog.o eeprog.c
arm-linux-gnueabihf-gcc -c -o 24cXX.o 24cXX.c
arm-linux-gnueabihf-gcc -Wall -O2 -o i2c eeprog.o 24cXX.o
 

思考题
I2C总线的优点是什么?
  

I2C总线主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的传输速率支持40个组件。I2C总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

I2C总线的启动信号和结束信号有什么特点。
开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值