`
hunxiejun
  • 浏览: 1142423 次
文章分类
社区版块
存档分类
最新评论

Prima I2C 程序设置与读写 CS42L52 的寄存器

 
阅读更多

1 I2C 简介

I2C 有两线――串行数据 SDA 和串行时钟 SCL。Prima 默认支持三路 I2C 端口,分别是两路硬件(I2C1 和 I2C2)和一路软件(I2C5),两个 I2C 分别对应 SDA_0、SCL_0 (I2C1)和 SDA_1、SCL_1(I2C2),在 Prima 的主控上是选择 SDA_1 和 SCL_1(I2C2)(详细见电路图文档 sirfatlasiv typical mini application system V1.1.pdf)。

2 硬件端口读写设置

2.1 驱动部分设置

在这里我们是通过 I2C 程序读写 CS42L52 的寄存器,该从设备驱动部分需要在 codec 中修改。

Codec.cpp(c:\wince600\platform\common\src\soc\prima_sirf_v2\common\src\drivers\wavedev\cs42l52)

1. 打开 I2C2 端口

DWORD Codec_InitI2C()

{

if (h_codec == NULL)

{

if ((h_codec = I2COpen(CS42L52_I2C_PORT_NUMB)) == NULL)

{

RETAILMSG(ZONE_ERROR, (TEXT("Codec: I2COpen faild !!!\r\n")));

return FALSE;

}

}

return ERROR_SUCCESS;

}

由于选择的是 I2C2 端口,因此参数 CS42L52_I2C_PORT_NUMB 在codec.h 定义:

#define CS42L52_I2C_PORT_NUMB TEXT("I2C2:")

static BOOL I2C_Write(HANDLE pI2CHandle, ULONG ulRegAddr, PBYTE pRegValBuf, UINT uiValBufLen)

{

I2CTRANS Trans;

Trans.bRead = FALSE;—————————————————————————-(1)

Trans.dwRegAddr = ulRegAddr;

Trans.pValueBuf = pRegValBuf;

Trans.uiValueLen = uiValBufLen;

Trans.dwClock = CS42L52_I2C_FREQ;————————————————————(2)

Trans.i2cdevinfo.pReadSeq = NULL;————————————————————(3)

Trans.i2cdevinfo.uiReadSeqLen = 0;

Trans.i2cdevinfo.pWriteSeq = NULL;———————————————————-(3)

Trans.i2cdevinfo.uiWriteSeqLen = 0;

Trans.i2cdevinfo.ulDevAddrW = CS42L52_ADDR_W;­­­­­­­­­­­­­­­——————————————(4)

Trans.i2cdevinfo.ulDevAddrR = CS42L52_ADDR_R;——————————————(4)

if (!I2CTransact(pI2CHandle, &Trans))

{

ERRORMSG(1, (TEXT("codec:I2C write failed\r\n")));

return FALSE;

}

return TRUE;

}

对以上标注说明如下:

(1) 当 I2C 端口是写(发送)时,设置成 FLASE,读(接收)时为 TRUE;

(2) 这个频率,在 codec.h 中按如下设置:

#define CS42L52_I2C_FREQ 50000 //50Khz

(3) 这里是设置读写时序,设置成 NULL 即选择默认时序,默认时序可以在 I2C 的驱动中看到,在这里 I2C 的默认读写时序如下:

static const BYTE g_pI2CDefaultWriteSeq[] =

{ I2C_SEQ_SEG_DEVADDR_W | SEG_MASK_SEND_START | SEG_MASK_NEED_ACK,

I2C_SEQ_SEG_REGADDR | SEG_MASK_NEED_ACK,

I2C_SEQ_SEG_DATA | SEG_MASK_SEND_STOP | SEG_MASK_NEED_ACK

};

static const BYTE g_pI2CDefaultReadSeq[] =

{ I2C_SEQ_SEG_DEVADDR_W | SEG_MASK_SEND_START | SEG_MASK_NEED_ACK,

I2C_SEQ_SEG_REGADDR | SEG_MASK_NEED_ACK,

I2C_SEQ_SEG_DEVADDR_R | SEG_MASK_SEND_START | SEG_MASK_NEED_ACK,

I2C_SEQ_SEG_DATA | SEG_MASK_NEED_NACK | SEG_MASK_SEND_STOP

};

(4) 在 codec.h 中,进行如下定义:

#define CS42L52_ADDR_R 0x95

#define CS42L52_ADDR_W 0x94

这是 8 位寄存器二进制值,前七位是对从机的寻址,第八位是读写控制,0 是写,1 是读,下图为文档 CS42L52_DNZR.pdf 中的时序截图。

3. 读设置

static BOOL I2C_Read(HANDLE pI2CHandle, ULONG ulRegAddr, PBYTE pRegValBuf, UINT uiValBufLen)

{

I2CTRANS Trans;

Trans.bRead = TRUE;

Trans.dwRegAddr = ulRegAddr;

Trans.pValueBuf = pRegValBuf;

Trans.uiValueLen = uiValBufLen;

Trans.dwClock = CS42L52_I2C_FREQ;

Trans.i2cdevinfo.pReadSeq = NULL;

Trans.i2cdevinfo.uiReadSeqLen = 0;

Trans.i2cdevinfo.pWriteSeq = NULL;

Trans.i2cdevinfo.uiWriteSeqLen = 0;

Trans.i2cdevinfo.ulDevAddrW = CS42L52_ADDR_W;

Trans.i2cdevinfo.ulDevAddrR = CS42L52_ADDR_R;

if (!I2CTransact(pI2CHandle, &Trans))

{

ERRORMSG(1, (TEXT("codec:I2C read failed\r\n")));

return FALSE;

}

return TRUE;

}

可以看出,与写设置不同的只有 Trans.bRead 的值。

2.2 配置文件设置

1. 批处理

在批处理文件 SiRFprima_EVB.BAT (c:\wince600\platform\tt4x0bd) 中,对三路端口设置如下:

IF "%BSP_ATLAS_I2C%" == "1" (

SET BSP_ATLAS_I2C1=1

SET BSP_ATLAS_I2C2=1

SET BSP_ATLAS_I2C5=

)

需要打开的是 I2C2,因此 BSP_ATLAS_I2C2 必须设成1。

2. Platform.bib

在文件 Platform.bib(c:\wince600\platform\tt4x0bd\files)中设置如下:

IF BSP_ATLAS_I2C

i2c.dll $(_FLATRELEASEDIR)\i2c.dll NK SHK

ENDIF

3. 注册表

在注册表文件 Platform.reg(c:\wince600\platform\tt4x0bd\files)中对 I2C1 和 I2C2 设置如下:

IF BSP_ATLAS_I2C1

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\I2C1]

"Prefix"="I2C"

"Dll"="I2C.dll"

"Index"=dword:1

"Order"=dword:0

;"IClass"="{A32942B7-920C-486b-B0E6-92A702A99B35}"

IF BSP_USE_HIVE

; @CESYSGEN IF FILESYS_FSREGHIVE

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\I2C1]

"Flags"=dword:1000 ; Don't put this when there is no hive. It will cause the driver unable to load in hive.

; @CESYSGEN ENDIF FILESYS_FSREGHIVE

ENDIF

ENDIF

IF BSP_ATLAS_I2C2

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\I2C2]

"Prefix"="I2C"

"Dll"="I2C.dll"

"Index"=dword:2

"Order"=dword:0

;"IClass"="{A32942B7-920C-486b-B0E6-92A702A99B35}"

IF BSP_USE_HIVE

; @CESYSGEN IF FILESYS_FSREGHIVE

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\I2C2]

"Flags"=dword:1000 ; Don't put this when there is no hive. It will cause the driver unable to load in hive.

; @CESYSGEN ENDIF FILESYS_FSREGHIVE

ENDIF

ENDIF

3 IO 口模拟 I2C 读写设置


3.1 说明

软件端口设置在硬件端口设置的基础上做以下修改。

3.2 驱动部分设置

1. 打开端口

需要在 Codec 驱动中打开端口 I2C5,参数 CS42L52_I2C_PORT_NUMB 在codec.h 中的定义如下:

#define CS42L52_I2C_PORT_NUMB TEXT("I2C5:")

2. 修改 I2C 驱动

I2C 的驱动修改是在以下文件中完成

BspI2cLib.c (c:\wince600\platform\tt4x0bd\src\drivers\i2c\i2csoftlib)

#ifdef __SOFT__I2C__0__

#define I2C_GPIO_GROUP 3

#define I2C_GPIO_INDEX_SDA 18

#define I2C_GPIO_INDEX_SCL 19

#else

#define I2C_GPIO_GROUP 0

#define I2C_GPIO_INDEX_SDA 3

#define I2C_GPIO_INDEX_SCL 2

#endif

SDA_1 和 GPIO0_3 复用一个引脚,SCL_1 和 GPIO0_2 复用一个引脚,因此对 __SOFT__I2C__0__ 不予以设置(为空),选择第二种设置。

软件 I2C 端口设置是通过 GPIO 口的拉高拉低来模拟 I2C,具体设置如下:

void BspI2cLibInit()

{

GPIO_PAD_EN_SET(GPIO_GROUP(I2C_GPIO_GROUP), GPIO_MASK(I2C_GPIO_INDEX_SDA));

GPIO_PAD_EN_SET(GPIO_GROUP(I2C_GPIO_GROUP), GPIO_MASK(I2C_GPIO_INDEX_SCL));

PIO_SET_PULL(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SDA));

PIO_SET_PULL(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SCL));

}

void BspI2cLibDataHigh()

{

PIO_OUTPUT_ONE(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SDA));

PIO_OUTPUT_ENABLE(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SDA));

}

void BspI2cLibDataLow()

{

PIO_OUTPUT_ZERO(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SDA));

PIO_OUTPUT_ENABLE(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SDA));

}

void BspI2cLibClockHigh()

{

PIO_OUTPUT_ONE(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SCL));

PIO_OUTPUT_ENABLE(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SCL));

}

void BspI2cLibClockLow()

{

PIO_OUTPUT_ZERO(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SCL));

PIO_OUTPUT_ENABLE(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SCL));

}

BOOL BspI2cLibGetData()

{

PIO_OUTPUT_DISABLE(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SDA));

usWait(i2cDelay);

return PIO_READ_INPUT(GPIO, GPIO_GROUP(I2C_GPIO_GROUP), GPIO_INDEX(I2C_GPIO_INDEX_SDA));

}

3.3 配置文件设置

1. 批处理

在批处理文件 SiRFprima_EVB.BAT (c:\wince600\platform\tt4x0bd) 中,需要如下设置。

IF "%BSP_ATLAS_I2C%" == "1" (

SET BSP_ATLAS_I2C1=

SET BSP_ATLAS_I2C2=

SET BSP_ATLAS_I2C5=1

)

需要打开的是 I2C5,因此 BSP_ATLAS_I2C5 必须设置成1,至于 BSP_ATLAS_I2C1 和 BSP_ATLAS_I2C2 没有要求。

2. 注册表

在注册表文件 Platform.reg(c:\wince600\platform\tt4x0bd\files)中对 I2C5 的设置如下:

;Software I2C port number up from 5.And you can own 3 software i2c at most.

IF BSP_ATLAS_I2C5

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\I2C5]

"Prefix"="I2C"

"Dll"="I2C.dll"

"Index"=dword:5

"Order"=dword:0

;"IClass"="{A32942B7-920C-486b-B0E6-92A702A99B35}"

IF BSP_USE_HIVE

; @CESYSGEN IF FILESYS_FSREGHIVE

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\I2C5]

"Flags"=dword:1000 ; Don't put this when there is no hive. It will cause the driver unable to load in hive.

; @CESYSGEN ENDIF FILESYS_FSREGHIVE

ENDIF

ENDIF

4 测试

4.1 硬件端口读写设置测试

1)为了测试 I2C 的程序读写 CS42L52 的寄存器是否成功,在 Codec.cpp 的 Codec_init 函数中添加一个死循环:

blch1=0x57;

while(1){

Codec_I2C_WriteReg(FALSE, POWER_CTRL2, (PUCHAR)&blch1, 1);

msWait(1000); // 延时函数可自己设置

Codec_I2C_ReadReg(FALSE, POWER_CTRL2, (PUCHAR)&blch, 1);

RETAILMSG(1, (TEXT("KKKKKKK------POWER_CTRL2--------------%2x\r\n"),blch));

}

启动机器,在终端中可看到该循环打印的信息

———KKKKKKK------POWER_CTRL2--------------57(与写入寄存器的值相同)。

2)用示波器观察可得以下波形(在图上有简单注解):

4.2 IO 口模拟 I2C 读写设置测试

1)在终端同样可以看到死循环的打印信息。

2)示波器观察得到的波形如下:

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics