在学习国芯Ai8051U单片机的I2C外设的时候,例程始终没有跑通。感觉在芯片构造上,Ai8051U与STC32G12K128应该差不多,于是回过头来研究STC32G12K128,使用其I2C外设读写AT24C04。
在读写AT24C04时,WordAddress只需要一个字节就够了。以读操作为例:
AT24C04的任意地址的读操作:
通讯时序中红色标记的P0位置的值,决定访问AT24C04的前后两个256字节中的哪个页。(AT24C04为512字节空间,被划分为两个页,WordAddress是一个字节)。
使用I2C外设作为主机使用时,读写操作中,开始信号、结束信号、收发数据以及Ack、NAck信号,都是通过向I2CMSCR(主机控制寄存器)这个寄存器发送不同的指令来实现的。
测试使用了最简单的电路连接,由STC32G12K128核心板和自制面包板搭建,
原理图如下:
I2C外设使用P2.4和P2.5复用为SCL和SDA。为了便有验证测试结果,使用了串口2(使用P4.6和P4.7)作为log输出。
I2C 配置寄存器(I2CCFG)设置为0xe0,
ENI2C = 1 :表示使能I2C外设
MSSL = 1 :表示工作为主机模式
MSSPEED =100000 :根据公式:I2C 总线速度=SYSCLK / 2 / (MSSPEED * 2 + 4),本例中SYSCLK 为单片机的工作主频,预设为22118400Hz,所以I2C的通讯速度应该是162KHz,实际测试是82KHz左右,似乎是差一倍,原因还没有搞清楚。
主程序中的处理逻辑是采用读-----加一后回写-----再读的方式运行的。
//-----------------------读取数据----------------------- IIC_Read_NByte(SLAVE_24C04,0,dat,5); for( i=0;i<5;i++ ) { sprintf(str,"地址:%d,值:%d\r\n",i,dat[i]); PrintString2(str); } PrintString2( "读取结束\r\n"); delay_ms(200); //-----------------------写入修改后的数据----------------------- for( i=0;i<5;i++ ) { dat[i] = (dat[i] +1); } IIC_Write_NByte(SLAVE_24C04,0,dat,5); delay_ms(200); //-----------------------读取数据----------------------- IIC_Read_NByte(SLAVE_24C04,0,dat,5); for( i=0;i<5;i++ ) { sprintf(str,"地址:%d,值:%d\r\n",i,dat[i]); PrintString2(str); } PrintString2( "测试结束\r\n");
实际运行中通过逻辑分析仪铺捉到的I2C通讯逻辑波形如下所以,可以看到有三个明显的I2C通讯过程,就是读-写-读的三组时序。AT24C04事先通过编程器将前八个单元的数据改成了1,2,3,4,5,6,7,8。经过几次测试,数据已经被程序改变成现在的这个样子。
读入的数据时6,7,8,9,10
分别加一后,变成7,8,9,10,11,重写回原来的单元,
再次读取后显示为7,8,9,10,11。
来自串口的log信息:
工程代码:i2c.zip