1.X1226的CCR(Clock/Control Register,时钟/控制寄存器)地址为1101111(0x6f)(忽略最后一位R/W位,从第二位开始,I2C的7位寻址模式),故从I2C从设备地址SCL应为0x6f。
(X1226手册P12)
在往CCR写入之前,主设备必须先往状态寄存器(SR)先写入一个02h,再写入一个06h才行。状态寄存器的地址为0x003f,对应跟在slave address之后的word address。
2.6747的I2C模块
6747具有两个I2C模块I2C0和I2C1。这简化了系统架构,因为可以在DSP使用一个模块控制IC片上的外设(DACs,ADCs,等等)的同时,用另外一个模块与其他控制器通信或者实现一个用户接口。
2.1初始化
在开始和其他I2C设备进行通信前,需要适当的I2C初始化。除非已经有完整的驱动,否则你需要确定所需的I2C配置,并且对I2C配置成所需的设置。第一个任务是使能I2C的时钟。然后I2C控制器就会处于复位状态。现在可以开始配置I2C控制器了。一旦配置完成,需要通过将控制器从复位状态中释放出来,以使能I2C控制器。在开始通信之前,你需要确保所有的状态位被清除了,同时不存在挂起中断。一旦总线可用,I2C就可以进行通信了。
下面看代码,
/* IIC 配置引脚 */
I2C_GPIO( );
/*初始I2C模块,以便访问X1226*/
C6747_I2C_init();
其中,I2C_GPIO();函数如下:
该函数将PINMUX8寄存器的第12~15位和第16~19位设置为02h,即0010b,查阅手册可知这两个字段含义如图:
(用户手册P203~204)
可见,该函数将6747的这两个引脚的功能配置成了I2C0的SCL线和I2C0的SDA线。然后是I2C的初始化函数,代码如下:
/*------------------------------------------------------------------------ *
* *
* _I2C_init( ) *
* *
* Enable and initalize the I2C module *
* The I2C clk is set to run at 20 KHz *
* *
*------------------------------------------------------------------------ */
Int16
C6747_I2C_init( )
{
I2C_ICMDR = 0;
// Reset I2C
I2C_ICPSC = 3;
// Prescale to get 12MHz I2C internal
I2C_ICCLKL = 10;
// Config clk LOW for 1.2MHz
I2C_ICCLKH = 5;
// Config clk HIGH for 2.4MkHz
I2C_ICMDR |= ICMDR_IRS;
// Release I2C from reset
return0;
}
ICMDR(I2C Mode Register,I2C模式寄存器),其字段如图:
(用户手册P916)
将ICMDR的IRS(I2C reset bit)位置0则I2C处于复位状态。
ICPSC(I2C prescaler register,I2C预分频器寄存器),ICPSC用于将I2C输入时钟分频,获得进行I2C操作所需的预分频模块时钟。当I2C处于复位模式时(ICMDR里的IRS位为0),必须对IPSC位(bits)进行初始化。只有当IRS位置为1时,预分频频率才开始起作用。当IRS=1时,改变IPSC的值不起作用。ICPSC的字段如下:
(用户手册P922)
ICPSC=3则IPSC字段为3h,则I2C时钟频率=I2C输入时钟频率/(IPSC+1)=I2C输入时钟频率/4;I2C外设的方块图如下:
(用户手册P892)
时钟发生流程图如图:
(用户手册P894)
注意,预分频模块时钟频率必须在6.7~13.3MHz范围内。I2C0的输入时钟来自AUXCLK,AUXCLK(Auxiliary Clock)来自参考时钟源。
(用户手册P116)
Pll0结构如图:
(用户手册P117)
CLKMODE为0时,使用片上振荡器(OSC),为1时,使用外部晶振。
总时钟流程图如图:
(用户手册P105)
I2C0的时钟来自时钟源直接产生的AUXCLK,见下图:
(用户手册P114)
默认情况下,时钟系统运行在旁通模式(bypass mode)下,系统时钟(OSCIN)直接由PLLCTL(PLL control register,PLL控制寄存器)的CLKMODE位所选择的输入参考时钟所提供(方波或内部振荡器(crystal,晶振))
(用户手册P116)
Uint8 CLKMODE = 0;
…
/*Select the Clock Mode bit 8 asExternal Clock or On Chip Oscilator*/
PLL0_PLLCTL&= 0xFFFFFEFF;
PLL0_PLLCTL |= (CLKMODE<<8);
/* Make CLKSRCas BootPacket to pass the value*/
PLLCTL寄存器定义如下:
(用户手册P123)
当CLKMODE位为0时,使用晶振。
(用户手册P894)
当ICMDR寄存器的IRS位置1时,预分频频率才会生效。
2.2 I2C写函数
函数声明如下Int16 C6747_I2C_write(Uint16 i2c_addr, Uint8* data, Uint16 len ),其中Uint8为unsigned char型,对32位机来讲就占一个word(字)的长度。
I2C_ICCNT = len; // Set length
I2C_ICCNT记录发送的字(word)数。
(用户手册P912)
I2C_ICSAR = i2c_addr; // Set I2C slave address
ICSAR(I2C slave addressregister)为I2C从地址,包含了一个7位的或10位的从地址。当ICMDR寄存器的XA位为0时,选择7位地址。
(用户手册P914)
I2C_ICMDR = 0x6E20; // Set for Master Write
设置该I2C设备为主设备模式(master mode),发送器模式(transmittermode)
(用户手册P917)
I2C_ICDXR = data[i];
ICDXR为I2C数据发送寄存器,发生的数据最多可以到8位,其他的位作保留位。
(用户手册P915)
I2C_ICSTR(I2CInterrupt Status Register,ICSTR),I2C中断状态寄存器,当数据从ICDXR寄存器拷贝到ICXSR寄存器后,ICSTR的ICXRDY位将会置1,表示ICDXR准备好接收新的数据了。
(用户手册P909)
一点疑问:
I2C的时钟初始化函数C6747_I2C_init中,ICPSC=3,由于外部晶振为24MHz,则预分频模块时钟频率(Prescaled module clock)应为24/(ICPSC+1)=6MHz,而手册要求该频率在67~13.3MHz之间,按理说应该会有问题,但是实验又没有出现问题。而程序注释写着该频率为12MHz,难道是注释有误?还是我理解错了。而注释写I2C时钟频率为20KHz,但是根据公式,值也不对。此处还是没能理解。