• S3C2440之IIC裸机驱动


    花了两天的时间终于把这个搞定了,其实I2C的原理还是比较简单的,只是几个细节性的东西还是需要特别的注意,主要是需要注意一下几点:
    1.rIICCON &= ~0x10; 清中断必须要在rIICDS = slvAddr; 和rIICSTAT = 0xf0;  // 主设备,启动  之后

    2.延时对于写外部的低速设备来说非常重要,比如while(flag)之后一定要加延时,还有在写数据时发现只能写入基数地址的数据,这也是由于延时导致的

    3.开始调试的时候系统总是死在read的函数中,后来发现在数据手册的note中说当读取最后一个数据的时候一定不能返回ACK信号,而我却在程序中使用while(flag)来等待ACK引发中断,这不死才怪呢。。。。所以数据手册中的NOTE部分也是特别重要的

    4.在真正对AT24C02A进行读取数据时,在发送带有读命令的从设备地址后,AT24C02A会再返回一个从设备地址信息或从设备内存地址信息作为应答,所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息。

    5.下面是核心代码:

    #include "def.h"  
    #include "2440addr.h"  
    #include "I2C.h"  
    #include "uart.h"   
    extern void Delay(int time);   
    int flag;   //用于标识是否收到应答信号,改标识在终端处理程序中被清0   
    void Test_Iic(void)   
    {   
        unsigned int i,j,save_E,save_PE;   
        static U8 data[256];   
        uart_printf(" IIC Test(Interrupt) using AT24C02 ");   
        save_E   = rGPECON;   
        save_PE  = rGPEUP;   
        rGPEUP  |= 0xc000;                  //Pull-up disable   
        rGPECON |= 0xa00000;                //GPE15:IICSDA , GPE14:IICSCL    
        pISR_IIC = (unsigned)IicInt;   
        rINTMSK &= ~(BIT_IIC);   
          //Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16   
          // If PCLK 50.7MHz, IICCLK = 3.17MHz, Tx Clock = 0.198MHz   
        rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);   
        rIICADD  = 0x10;                    //2440 slave address = [7:1]   
        rIICSTAT = 0x10;                    //IIC bus data output enable(Rx/Tx)   
        rIICLC = (1<<2)|(1);                  // Filter enable, 15 clocks SDA output delay       added by junon   
           
        uart_printf("Write test data into AT24C02 ");   
        for(i=0;i<256;i++)   
           { Wr24C080(0xa0,(U8)i,i);   
            Delay(1);   //注意这个延时不能少,否则出现有些数据无法写入的问题   
           }       
        for(i=0;i<256;i++)   
            data[0] = 0;   
        uart_printf("Read test data from AT24C02 ");   
           
         for(i=0;i<256;i++)   
             Rd24C080(0xa0,(U8)i,&(data[i]));    
        for(i=0;i<16;i++)   
        {   
            for(j=0;j<16;j++)   
                uart_printf("%2x ",data[i*16+j]);   
            uart_printf(" ");   
        }   
        rINTMSK |= BIT_IIC;       
        rGPEUP  = save_PE;   
        rGPECON = save_E;   
    }   
    void Wr24C080(U32 slvAddr, U32 addr, U8 data)   
    {   
        flag=1;  //应答标志   
        rIICDS = slvAddr;    
        rIICSTAT = 0xf0;  // 主设备,启动   
            rIICCON &= ~0x10;            //清中断标志 ,特别注意这条语句的位置,不能放到上条的前面     
        while(flag == 1)   //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0   
         Delay(1);   
            
           
         flag =1 ; //readly to translate addr   
         rIICDS = addr;    
         rIICCON &= ~0x10;            //清中断标志   
         while(flag == 1)   //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0   
         Delay(1);   
            
         flag =1 ; //readly to translate data   
         rIICDS = data;    
         rIICCON &= ~0x10;            //清中断标志   
         while(flag == 1)   //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0   
         Delay(1);   
            
        rIICSTAT = 0xd0;                    //Stop MasTx condition    
        rIICCON  = 0xaf;                    //Resumes IIC operation.    
        Delay(1);   
           
    }   
      
    void Rd24C080(U32 slvAddr, U32 addr, U8 *data)   
    {   
        unsigned char temp;   
        flag=1;  //应答标志   
        rIICDS = slvAddr;    
        rIICSTAT = 0xf0;  // 主设备发送模式用来发送slvAddr和addr,,启动   
        rIICCON &= ~0x10;            //清中断标志   
        while(flag == 1)   //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0   
         Delay(1);   
            
        flag =1 ; //readly to translate addr   
         rIICDS = addr;    
         rIICCON &= ~0x10;            //清中断标志   
         while(flag == 1)   //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0   
         Delay(1);   
               
        flag=1;   
        rIICDS = slvAddr;    
        rIICSTAT = 0xb0;  // 主设备接收模式用来接收数据,启动   
            rIICCON &= ~0x10;            //清中断标志   
        while(flag == 1)   //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0   
         Delay(1);   
           
        //注意:读取下面这个字节必须进行,因为在发送带有读命令的从设备地址后,   
        //AT24C02A会再返回一个从设备地址信息或从设备内存地址信息作为应答,所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息;   
        flag =1 ; //readly to translate addr   
        temp = rIICDS;   // 抛弃第一自己   
        rIICCON &= ~0x10;            //清中断标志   
        while(flag)   
         Delay(1);   
            
        rIICCON = 0x2f;                  //Resumes IIC operation with NOACK.    
        *data = rIICDS;    
        Delay(1);   
         rIICSTAT = 0x90;                    //Stop MasTx condition    
         rIICCON  = 0xaf;                    //Resumes IIC operation.   
               
         Delay(1);   
           
    }   
      
    //-------------------------------------------------------------------------   
    void __irq IicInt(void)   
    {   
        
        rSRCPND = BIT_IIC;          //Clear pending bit   
        rINTPND = BIT_IIC;   
        flag = 0;   
          

    原文链接:http://www.linuxidc.com/Linux/2011-06/37583p4.htm

  • 相关阅读:
    THUPC2018 好图计数
    CF1349F1
    CF1098E
    [HNOI2011]卡农
    CF736D Permutations(伴随矩阵)
    uoj310【UNR #2】黎明前的巧克力(FWT)
    知识点简单总结——常系数齐次线性递推
    知识点简单总结——带花树(一般图最大匹配)
    知识点简单总结——Pollard-Rho算法
    知识点简单总结——二次剩余
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3206462.html
Copyright © 2020-2023  润新知