天嵌 ARM开发社区

 找回密码
 注册
查看: 2624|回复: 2

基于S3C2440的24C02的IIC总线操作

[复制链接]
Romatom 发表于 2012-10-12 18:33:49 | 显示全部楼层 |阅读模式
S3C2440对24C02的IIC总线基本操作

#include"2440addr.h"
#include"iic.h"
#include"uart.h"

int TT;

void Delay(int time) //延时程序(精确)
{
        unsigned int val = (50000000>>3)/1000-1;
       
        rTCFG0 &= ~(0xff<<8);
        rTCFG0 |= 3<<8;                        //prescaler = 3+1
        rTCFG1 &= ~(0xf<<12);
        rTCFG1 |= 0<<12;                //mux = 1/2

        rTCNTB3 = val;
        rTCMPB3 = val>>1;                // 50%
        rTCON &= ~(0xf<<16);
        rTCON |= 0xb<<16;                //interval, inv-off, update TCNTB3&TCMPB3, start timer 3
        rTCON &= ~(2<<16);                //clear manual update bit
        while(time--) {
                while(rTCNTO3>=val>>1);
                while(rTCNTO3<val>>1);}
}


void __irq IicIn(void)
{
        rSRCPND |= (BIT_IIC);
        rINTPND |= (BIT_IIC);
        TT=0;
}

void Test_Iic(void)
{
        int i;

        unsigned int save_E,save_PE;
        static unsigned char A_1='0',A_2='0';
        save_E = rGPECON;
        save_PE = rGPEUP;
        rGPEUP  |= 0xc000;                //这句代码的意图禁止GPE14和GPE15上拉,可是真有用吗?S3C2440数据手册上明明写着
                                                        //This pad is open-drain,There is no Pull-up option
        rGPECON |= 0xa0000000;   //很多资料均写的0xa00000;我都不知道他们是不是真的在S3C2440
                                                         //到底跑过,写出来害我类初学者
                                                       
        pISR_IIC = (unsigned int)IicIn;        //装载中断函数
        rINTMSK &= ~(BIT_IIC);        //使能IIC中断
       
        rIICCON = (1<<7)|(0<<6)|(1<<5)|(0xf); //ACk、接收发送中断的使能,总线发送时钟的设置
       
        rIICADD = 0x10;                //给主机分配作为从机时的总线地址,在本试验S3C2440一直作为主机,可设置也可不设置。但是注意了
                                                //如果要写入这个地址,必须首先确认IICSTAT[4]=0,关于读取却可以在任意时刻。
        rIICSTAT = 0x10;        //IIC bus data output enable(Rx/Tx)
        rIICLC = (1<<2)|(1);        //总线线路控制寄存器,这个可以不设置。
       
        putc('A');
       
        A_1='U';
        for(i=65;i<91;i++)                //我想向AT24C02中写入‘a?~‘z'字母,直接使用ASCII码
        {A_1=i;
        Wr24c02(0xa0,i-65,A_1);}
        Wr24c02(0xa0,2,'M');
        for(i=0;i<256;i++)
        {Rd24c02(0xa0,i,&A_2);
        putc(A_2);}
        putc('A');
        rINTMSK |= BIT_IIC;        //禁止中断操作
        rGPEUP = save_PE;        //恢复IO口
        rGPECON = save_E;
}


void Delay_1(int time) //延时程序,为了操作对AT24C02总线时序时滞和硬件反应时间的控制
{
        int i,j;
        for(j=0;j<time;j++)
                for(i=0;i<10;i++);
}

void Wr24c02(unsigned char slvaddr,unsigned char addr,unsigned char data)
{
        rIICDS = slvaddr; //将从机器地址发送到接收发送数据寄存器IICDS中
        rIICSTAT = 0xf0;        //配置为主发送模式,(写)开始信号输出,滞后IICDS中的数据开始发送
        TT=1;                                //中断标记,相信大家都知道它用来干嘛
        while(TT)                // waitting for interrput 1,第一个ACK后当然要产生中断了。见图1的信号操作过程
                Delay_1(10);
        rIICDS = addr;        //送入写入首地址
        Delay_1(1);                //为了实现IICSCL上升沿的建立时间
        rIICCON = 0xaf;        //Resumes IIC operation.清除了IIC中断标记,不清除的话,总线将持续挂起,清除后开始传送数据了
        TT=1;
        while(TT)                // waitting for interrput 2,第二个ACK后的中断
                Delay_1(10);
        rIICDS = data;        //将数据送到IICDS中
        Delay_1(1);
        rIICCON = 0xaf;        //同上
        TT=1;
        while(TT)                // waitting for interrput 3,第三个ACK后的中断
                Delay_1(10);
        rIICSTAT = 0xd0; //生成停止信号(写模式下IICSTAT[5]的定义可知)
        rIICCON = 0xaf;                //恢复操作
        //Delay(1);
       
        /*rIICDS = slvaddr;
        rIICSTAT = 0xf0;
        rIICCON = 0xaf;
        TT=1;
        while(TT)                // waitting for interrput 4
                Delay_1(10);
        while(!(rIICSTAT&0x01));
        rIICSTAT = 0xd0;
        rIICCON = 0xaf;*///上诉几行代码是我在参考TQ2440测试程序代码中写的,说是ACK模式下的操作,在这里的简单操作模式中没有也可以。
        Delay(10);
}

void Rd24c02(unsigned char slvaddr,unsigned char addr,unsigned char *data)
{
        unsigned char temp;
        rIICDS = slvaddr;//发送从机地址,实现伪写
        rIICSTAT = 0xf0; //配置为主发送模式,(写)开始信号输出,滞后IICDS中的数据开始发送
        TT=1;
        while(TT)                // waitting for interrput 1
                Delay_1(10);
        rIICDS = addr; //将首地址送入rIICDS
        Delay_1(1);
        rIICCON = 0xaf;//Resumes IIC operation.清除了IIC中断标记,不清除的话,总线将持续挂起,清除后开始传送数据了
        TT=1;
        while(TT)                // waitting for interrput 2
                Delay_1(10);
        rIICDS = slvaddr;        //发送从机地址,实现真正从机的发送
        rIICSTAT = 0xb0;        //配置接收模式
        rIICCON = 0xaf;//Resumes IIC operation.清除了IIC中断标记,不清除的话,总线将持续挂起,清除后开始传送数据了
        TT=1;
        while(TT)                // waitting for interrput 3
                Delay_1(10);
       
        temp =rIICDS;                //发送带有读命令的从设备地址后,24C02再返回一个从设备地址信息或从设备内存地址信息作为应答
                                                //所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息。
        rIICCON = 0x2f;
        TT=1;
        while(TT)                // waitting for interrput 4
                Delay_1(10);
        *data = rIICDS;
        rIICSTAT = 0x90;
        rIICCON = 0xaf;
        Delay(10);
}

这段程序费了我一周时间,由于本人是初学者有点难度,相信这些代码对其他初学者IIC总线的学习有所帮助。
亚瑟王 发表于 2012-10-13 09:21:19 | 显示全部楼层
好帖子,加精了,送给你5个金币。
 楼主| Romatom 发表于 2012-10-15 10:37:49 | 显示全部楼层
亚瑟王 发表于 2012-10-13 09:21
好帖子,加精了,送给你5个金币。

:D:):P:$谢谢了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-5-2 07:04 , Processed in 1.046875 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表