早上正点原子的逻辑分析仪到了,那正好分析IIC过程会比较舒服,SPI的协议我也更新了,最后把完整的波形已经放到了最后,大家有兴趣也可以看看。
IIC的初始化非常简单,程序如下
void init_i2c0(void)
{
i2c_master_config_t masterConfig;
/* Enables clock for switch matrix.: enable */
CLOCK_EnableClock(kCLOCK_Swm);
/* I2C0_SDA connect to P0_7 */
SWM_SetMovablePinSelect(SWM0, kSWM_I2C0_SDA, kSWM_PortPin_P0_7);
/* I2C0_SCL connect to P0_14 */
SWM_SetMovablePinSelect(SWM0, kSWM_I2C0_SCL, kSWM_PortPin_P0_14);
/* Disable clock for switch matrix. */
CLOCK_DisableClock(kCLOCK_Swm);
CLOCK_Select(kI2C0_Clk_From_MainClk);
/*
* masterConfig.debugEnable = false;
* masterConfig.ignoreAck = false;
* masterConfig.pinConfig = kI2C_2PinOpenDrain;
* masterConfig.baudRate_Bps = 100000U;
* masterConfig.busIdleTimeout_ns = 0;
* masterConfig.pinLowTimeout_ns = 0;
* masterConfig.sdaGlitchFilterWidth_ns = 0;
* masterConfig.sclGlitchFilterWidth_ns = 0;
*/
I2C_MasterGetDefaultConfig(&masterConfig);
/* Change the default baudrate configuration */
masterConfig.baudRate_Bps = 100000U;
/* Initialize the I2C master peripheral */
I2C_MasterInit(I2C0, &masterConfig, CLOCK_GetFreq(kCLOCK_MainClk));
}
分配一个结构体用以设置
映射管脚
开启IIC时钟,还是mainclk,15Mhz那条
获取默认配置,并修改通信速率。这里默认配置也放在这里了,一般不用怎么更改,如果大家需要可以看一下详细配置,根据实际情况修改。
将配置信息初始化
整个过程没有什么难度,都是非常常见的简单。
额外说一句官方的例程又又又有问题了,在这个最简单的例程里,i2c的时钟频率是15Mhz,而非12Mhz,我当初第一次测试的时候发现SCL的时钟频率不是设置的100K,而是125K,然后一查程序发现是时钟不对,但是我又查了时钟发现实际是15Mhz,难怪
真是不知道当初开发这个工程的工程师是不是996太多了,竟然出现这样的问题,以前的程序都是读取主时钟的,包括这次我的程序里也是,真是怪了。
程序如下
void i2c0_senddata(unsigned char *senddata,unsigned char datalength,unsigned char address)
{
unsigned char reVal=kStatus_Fail;
/* Send master blocking data to slave */
if (kStatus_Success == I2C_MasterStart(I2C0, address, kI2C_Write))
{
reVal = I2C_MasterWriteBlocking(I2C0, senddata, datalength, kI2C_TransferDefaultFlag);
I2CCHECKACK;
reVal = I2C_MasterStop(I2C0);
I2CCHECKACK;
}
}
首先是发送起始信号,当得到应答才继续
这个函数的原型如下,第一个参数是指定IIC(I2C0/I2C1)第二个参数是需要传输信息的基地址,第三个参数是传输长度,最后是标志位。
发送完毕后我们可以进行检测,看看是否有应答,我这里用宏定义进行了封装
之后是发送停止信号
这就是整个发送过程了
这里我借鉴eeprom的通信过程进行介绍,因为eeprom里面包含了重发开始信号,过程会复杂一点,程序如下
void i2c0_recivedata(void)
{
unsigned char reVal=kStatus_Fail;
unsigned char deviceAddress[2]={0,0};
if (kStatus_Success == I2C_MasterStart(I2C0, 0x50, kI2C_Write))
{
reVal = I2C_MasterWriteBlocking(I2C0, &deviceAddress, 2, kI2C_TransferNoStopFlag);
I2CCHECKACK;
reVal = I2C_MasterRepeatedStart(I2C0, 0x50, kI2C_Read);
I2CCHECKACK;
reVal =
I2C_MasterReadBlocking(I2C0, g_master_rxBuff, 3, kI2C_TransferDefaultFlag);
I2CCHECKACK;
reVal = I2C_MasterStop(I2C0);
I2CCHECKACK;
}
}
首先申请的标志位,和发送地址
之后是发送开始信号,从机地址0x50,主机写
然后是先发送两个数据,注意这里无需停止信号
之后是读取过程,与写入类似,第一个参数指定iic,第二个参数是主机接受数据地址,第三个参数是数据长度,最后一个参数是开启标准位
这里我一共发送五个数据,数据如下,从机地址是0x50
我这里从机发送3个数据,00 11 22
结果如下,可以看到从机顺利接收和发送数据了
波形也非常漂亮,最后看一下主机,三个数据也读进来了
至此三大主要通信协议我们都已经说过了,可以感觉到NXP的通信协议做的是非常流畅的,数据等等都能顺利读取到,程序也很简单。LPC804还有最后AD/DA两章没有讲,年前应该是能做完的了。好了,还是那句话,有问题欢迎评论区讨论,那么我们下一篇文章见。