Linux學習之i-mx287學習:ARM9與GD32F407的I2C通信(ioctl,write,read)

        最近想試一下ARM9下的I2C設備與外掛MCU通信,外掛mcu用的是GD32F407,在把GD32F4的I2C0初始化成從中斷接收模式後,ARM9的i2c讀寫遇到了一點問題,mcu始終沒有進接收中斷,在搜索問題解決方法時瞭解到linux下的I2C設備操作的一些經驗,在這裏記錄一下。

一、linux下I2C設備的設置

i2c通信無非是模式設置、設備地址設置、速率設置,linux下的i2c設備設置操作給出了標準,需要使用ioctl這個函數進行設置,下面就I-MAX287A的ARM板中給的I2C讀寫例程來進行分析。

/*i2c_test.c*/

#include     <stdio.h>
#include     <stdlib.h> 
#include     <unistd.h>  
#include     <sys/types.h>
#include     <sys/stat.h>
#include     <fcntl.h> 
#include     <termios.h>
#include     <errno.h>  

#include "iic.h"

#define I2C_ADDR  0x30 //從設備地址 如果單片機的i2c從地址是0x30
#define DATA_LEN  15

#define DEV_NANE "/dev/i2c-1"

int main(void)
{
	unsigned int uiRet;
	int i;

	unsigned char tx_buf[DATA_LEN];
	unsigned char rx_buf[DATA_LEN];
	unsigned char addr[2] ;

	addr[0] = 0x00;
	    
	GiFd = open(DEV_NANE, O_RDWR|O_NONBLOCK);   
	if(GiFd < 0)
    	perror("open i2c-1\n");
	printf("i2c1 open ok\r\n");
	
	//設置i2c的地址位寬,0:7bit addr;1:10bit addr.
	uiRet = ioctl(GiFd, I2C_TENBIT, 0);
	if (uiRet < 0) {
	printf("setenv addr bit faile ret: %x \n", uiRet);
	return -1;
 	}	
	
	//設置通信從設備地址
	uiRet = ioctl(GiFd, I2C_SLAVE, I2C_ADDR >> 1);
	if (uiRet < 0) {
	printf("setenv address faile ret: %x \n", uiRet);
	return -1;
 	}
	 
	 
	for (i = 0; i < DATA_LEN; i++) //寫將要發送的數據到 發送buf
    	tx_buf[i] = i+1; 
	
	for (i = 0; i < DATA_LEN; i++){ //寫要發送的數據到 24c02
		addr[0] = 0x30; //當前地址
		write(GiFd, addr, 1);  //寫地址
		write(GiFd, &tx_buf[i], 1); //寫數據
	}
	
	// addr[0] = 0x00; //當前地址
	// write(GiFd, addr, 1);  //寫地址
	// read(GiFd, rx_buf, DATA_LEN); //讀數據

	// printf("read from eeprom:");
	// for(i = 0; i < DATA_LEN; i++) {
    //  	printf(" %x", rx_buf[i]);
	// }

	printf("\n");

	return 0;
}
/*iic.h*/

#ifndef __I2C_H_
#define __I2C_H_

#define I2C_SLAVE	0x0703
#define I2C_TENBIT	0x0704

int GiFd;

int GiIndex;

int  iicOpen();

int waitIRQ();
void waitset();

void setdriverTo500smod();
void setdriverToCOMMmod();

#endif

(1) ioctl函數的使用:
原型:struct ioctl(struct file *file,unsigned int cmd,unsigned long arg);
 cmd有I2C_SLAVE,I2C_SLAVE_FORCE,I2C_TENBIT,I2C_SET_SPEED幾個選項;
    I2C_SLAVE:對應的arg取值爲I2C從機地址,用來設定I2C從機地址;

    I2C_SLAVE_FORCE:對應的arg取值爲I2C從機地址,用來修改I2C從機地址;

    I2C_TENBIT:對應的arg取值爲0:從機地址爲7 bit;對應的arg取值爲1:從機地址爲10bit。用來指定I2C從機地址的位數;  

    I2C_SET_SPEED:對應的arg取值爲I2C總線控制器分頻值。用來設置I2C總線控制器時鐘頻率;


    常用設置設置I2c從機地址爲0xA0,如果選用at24c08設備,那麼從機是7 bit地址,所以要右移1位,指定從機地址爲7 bit,

ioctl(fd,I2C_TENBIT,0)。
ioctl(fd,I2C_SLAVE,0xA0>>1);

上面貼的代碼中,沒有I2C_SLAVE_FORCE和I2C_SET_SPEED設置項,這個應該是示例中沒有給出的,I2C_SLAVE 的值爲何是0x0703,暫時沒有找到依據,猜測是驅動裏面給這個值過去後,會將I2C設備的某個寄存器進行相應的設置,I2C_TENBIT也同理。

二、linux下i2c設備的讀寫操作

read()與write()函數的使用
假設子地址爲48,向有子地址的器件寫進7個字節:

unsigned char buf[8]={48,'a','b','c','d','e','f','g');/*第1個字節48爲子地址*/

write(fd,buf,9);/*寫進7個字節,第1個字節爲子地址*/

從有子地址的I2C器件讀取7個字節:
unsigned char suba=0,recbuf[20];
write(fd,buf,1);/*發送子地址0*/
read(fd,recbuf,7);/*從子地址48開始讀取7個字節*/

三、linux下i2c的結束標誌位
linux下I2C做主設備讀寫數據時,結束標誌都由主設備給出,如果發現MCU設備沒有退出I2C中斷,需檢查MCU的I2C中斷配置是否有問題。

 

四、通信效果


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章