mini2440裸机编程-----IIC—读写AT24C08

发布者:CaptivatingGaze最新更新时间:2022-01-14 来源: eefocus关键字:mini2440  裸机编程  IIC 手机看文章 扫描二维码
随时随地手机看文章

开始弄2440的裸机编程,争取尽快从最底层把这些硬件都熟悉掌握。


最初始从配置裸机开发环境开始的,本来想用jlink+ADS来进行下载,结果用ADS的调试器AXD通过jlink进行下载的时候,软件总是出现各种问题,这个问题折腾了有10天的时间,浪费了很长时间,最后重装了系统,都没有搞定。最后决定还是通过ADS来编译,然后用supervivi来进行下载了。现在经常出现的问题是 usb下载器总是识别不到,而且有时会导致电脑重启,应该是友善之臂提供的usb的驱动的问题,这些问题经常导致我折腾很长时间,心情很沮丧。有碰到并解决了类似问题的同学可以给我留个言。闲话少叙。


最开始写了uart的驱动试验,然后做了iic和iis的试验。先记录iic的试验,以后再补上uart的部分。


IIC(Inter-Integrated Circuit,I2C)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微处理器及其外围设备,它只需要数据线SDA和时钟线SCL,就能够实现CPU与被控IC之间、IC与IC之间进行双向传送。


s3c2440内部有一个IIC总线接口,因此为我们连接带有IIC通信模块的外围设备提供了便利。它具有四种操作模式:主设备发送模式、主设备接收模式、从设备发送模式和从设备接收模式。在这里我们只把s3c2440当做IIC总线的主设备来使用,因此只介绍前两种操作模式。


在主设备发送模式下,它的工作流程为:


1. 配置IIC模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xF0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号,如果想要继续发送数据,那么在接收到应答信号后,再把待发送的数据写入寄存器IICDS中,清除中断标志后,再次等待应答信号;如果不想再发送数据了,那么把0x90写入寄存器IICSTAT中,清除中断标志并等待停止条件后,即完成了一次主设备的发送。


在主设备接收模式下,它的工作流程为:


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


数据手册中有两个流程图,非常清晰。在完成上述两个模式时,主要用到了控制寄存器IICCON、控制状态寄存器IICSTAT和发送接收数据移位寄存器IICDS。由于我们只把s3c2440当做主设备来用,并且系统的IIC总线上只有这么一个主设备,因此用来设置从设备地址的地址寄存器IICADD,和用于仲裁总线的多主设备线路控制寄存器IICLC都无需配置。寄存器IICCON的第6位和低4位用于设置IIC的时钟频率,因为IIC的时钟线SCL都是由主设备提供的。s3c2440的IIC时钟源为PCLK,当系统的PCLK为50MHz,而从设备最高需要100kHz时,可以将IICCON的第6位置1,IICCON的低4位全为0即可。寄存器IICCON的第7位用于设置是否发出应答信号,第5位用于是否使能发送和接收中断,第4位用于中断的标志,当接收或发送数据后一定要对该位进行清零,以清除中断标志。寄存器IICSTAT的高2位用于设置是哪种操作模式,当向第5位写0或写1时,则表示结束IIC或开始IIC通讯,第4位用于是否使能接收/发送数据。


由于通讯是双方的事情,在了解了主设备的操作模式后,还要清楚从设备的运行机制,两者要达到完美地结合,才能实现彼此的通讯。在这里,从设备是EEPROM——AT24C08。在看到的赵老师的博客中,他是对AT24c02a进行的读写。我觉得这两个eeprom基本上是一样的。


要想让s3c2440能够正确地对AT24C02A读写,就必须让s3c2440的时序完全按照AT24C02A的时序。AT24C02A的写操作有两种模式:字节写和页写。字节写是先接收带有写命令的设备地址信息,如果符合就应答,再接收设备内存地址信息,发出应答后,再接收要写入的数据,这样就完成了字节写过程。页写与字节写的区别就是,页写可以一次写多个数据,而字节写只能一次写一个数据。但由于AT24C02A的一页才8个字节,所以页写也最多写8个数据,而且只能在该页内写,不会发生一次页写同时写两页的情况。AT24C02A的读操作有三种模式:当前地址读、随机读和序列读。当前地址读是只能读取当前地址内的数据,它的时序是先接收带有读命令的设备地址信息,如果符合就应答,然后发送当前地址内的数据,在没有接收从主设备发来的应答信号的情况下终止该次操作。随机读的时序是,连续接收带有写命令的设备地址信息和设备内存地址信息,然后主设备重新开启IIC通信,AT24C02A再次接收到带有读命令的设备地址信息,在发出应答信号以后,发送该内存地址的数据,在没有接收到任何应答信号的情况下结束该次通信。当前地址读和随机读一次都只能读取一个数据,而序列读一次可以读取若干个数据,它的时序就是在当前地址读或随机读发出数据后,接收到了应答信号,那么AT24C02A会把下一个内存地址中的数据送出,除非AT24C02A接收不到任何应答信号,否则它会一直把下一个内存地址中的数据送出。序列读没有一页8个字节的限制。


这里是赵老师写的注意事项:


⑴清IIC中断标志语句rIICCON &= ~0x10;一定要在读写寄存器IICDS的后面,不能放到它的前面;


⑵在等待应答的死循环while内,一定要加上延时的程序;


⑶在读取AT24C02A数据时,当读到最后一个数据时,一定不能让s3c2440发送应答信号,否则以后会无法再读取AT24C02A数据,除非关电重启;


⑷在真正对AT24C02A进行读取数据时,在发送带有读命令的从设备地址后,AT24C02A会再返回一个从设备地址信息或从设备内存地址信息作为应答,所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息;(这里在看at24c08的数据手册中,并没有看到有这个。)


⑸按照AT24C02A的时序,在发送从设备地址字节时,它的最低位是0表示写,1表示读。但对于s3c2440来说,不用人为设置这一位,即是0是1都无所谓,因为这一位是由s3c2440根据是主设备发送模式还是主设备接收模式来自动设置。


我把赵老师的源程序,修改了一下,经过反复试验,刚开始弄错了i2c地址,结果只实现了eeprom的写入,读数据时,读出来的都是0xff。


赵老师的程序中,读取数据的函数如下


void rd24c02a(unsigned char wordAddr,unsigned char *buffer,int sizeofdate )

{

       int i;

       unsigned char temp;

       flag =1;

       rIICDS = devAddr;                     //

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

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

       while(flag)

              delay(100);

      

       flag = 1;

       rIICDS = wordAddr;

       rIICCON &= ~0x10;

       while(flag)

              delay(100);

             

       flag = 1;

       rIICDS =  devAddr;            //

       rIICCON &= ~0x10;           

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

       while (flag)

              delay(100);

             

       flag = 1;

       temp = rIICDS;                //读取从设备地址, 这小段程序按照24c08的手册,我觉得是完全没必要的。

       rIICCON &= ~0x10;

       while(flag)

              delay(100);

 

//连续读

       for(i=0;i       {

              flag = 1;

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

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

              *(buffer+i) = rIICDS;

              rIICCON &= ~0x10;

              while(flag)

                     delay(100);

       }

      

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

       rIICCON = 0xe0;          //

      

       delay(100);                         

}


后来我修改了i2c地址之后,程序可以实现正确的读写。令我不解的是,为什么当i2c地址是错误时,mcu仍然可以收到ack信号,并且进入中断函数呢?下面附上我的源程序。

#include

#include

 

#include "def.h"

#include "option.h"

#include "2440addr.h"     

#include "2440lib.h"

#include "2440slib.h"    

#include "mmu.h"  

#include "led.h"

 

unsigned char flag;                  //应答标志

unsigned char comm;                  //命令

//unsigned char devAddr=0x10 << 1;          //从设备AT24C02A的地址

unsigned char devAddr=0xa0 << 1; //从设备AT24C02A的地址 

//IIC通信中断

void __irq IicISR(void)

{

  //   rSRCPND |= 0x1<<27;

  //   rINTPND |= 0x1<<27;

  

   ClearPending(BIT_IIC);

       flag = 0;                //清标志

       led_toggle(2);

}

  

 

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

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

void wr24c02a(char wordAddr, char *buffer,int len )

{

       int i;

   char mbuf[4];

   

   while(1) {

   i = rIICSTAT;

   if(i & (0x01<<5)){

      Uart_Send("bus busy",10);

      delay(100);

   } else

     break;

     }

   

       flag =1;                     //应答标志

       

       rIICDS = devAddr;

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

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

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

              delay(100);           //一旦进入IIC中断,即可跳出该死循环

       Uart_Send("a",1); 

   

       flag = 1;

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

       rIICCON &= ~0x10;

       while(flag)

              delay(100);

 

   Uart_Send("b",1);  

//连续写入数据

       for(i=0;i       {

              flag = 1;

              rIICDS = *(buffer+i);

              rIICCON &= ~0x10;

              while(flag)

                     delay(100);

  

  mbuf[0] = *(buffer + i);

  mbuf[1] = '.';

   Uart_Send(mbuf, 2);

       }

      

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

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

      

       delay(100);                   //等待

}

 

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

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

void rd24c02a(char wordAddr,char *buffer,int len )

{

       int i;

       unsigned char temp;

   char mbuf[12];

   

   while(1) {

   i = rIICSTAT;

   if(i & (0x01<<5)){

      Uart_Send("bus busy",10);

      delay(100);

   } else

     break;

     }

   

       flag =1;

       rIICDS = devAddr ;                     //

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

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

       while(flag)

[1] [2]
关键字:mini2440  裸机编程  IIC 引用地址:mini2440裸机编程-----IIC—读写AT24C08

上一篇:mini2440裸机编程--------LCD驱动
下一篇:mini2440上dm9000驱动分析(三)

推荐帖子

IPC-4552B-中文版-CN TOC印制板化学镀镍 浸金(ENIG)镀覆性能规范
IPC-4552B-中文版-CNTOC印制板化学镀镍浸金(ENIG)镀覆性能规范https://share.weiyun.com/aigOt6UzIPC-4552B-中文版-CNTOC印制板化学镀镍浸金(ENIG)镀覆性能规范
李强980702 EE_FPGA学习乐园
TL494的功能和检测方法
随着信息化的不断普及,微机已进入普通家庭和中小学校,随之而来的维修工作也越来越重。而微机中硬件故障率最高的是主机的电源,从维修中我发现弄清TL494的功能和各引脚的作用对维修电源致关重要,下面就介绍TL494的功能和各引脚的作,以及检测方法。TL494的功能和检测方法8错借用了请问一下这个文档里面对494的检测是直接给芯片上电,还是要焊接好外围保护电路。我焊接了里面的外围电路,但是还是测不出相应的波形,那么芯片是否坏了呢?谢谢分享,下载看看。
wxf1357 模拟与混合信号
【嵌入式驱动开发】linux的哪些事儿之USB的开发
最近在做DM368的USB的开发,也是刚接触USB驱动的开发,还不是很熟悉,同学给我推荐的,现在这一系列书分享给大家!想要了解USB的检测机制、构架的一定得看,是非常的有帮助,通俗易懂!=================================================其中我是U盘属于基础性的.这一阶段会遇到一些问题.比如urb提交之后究竟怎么处理的?用户空间究竟是如何访问U盘的?DMA究竟怎么回事.这之后可以开始看Hub.这一阶段你会明白一个usb
37°男人 Linux与安卓
temp6=(int)(Rain*10);这个语句有问题吗?
temp6=(int)(Rain*10);这个语句有问题吗?我的Rain是float类型的temp6=(int)(Rain*10);这个语句有问题吗?我的temp6会是确定的整型数吗?这个不是强制类型转换吗,应该是可以的。float型强制转换成int型。
小子不乖1229 编程基础
MSP430的特殊功能寄存器
MSP430的特殊功能寄存器共有哪些?地址分别是什么?当430进入低功耗模式,有中断唤醒后进入中断程序,为何最后加一句“__bic_SR_register_on_exit(CPUOFF);//ExitLPM0”就能退出低功耗模式呢?中断执行完后不是应该恢复原状态吗?附:#includemsp430g2553.hunsignedcharTXData;unsignedcharTXByteCtr;voidmain(void){WDTCTL=WDTPW
wlsdhw 单片机
请教各位,一般手机用的speaker 和 马达 功耗是多大 允许通过的电流是多少?
如题请教各位,一般手机用的speaker和马达功耗是多大允许通过的电流是多少?比较小,我用单片机的io口驱动过,估计最大在20ma左右。小弟最近找了一款小马达,手机上用的,量了一下基本上要30mA才有感觉不过这马达的最大电流也就80mA喇叭的还没有测过,最近没有条件测,回头测下看奇怪,我50分的帖子居然没有人回晕菜,把我不当人看?
hjwahjl 嵌入式系统
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved