DSP

tms320c6747的I2C模块

2019-07-13 16:18发布

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,但是根据公式,值也不对。此处还是没能理解。