DSP6748 IIC读写使用

一,DSP中IIC模块框图:

1. 总线空闲状态
SDA和SCL两条信号线都处于高电平,即总线上所有的器件都释放总线,两条信号线各自的上拉电阻把电平拉高;
2. 启动信号START
时钟信号SCL保持高电平,数据信号SDA的电平被拉低(即负跳变)。启动信号必须是跳变信号,而且在建立该信号前必修保证总线处于空闲状态;
3. 停止信号STOP
时钟信号SCL保持高电平,数据线被释放,使得SDA返回高电平(即正跳变),停止信号也必须是跳变信号。
4. 数据传送
SCL线呈现高电平期间,SDA线上的电平必须保持稳定,低电平表示0(此时的线电压为低电压),高电平表示1(此时的电压由元器件的VDD决定)。只有在SCL线为低电平期间,SDA上的电平允许变化。
5. 应答信号ACK
I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个ACK(把数据总线的电平拉低)来表示数据成功接收。
6. 无应答信号NACK
在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个NACK,NACK有两种用途:
a. 一般表示接收器未成功接收数据字节;
b. 当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。

地址模式:DSP上面设计了三种地址模式,为了更好的跟外部器件接口通信。
7bit地址格式:i2c的第一个字节的高7bit为器件的地址。后面的数据bit长度可以自己设定。
10bit地址格式:i2c的第一个字节的低2bit为器件的地址的高2bit,第二字节的8bit作为器件地址的低8bit。后面的数据bit长度可以自己设定。
1,free地址格式:i2c的第一个字节的nbit为器件的地址。后面的数据bit长度可以自己设定。
通信模式:为了跟好的跟外部器件接口,DSP上面设计了两种通信模式

2,NOREAPTE:就是我们上面所说的一般通信模式,一个start信号发出一个器件地址,当这个器件收到地址之后发出应答之后,就占有i2c总线,然后进行数据通信和数据的交换,只有主机发出停止信号之后才释放总线。

3,REAPTE:就是我们上面所说的一般通信模式,一个start信号发出一个器件地址,当这个器件收到地址之后发出应答之后就占有i2c总线,然后进行数据通信和数据的交换,之后主机可以发出start信号之后继续选址其他,然后进行数据通信,然后进行数据通信。

二,函数解析

函数对C6748的IIC0模块所在复用引脚的功能配置为IIC引脚。设置SYSCFG0模块的PINMUX4寄存器的PINMUX4_15_12和PINMUX4_11_8字段都为2,则设置了引脚功能为I2C0_SDA和I2C0_SCL。

voidI2CPinMuxSetup(unsignedint instanceNum)
{
unsignedint savePinMux = 0;
if(0 == instanceNum)
{
savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) & \
~(SYSCFG_PINMUX4_PINMUX4_15_12 | \
SYSCFG_PINMUX4_PINMUX4_11_8);
 
HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) = \
(PINMUX4_I2C0_SDA_ENABLE | \
PINMUX4_I2C0_SCL_ENABLE | \
savePinMux);
}
elseif(1 == instanceNum)
{
savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) & \
~(SYSCFG_PINMUX4_PINMUX4_23_20 | \
SYSCFG_PINMUX4_PINMUX4_19_16);
HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) = \
(PINMUX4_I2C1_SDA_ENABLE | \
PINMUX4_I2C1_SCL_ENABLE | \
savePinMux);
}
}

主函数中,进行中断初始化工作,InterruptInit();函数使能全局中断,IICInterruptInit();进行IIC中断初始化,IICInterruptInit函数如下:

voidIICInterruptInit(void)
{
    IntRegister(C674X_MASK_INT6, IICIsr);
    IntEventMap(C674X_MASK_INT6, SYS_INT_I2C0_INT);
    IntEnable(C674X_MASK_INT6);
}

1,IICInterruptInit函数注册CPU#6号可屏蔽中断的服务函数为IICIsr,设置interrupt selector的INTMUX1寄存器的INTSEL6字段(INTMUX1_16_22位)为36(SYS_INT_I2C0_INT),将#36号中断事件映射到CPU#6号可屏蔽中断,然后使能CPU#6号可屏蔽中断,IntEnable(C674X_MASK_INT6)。
2,中断初始化完成后,对IIC初始化,IICInit()。

voidIICInit(void)
{
//IIC 复位 / 禁用
I2CMasterDisable(SOC_I2C_0_REGS);
// 配置总线速度为 100KHz
I2CMasterInitExpClk(SOC_I2C_0_REGS, 24000000, 8000000, 100000);
// 设置从设备地址
I2CMasterSlaveAddrSet(SOC_I2C_0_REGS, ADDRESS);
// IIC 使能
I2CMasterEnable(SOC_I2C_0_REGS);
}

(1) 函数先是复位IIC0模块,I2CMasterDisable函数清除I2C0外设的ICMDR寄存器(I2C Mode Register)的IRS位,从而复位并禁用I2C0

voidI2CMasterDisable(unsignedint baseAddr)
{
/* Bring the I2C module out of reset */
HWREG(baseAddr + I2C_ICMDR) &= ~(I2C_ICMDR_IRS);
}

 (2)I2CMasterInitExpClk(SOC_I2C_0_REGS, 24000000,8000000, 100000);函数对I2C主模块的操作进行初始化,配置I2C0的总线速度为100KHz,并使能I2C0

voidI2CMasterInitExpClk(unsignedint baseAdd, unsignedint inputClk,
unsignedint scaledClk, unsignedint outputClk)
{
unsignedint prescale = 0;
unsignedint dValue = 0;
unsignedint div = 0;
/* Calculate the prescalar value */
prescale = (inputClk/scaledClk) - 1;
HWREG(baseAdd + I2C_ICPSC) = prescale;
switch (prescale)
{
case 0:
dValue = 7;
break;
case 1:
dValue = 6;
break;
default:
dValue = 5;
break;
}
div = scaledClk/outputClk;
div -= (2*dValue);
HWREG(baseAdd + I2C_ICCLKL)= div/2;
HWREG(baseAdd + I2C_ICCLKH) = div - HWREG(baseAdd + I2C_ICCLKL);
return;
}

函数的输入参数,inputClk为输入I2C模块的时钟,I2C0的输入时钟为PLL旁路时钟,晶振的时钟为24MHz,所以inputClk为24MHz。scaledClk为经过I2C模块预分频后的时钟频率,范围应该在6.7到13.3MHz之间。OutputClk为I2C_SCL时钟线上的频率。函数对ICPSC寄存器的IPSC字段,以及ICCCLKL、ICCLKH寄存器作相应设置,从而得到正确的I2C_SCL频率。IPSC字段必须要在I2C模块处于reset/disable状态时设置,否则设置无效。

(3)I2CMasterSlaveAddrSet(SOC_I2C_0_REGS, ADDRESS);设置从机设备地址为ADDRESS(0x50,IICEEPROM地址)。I2C的slave address有7位和10位以及free mode三种形式,在7位和10位从机地址后面会跟一个读写位R/Wn,根据I2C是发送方还是接收方来决定。

voidI2CMasterSlaveAddrSet(unsignedint baseAddr, unsignedint slaveAddr)
{
/*Set the address of the slave with which the master will communicate.*/
HWREG(baseAddr + I2C_ICSAR) = slaveAddr;
}

 

(4)对I2C0的设置完成后,就可以使能I2C了I2CMasterEnable(SOC_I2C_0_REGS):

voidI2CMasterEnable(unsignedint baseAddr)
{
/* Bring the I2C module out of reset */
HWREG(baseAddr + I2C_ICMDR) |= I2C_ICMDR_IRS;
/* Set the backward compatibility mode off, for proper interruption */
HWREG(baseAddr + I2C_ICEMDR) &= ~I2C_ICEMDR_BCM;
}

三,DSP IIC读写部分

猜你喜欢

转载自blog.csdn.net/wangjie36/article/details/117914524
IIC
dsp