s3c2440的IIC控制

发布时间:2024-08-29  

在tq2440和mini2440上都连接着EEPROM 它们作用也不过測试I2C总线能否用。


当中在mini2440上EEPROM型号是 AT24C08,在tq2440上这个型号是 AT24C02A。


它们之间容量不同。地址线也不一样。


S3C2440A RISC 微处理器能够支持一个多主控 IIC 总线串行接口。一条串行数据线(SDA)和一条专用时钟线(SCL) 连接到 IIC 总线的总线主控和外设之间。SDA 和 SCL 线都为双向的。都连接到GPE14(SCL)  GPE15(SDA)。


为了控制多主控 IIC 总线操作,必须写入值到下面寄存器中:

– 多主控 IIC 总线控制寄存器,IICCON

– 多主控 IIC 总线控制/状态寄存器,IICSTAT

– 多主控 IIC 总线 Tx/Rx 数据移位寄存器,IICDS

– 多主控 IIC 总线地址寄存器,IICADD

因为我们仅仅把s3c2440当做主设备来用,而且系统的IIC总线上仅仅有这么一个主设备,因此用来设置从设备地址的地址寄存器IICADD无需配置。  


S3C2440A 的 IIC 总线接口有 4 种工作模式:

– 主机发送模式

– 主机接收模式

– 从机发送模式

– 从机接收模式


起始和停止条件

当 IIC 总线接口不活动时,其通常在从机模式。


换句话说,该接口在从 SDA 线上检測到起始条件之前应该处于从机模式(当 SCL 时钟信号为高时的一个高到低 SDA 的变化可


以启动一个起始条件)。当接口状态被改为主机模式时,能够起始发送数据到 SDA 上而且产生 SCL 信号。


起始条件能够传输 1 字节串行数据到 SDA 线上,而停止条件能够结束


数据的传输。


停止条件是在当 SCL 为高时的 SDA 线低到高的变化。起始和停止条件总由主机产生。当产生了一个起始条件时 IIC 总线变为忙。停止条件将使得 IIC 总线空暇。


当主机发起一个起始条件时,其应该送出一个从机地址来通知从设备。


地址字段的 1 字节由 7 位地址和 1 位传输方向标志(表现为读或写)组成。


假设位[8]为 0,其表示一个写操


作(发送操作);假设位[8]为 1,其表示一个数据读取的请求(接收操作)。


主机将通过发送一个停止条件来完毕传输操作。假设主机希望持续发送数据到总线上,其应该在同一个从地址产生再一个起始条件。这样就能够运行各种格式的读写操作。

注意到在 起始 和 停止 条件之间还有若干个SCL时钟。 用来发送数据。


传输数据格式

放置到 SDA 线上的每一个字节应该以 8 位为长度。


每次传输字节能够无限制的发送。起始条件随后的第一个字节应该包括地址字段。当 IIC 总线工作在主机模式时能够由主机


发送该地址字段。


每一个字节都应该尾随一个应答(ACK)位。


总是最先发送串行数据和地址的 MSB。

上图勘误   这里图例应该反过来  ---  灰色框表示从从机到主机,看来翻译文档的人还不够细心呢。


上面提到了4中工作模式,在这里我们仅仅把s3c2440当做IIC总线的主设备来使用。因此仅仅介绍前两种操作模式。


首先看下主设备发送流程图:

首先配置IIC模式,然后把从设备地址写入 接收发送数据移位寄存器IICDS  中。再把0xF0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号。如果想要继续发送数据。那么在接收到应答信号后,再把待发送的数据写入寄存器IICDS中,清除中断标志后。再次等待应答信号。假设不想再发送数据了,那么


把0x90写入寄存器IICSTAT中,清除中断标志并等待停止条件后。即完毕了一次主设备的发送。


代码例如以下:


//AT24C02A页写,当sizeofdate为1时。是字节写

//输入參数依次为设备内存地址、IIC数据缓存数组和要写入的数据个数

void __attribute__((optimize('O0'))) wr24c02a(UINT8 wordAddr,UINT8 *buffer,UINT32 sizeofdate )

{

int i;

i2cflag =1;                               //应答标志


rIICDS = devAddr;

rIICSTAT = 0xf0;                 //主设备发送模式

rIICCON &= ~0x10;            //清中断标志


while(i2cflag == 1)                   //等待从设备应答,

OSTimeDly(2);                   //一旦进入IIC中断,就可以跳出该死循环


i2cflag = 1;


rIICDS = wordAddr;            //写入从设备内存地址

rIICCON &= ~0x10;


while(i2cflag)

OSTimeDly(2);


//连续写入数据

for(i=0;i {

i2cflag = 1;

rIICDS = *(buffer+i);

rIICCON &= ~0x10;

while(i2cflag)

OSTimeDly(2);

}


rIICSTAT = 0xd0;         //发出stop命令,结束该次通讯

rIICCON = 0xe0;          //为下次IIC通讯做准备


OSTimeDly(100);

}

上面有2点地方须要说明。1点是刚開始的初始化 rIICCON  一定要在 rIICSTAT 后面赋值。

第2点是因为这是在多任务环境下执行的,while后面跟的OSTimeDly有延迟,也就是说假设OSTimeDly(2)延迟10ms,而在1ms的时候中断发生了。这里


仍然要延迟10ms才干继续运行,能够考虑用信号量替代。这样一旦发生中断,从中断出来之后就会马上继续运行。


然后就是主设备接收流程图:

首先配置 IIC 模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xB0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号。假设想要接收数据,那么在应答信号后。读取寄存器IICDS,清除中断标志;假设不想接收数据了,那么就向寄存器IICSTAT写入0x90。清除中断标志并等待停止条件后,即完毕了一次主设备的接收。


//AT24C02A的序列读,当sizeofdate为1时,是随机读

//输入參数依次为设备内存地址、IIC数据缓存数组和要读取的数据个数

void rd24c02a(UINT8 wordAddr,UINT8 *buffer,UINT32 sizeofdate )

{

int i;

unsigned char temp;


i2cflag =1;

rIICDS = devAddr;                     //


rIICCON &= ~0x10;            //清中断标志

rIICSTAT = 0xf0;                 //主设备发送模式


while(i2cflag)

OSTimeDly(2);


i2cflag = 1;


rIICDS = wordAddr;

rIICCON &= ~0x10;

while(i2cflag)

OSTimeDly(2);


i2cflag = 1;

rIICDS =  devAddr;            //

rIICCON &= ~0x10;           

rIICSTAT = 0xb0;                //主设备接收模式

while (i2cflag)

OSTimeDly(2);


i2cflag = 1;

temp = rIICDS;                    //读取从设备地址

rIICCON &= ~0x10;

while(i2cflag)

OSTimeDly(2);


//连续读

for(i=0;i {

i2cflag = 1;

if(i==sizeofdate-1)                             //假设是最后一个数据

rIICCON &= ~0x80;                   //不再响应

*(buffer+i) = rIICDS;

rIICCON &= ~0x10;

while(i2cflag)

OSTimeDly(2);

}


rIICSTAT = 0x90;         //结束该次通讯

rIICCON = 0xe0;          //


OSTimeDly(100);

}


s3c2440的 IIC 时钟源为PCLK。当系统的 PCLK 为50MHz。而从设备最高须要100kHz时,须要配置IICCON寄存器   例如以下图所看到的:

系统初始化时候配置iic寄存器例如以下:


void init_i2c(void)

{

rGPEUP  |= 0xc000;                  //Pull-up disable   

rGPECON |= 0xa0000000;                //GPE15:IICSDA , GPE14:IICSCL     


rINTMSK &= ~(1<<27); /// enable i2c

rIICCON  = 0xe0;                        //设置IIC时钟频率,使能应答信号,并开启中断

rIICSTAT = 0x10;

pIRQ_IIC = (UINT32)i2c_isr;

}


在 i2c_isr 里面也不过把 i2cflag 赋值为0:

void i2c_isr(void)

{

i2cflag = 0;

}


详细的代码能够从我的github上clone。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>