开始弄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)
上一篇: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 嵌入式系统
设计资源 培训 开发板 精华推荐
- JasonFly_pad
- 【征集令】语音车库门控制系统
- LT3089IR 高效可调电源的典型应用电路
- DC1332B-B,用于 LTC2631ACTS8-LZ12 的演示板,12 位 I2C DAC(2.5V 参考,复位至零电平)
- 基于ESP32的多功能LED时钟
- LTC3388 的典型应用 - 20V 高效率纳米功率降压型稳压器
- 南通大学地图
- 使用 ROHM Semiconductor 的 BU4912 的参考设计
- 使用内部软启动的典型应用电路,VIN = 12 V,VOUT = 1.8 V,IOUT = 4 A,fSW = 600 kHz,适用于 ADP2384 20V、4A、同步降压直流至直流稳压器
- LT1764EQ-1.5 3.3 VIN 至 2.5 VOUT LDO 稳压器的典型应用