刚才研究了CF卡的操作,取得一些成果,不敢独享,拿出来和大家交流一下
首先show出我的实验板(ATmega8515):http://cache.amobbs.com/bbs_upload782111/files_1/armok0137122.jpg
下面给出我的CF卡连接原理图:
http://cache.amobbs.com/bbs_upload782111/files_1/armok0137123.JPG
其中信号CFCEn是由一片74VHCT138选出的,在我的实验板中,选中的地址是8000-8FFF。
下面两个是我研究时参考的文档,其中一个是CF卡官方Datasheet,一个是TrueIDE方式访问CF卡的应用文档:
点击此处打开armok0137124.pdf
点击此处打开armok0137125.pdf
然后是具体操作过程(这里使用了我自编的COM Monitor和AVR程序,利用类似Debug的命令在PC端进行调试):
http://cache.amobbs.com/bbs_upload782111/files_1/armok0137127.JPG
sre 1 : 表示使用外部SRAM
wr 8100 01 : 把0x01写到地址0x8100,按照上面的原理图连接的话,地址0x8100是CF卡的Feature Register(特性寄存器),写0x01表示使用8位方式传输数据,具体见Datasheet
wr 8700 ef : 地址0x8700写入时表示命令寄存器,命令0xef功能是设置CF卡的Feature,具体见Datasheet
rd 8100 : 读取地址0x8100,地址0x8100在读取时为错误代码寄存器,如果读得0表示命令成功
wr 8200 01 : 地址0x8200表示每次操作的扇区数目,在这里,每次操作一个扇区
wr 8300 01 : 地址0x8300表示扇区号,这里我访问的是1号扇区
wr 8400 10 : 地址0x8400为柱面号低位,这里我访问的是16号柱面(0x10)
wr 8500 00 : 柱面号高位
wr 8600 a0 : 地址0x8600低4位为磁头号,这里我访问0号磁头,高4位用来表示驱动器特性,这里高4位为1010表示CF卡是主盘(Master),采用磁头/柱面/扇区方式访问(除此以外可以选择LBA方式访问),具体见Datasheet
wr 8700 20 : 执行指令0x20,即读扇区指令
rd 8100 : 读错误代码寄存器
rd 8700 : 地址0x8700在读取时为状态寄存器,这里读得58表示CF卡已经Ready,且需要Data Request,具体见Datasheet
设置好访问的位置和指令后,就可以访问数据寄存器0x8000来获得数据了。这里读取0x8000-0x80ff的数据,就是扇区的前256字节(其实访问0x8000-0x80ff就是访问256次0x8000,理解了原理图的话就会知道)。
http://cache.amobbs.com/bbs_upload782111/files_1/armok0137128.JPG
然后再来一次读取0x8000-0x80ff,得到扇区的后256字节。整个扇区全部读出。
http://cache.amobbs.com/bbs_upload782111/files_1/armok0137129.JPG 板子很美丽,调试工具不配对。 自编的COM Monitor和AVR程序能给大家学习一下吗? 楼主能不能介绍一下,TrueIDE方式访问有什么特点? 以我的理解,TrueIDE方式的好处是不需要373之类的锁存器,只需单片机的数据线和地址线直接连接即可,只有3条地址线,对应CF卡8个地址,10个寄存器。而I/O模式和Common Memory模式用起来自由度大一些,但访问寄存器的同时,还需要较多的地址线,需要锁存器辅助。
TrueIDE方式操作是以扇区为最小单位,每次至少操作一个扇区。如果需要读取具体到某个扇区中的第n个字节,而又不想使用一个512字节的数组的话,可以这样操作:先空读n-1次数据寄存器0x8000,再把数据寄存器0x8000的值取出到你的变量。但是写入操作的话就只能整个扇区写入,不能具体到字节。
那个COMMonitor是我自编自用的,所以界面比较差,请hotpower推荐一个较好用的调试工具。那个AVR程序现在只有rd、wr、lst三个功能,等我完善后再拿出来。 咦,qwernet 小俊 好像没有申请我们的MP3 芯片样片?
有兴趣吗? 如果有的话,发一下邮件给我: 13902245677@21cn.com 附上你的地址,我这两天就能用平邮寄给你。 谢谢armok的好意!
不过我之前已经买了一片STA013并在TI申请到了音频DAC(内置放大器),我就不浪费你的资源了(早知这样我就不买了,花了42元,呜呜呜~~~~~) 预祝大家这次的MP3制作活动能完满成功! 呵呵,42元一片 STA013 ? 真的超贵呢。 "等我完善后再拿出来",太好了。等待ING 小俊
看了你的程序啊
先谢谢了
不过里面有两个函数看不懂
是inb()
和outb()
你还有它们的源代码啊 inb()和outb()是在sfr_defs.h里面定义的宏,你可以打开这个头文件看看是怎么定义的。
这两个的作用分别是从某个地址读取1个字节和把1个字节写到某个地址。
类似的还有inw()和outw(),这两个是读、写1个字(2字节)。 xiexie
我用的是icc,没找到这个头文件啊
你是不是用winavr啊,还能把那两个函数的代码发给我啊,
谢谢了
我的邮箱
wq3116@vip.sina.com
-----此内容被wowo于2005-02-22,13:06:33编辑过
-----此内容被wowo于2005-02-22,13:09:24编辑过 你用*(volatile unsigned char *)(地址)来访问也可以啊。读的时候就读这个值,写的时候对它赋值就可以了。 因为在这个工作模式下,cf卡象是扩充的ram,我以前没用过外扩ram,所以我想看一下源代码
看看时序是这样的
新手
没办法的
好多东西不懂 请问
小俊
你程序中有用到几个连续的outb()
我想问一下,通过什么来判断前一个写寄存器或读寄存器操作已经完成 你所指的几个连续的outb()是不是指设置寄存器的那几个?那是不需要判断是否完成的,因为写入时WRn引脚拉低后再升高,就完成的一次写入过程,这跟写外部SRAM是一样的,只要写入时序符合要求,写入就能成功。 是不是这样的啊
如果我要写8600
地址线上先输出8600
然后wr拉低
数据线上写要写的东西
然后wr拉高
就完成了啊 实际过程是这样,但不需要自己完成。你直接向0x8600读写就可以了。至于地址、数据的输出、读、写电平是由avr的外部存储器接口控制的。可以参考一下Datasheet里面的时序图。 谢谢 小俊
还能把cf卡的封装发给我啊
还有电源插孔的
那个d12还容易买啊
我想先把它画到板子上 小俊
能不能把你的CF卡的“元件库”发给我一份呀?我有点懒的画了,谢谢你
我的邮箱:e_leeman@yahoo.com.cn
如果你愿意,建议直接发到论坛里,相信不少人需要这东东,谢谢:P
-----此内容被e_leeman于2005-10-25,22:51:03编辑过 谢谢!参考一下 好像现在做CF卡的人很少了,求助一下,我用51扩展RAM来做,但是没成功。请各位帮忙看一下我的图有没有问题呀?然后就是各个寄存器的地址怎么算呀?
http://cache.amobbs.com/bbs_upload782111/files_8/armok01173358.jpg 仅从图中可以看出,假设SDCE和CE都是低电平有效,无关位用0表示。
6116的地址范围是:0x4000~0x47ff;P2.7=0;P2.6=1;
CF CARD的地址范围是:0x8000~0x8007;P2.7=1;P2.6=0; 谢谢tiker 田开坤的关注,我现在测试6116能正常工作了,但是CF卡一直不能就绪。程序如下:
//CF.h
#include <reg51.h>
#include <absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define DATA_REG XBYTE
#define Features XBYTE
#define SEC_COUNT_REG XBYTE
#define SEC_NUM_REG XBYTE
#define CYL_LOW_REG XBYTE
#define CYL_HI_REG XBYTE
#define DRV_HD_REG XBYTE
#define STATUS_REG XBYTE
#define COMMAND_REG XBYTE
#define SECTOR 512
void CF_Read(ulong sector,uchar *buffer);
void CF_Write(ulong sector,uchar *buffer);
//读写子程序
#include <CF.h>
void CF_Write(ulong sector,uchar*cfbuf_add)
{
uint i=0 ;
uchar temp=0 ;
if((STATUS_REG&0x02)!=0x02)
{
while((STATUS_REG&0xf0)!=0x50)
P1=STATUS_REG ; //不知道为什么一到这里就停住了
//CF等待就绪
}
SEC_COUNT_REG=0x01 ;
//写的扇区数为1
SEC_NUM_REG=(sector&0xff);
//要求读写的扇区低字节
CYL_LOW_REG=((sector&0xffff)>>8);
//要求读写的扇区中间字节
CYL_HI_REG=(sector>>16);
//要求读写的扇区高字节
DRV_HD_REG=0xe0 ;
//选择LBA模式
COMMAND_REG=0x30 ;
//命令字,写扇区
if((STATUS_REG&0x02)!=0x02)
{
while((STATUS_REG&0xf8)!=0x58)
P1=STATUS_REG ;
//CF请求发送数据
}
//写一个扇区512字节
for(i=0;i<SECTOR;i++)
{
temp=cfbuf_add;
DATA_REG=temp ;
}
}
void CF_Read(ulong sector,uchar*cfbuf_add)
{
uint i=0 ;
uchar temp ;
if((STATUS_REG&0x02)!=0x02)
{
while((STATUS_REG&0xf0)!=0x50)
P1=STATUS_REG ;
}
SEC_COUNT_REG=0x01 ;
SEC_NUM_REG=(sector&0xff);
CYL_LOW_REG=((sector&0xffff)>>8);
CYL_HI_REG=(sector>>16);
DRV_HD_REG=0xe0 ;
COMMAND_REG=0x20 ;
if((STATUS_REG&0x02)!=0x02)
{
while((STATUS_REG&0xf8)!=0x58)
P1=STATUS_REG ;
}
for(i=0;i<SECTOR;i++)
{
temp=DATA_REG ;
*cfbuf_add=temp ;
cfbuf_add++;
}
}
//CF测试
#include <CF.h>
uchar code Dat="0123456789abcdefghijklmnopqrstuvwxyz";
uchar xdata buf _at_ 0x4010;
void Delay(uint n)
{
uchar i,j;
for(;n;n--)
for(i=0;i<50;i++)
for(j=0;j<124;j++)
;
}
void main(void)
{
uint i;
Delay(10);
CF_Write(0x0040,Dat);
//P1=0xF0;
CF_Read(0x0040,buf);
while(1)
{
for(i=0;i<SECTOR;i++)
{
P1=buf;
Delay(30);
}
}
}
请各位看一下问题出在哪里,谢谢! 谢谢!收藏! 嗯~真的还不错啊,过两天休息,我一定买东西做一下 值得学习啊!! 学习 mark 一下 MARK mark mark 先收藏,谢谢! 记号~~ mark!! 卡号多啊,SD,CF。。。 楼主,装CF卡的器件一般叫什么名字,封装呢,有无现成的?(前天下了一个,不知如何?) 小俊强人!
收藏! MARK mark GOOD mark 先mark一个 ,学习一下。 mark,先留着
页:
[1]