Chinaunix首页 | 论坛 | 博客
  • 博客访问: 469997
  • 博文数量: 98
  • 博客积分: 3265
  • 博客等级: 中校
  • 技术积分: 1227
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 00:29
文章分类

全部博文(98)

文章存档

2012年(6)

2011年(83)

2010年(9)

分类: 嵌入式

2011-03-19 17:19:19

S3C2440A 的IIC 总线接口有4 种工作模式:
– 主机发送模式
– 主机接收模式
– 从机发送模式
– 从机接收模式
这里把S3C2440A单做主机,AT24C08单做从机,讲解主机发送模式,主机接收模式

I2C总线的数据传输协议如下:

1)、主器件发出开始信号

2)、主器件发出第一个字节,用来选通相应的从器件。其中前7位为地址码,第8位为方向位(R/W)。方向位为“0”表示发送,方向位为“1”表示接受。

3)、从机产生应答信号,进入下一个传送周期,如果从器件没有给出应答信号,此时主器件产生一个结束信号使得传送结束,传送数据无效。

4)、接下来主、从器件正式进行数据的传送,这时在I2C总线上每次传送的数据字节数不限,但每一个字节必须为8位(传送的时候先送高位,再送低位)。当一个字节传送完毕时,再发送一个应答位(第9位),如上一条所述,这样每次传送一个字节都需要9个时钟脉冲。

每一次传送之后都要进行应答,除非到了最后一个数据

当主器件传送一个字节后,在第9SCL时钟内置高SDA线,而从器件的响应信号将SDA拉低,从而给出一个应答位。

当使用24WC08 时最多可连接2 个器件且仅使用地址管脚A2 A0 A1 管脚未用可以连接到

Vss(地) 或悬空如果只有一个24WC08 被总线寻址A2 管脚可悬空或连接到Vss

  1. #include "2440addr.h"
  2. #include "uart.h"
  3. #include "def.h"
  4. #include "IIC.h"


  5. extern void Delay(int time);
  6. //全局变量
  7. static U8 _iicData[IICBUFSIZE];
  8. static volatile int _iicDataCount;
  9. static volatile int _iicStatus;
  10. static volatile int _iicMode;
  11. static int _iicPt;            //指针


  12. void __irq IicInt(void)
  13. {
  14.     U32 iicSt,i;
  15.     
  16.     rSRCPND = BIT_IIC; //Clear pending bit
  17.     rINTPND = BIT_IIC;
  18.     //iicSt = rIICSTAT;
  19.     
  20.     //if(iicSt & 0x8){} //When bus arbitration is failed.
  21.     //if(iicSt & 0x4){} //When a slave address is matched with IICADD
  22.     //if(iicSt & 0x2){} //When a slave address is 0000000b
  23.     //if(iicSt & 0x1){} //When ACK isn't received

  24.     switch(_iicMode)
  25.     {
  26.        //case POLLACK:
  27.         // _iicStatus = iicSt;
  28.          // break;

  29.        case RDDATA:
  30.            if((_iicDataCount--)==0)
  31.            {
  32.                _iicData[_iicPt++] = rIICDS;
  33.             
  34.                rIICSTAT = 0x90; //Stop MasRx condition
  35.                rIICCON = 0xaf; //Resumes IIC operation.
  36.                Delay(1); //Wait until stop condtion is in effect.
  37.                                                 //Too long time...
  38.                                                 //The pending bit will not be set after issuing stop condition.
  39.                break;
  40.            }
  41.            _iicData[_iicPt++] = rIICDS; //The last data has to be read with no ack.

  42.            if((_iicDataCount)==0)
  43.                rIICCON = 0x2f; //Resumes IIC operation with NOACK.
  44.            else
  45.                rIICCON = 0xaf; //Resumes IIC operation with ACK
  46.                break;

  47.         case WRDATA:
  48.             if((_iicDataCount--)==0)
  49.             {
  50.                 rIICSTAT = 0xd0; //Stop MasTx condition
  51.                 rIICCON = 0xaf; //Resumes IIC operation.
  52.                 Delay(1); //Wait until stop condtion is in effect.
  53.                        //The pending bit will not be set after issuing stop condition.
  54.                 break;
  55.             }
  56.             rIICDS = _iicData[_iicPt++]; //_iicData[0] has dummy.地址,不是我们要的数据
  57.             for(i=0;i<10;i++); //for setup time until rising edge of IICSCL
  58.               
  59.             rIICCON = 0xaf; //resumes IIC operation.
  60.             break;

  61.         case SETRDADDR:
  62. // Uart_Printf("[ S%d ]",_iicDataCount);
  63.             if((_iicDataCount--)==0)
  64.                 break; //IIC operation is stopped because of IICCON[4]
  65.             rIICDS = _iicData[_iicPt++];        //扔到IICDATA数据线上,串行传输
  66.             for(i=0;i<10;i++); //For setup time until rising edge of IICSCL
  67.             rIICCON = 0xaf; //Resumes IIC operation.
  68.             break;

  69.         default:
  70.             break;
  71.     }
  72. }





  73. void Wr24C080(U32 slvAddr,U32 addr,U8 data)
  74. {
  75.     _iicMode = WRDATA;
  76.     _iicPt = 0;
  77.     _iicData[0] = (U8)addr;
  78.     _iicData[1] = data;
  79.     _iicDataCount = 2;
  80.     
  81.     rIICDS = slvAddr; //0xa0
  82.     rIICSTAT = 0xf0; //MasTx,Start
  83.       //Clearing the pending bit isn't needed because the pending bit has been cleared.
  84.     
  85.     while(_iicDataCount!=-1);    //等待应答信号

  86.     _iicMode = POLLACK;

  87.     while(1)
  88.     {
  89.         rIICDS = slvAddr;
  90.         _iicStatus = 0x100;
  91.         rIICSTAT = 0xf0; //MasTx,Start
  92.         rIICCON = 0xaf; //Resumes IIC operation.
  93.            
  94.         //while(_iicStatus==0x100);//等待中断,这里无实质意义,
  95.         //只是为了看状态寄存器的值改变否?用个1ms的延时代替也可
  96.         Delay(1);
  97.            
  98.         if(!(_iicStatus&0x1))        
  99.             break; //When ACK is received
  100.     }
  101.     rIICSTAT = 0xd0; //Stop MasTx condition
  102.     rIICCON = 0xaf; //Resumes IIC operation.
  103.     Delay(1); //Wait until stop condtion is in effect.
  104.        //Write is completed.
  105. }



  106. void Rd24C080(U32 slvAddr,U32 addr,U8 *data)
  107. {
  108.     _iicMode = SETRDADDR;
  109.     _iicPt = 0;
  110.     _iicData[0] = (U8)addr;
  111.     _iicDataCount = 1;

  112.     rIICDS = slvAddr;
  113.     rIICSTAT = 0xf0; //MasTx,Start
  114.       //Clearing the pending bit isn't needed because the pending bit has been cleared.
  115.     while(_iicDataCount!=-1);    //等待中断

  116.     _iicMode = RDDATA;
  117.     _iicPt = 0;
  118.     _iicDataCount = 1;
  119.     
  120.     rIICDS = slvAddr;
  121.     rIICSTAT = 0xb0; //MasRx,Start
  122.     rIICCON = 0xaf; //Resumes IIC operation.
  123.     while(_iicDataCount!=-1);

  124.     *data = _iicData[1];//数据总是放在这个元素里面
  125. }





  126. void Test_Iic(void)
  127. {
  128.     unsigned int i,j;
  129.     static U8 data[256];

  130.     Uart_Printf("\nIIC Test(Interrupt) using AT24C02\n");

  131.     
  132.     rGPEUP |= 0xc000; //Pull-up disable
  133.     rGPECON |= 0xa00000; //GPE15:IICSDA , GPE14:IICSCL

  134.     pISR_IIC = (unsigned)IicInt;    //中断处理函数的并联,要用到MMU,因为烧到SDRAM的话,中断向量不再0x00000000那里
  135.     rINTMSK &= ~(BIT_IIC);        //开启中断

  136.       //Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
  137.       // If PCLK 50.7MHz, IICCLK = 3.17MHz, Tx Clock = 0.198MHz
  138.     rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);

  139.     //rIICADD = 0x10; //2440 slave address = [7:1],2440做从机的地址
  140.     rIICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
  141.     //rIICLC = (1<<2)|(1);         // Filter enable, 15 clocks SDA output delay added by junon
  142.     
  143.     Uart_Printf("Write test data into AT24C08\n");

  144.     for(i=0;i<256;i++)    //第一个参数:AT24C08地址,第二个参数:AT24C08内部地址,第三个参数,数据
  145.         Wr24C080(0xa0,(U8)i,i);//0xa0,0xa1无所谓,因为2440有主从机收发4种模式
  146.            
  147.     for(i=0;i<256;i++)
  148.         data[i] = 0;

  149.     Uart_Printf("Read test data from AT24C08\n");
  150.     
  151.     for(i=0;i<256;i++)
  152.         Rd24C080(0xa0,(U8)i,&(data[i])); //0xa0,0xa1无所谓,因为2440有主从机收发4种模式

  153.         //Line changed 0 ~ f
  154.     for(i=0;i<16;i++)
  155.     {
  156.         for(j=0;j<16;j++)
  157.             Uart_Printf("%2x ",data[i*16+j]);
  158.         Uart_Printf("\n");
  159.     }
  160.     rINTMSK |= BIT_IIC; //关闭中断
  161. }


说明:

1:注意那几个全局变量的值,很灵活,程序不好懂

2:发送,接受都是用到中断,尤其是应答信号,烧到SDRAM中的话,要在mian中初始化MMU,,因为烧到 SDRAM的话,中断向量已经改变了

3:操作时序按,2440芯片手册的主机收发模式操作,细细体会,出差的话很难调试的,尤其某些地方需要延时,试了好几个程序,都没成功,最终参看模板中的这个~_~

阅读(2407) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~