ADI Blackfin DSP处理器-BF533的开发详解22:SD卡的设计和实现原理及应用(含源码)

news2025/1/11 14:48:32

硬件准备

ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器

软件准备

Visual DSP++软件

硬件链接

在这里插入图片描述

功能介绍

ADSP-EDU-BF53x 板卡上设计了一个 SD/MMC 接口,可以通过该接口实现对 SD/MMC 卡数据的访问。

SD 卡有两种工作模式:SDIO 模式和 SPI 模式。SDIO 模式为半字节读写模式,该模式采用四根数据线,每次可对半个字节作操作。SPI 模式有 4 根控制线:MOSI,MISO,SPICLK,SPISS.因为每次只能对一位数据作操作。

SD/MMC 卡的寻址方式是按字节寻址的,为方便使用,将其寻址方式定义成连续的存储单元寻址方式。每个存储单元为 512 个字节。每个存储单元地址唯一,通过访问存储单元地址来读取数据。

ADSP-EDU-BF533板卡上采用 PF2 实现对 SPI 设备的控制,由于板卡上有 SD 卡和触摸屏控制器两个 SPI 设备,所以通过 CPLD 将 PF2 接口做了个 2 选 1 切换,通过配置 CPLD 的 DEVICE_OE 寄存器,来使能和选通 PF2 连接哪一个 SPI 设备。

SD 卡插入后,不会触发中断信号,但可以通过中断数据寄存器读取其插入信息。

DEVICE_OE 寄存器(读/写):
DEVICE_OE 寄存器地址:0x20320000
DEVICE_OE 寄存器设置硬件设备上一些控制管脚的电平状态。

DEVICE_OE 寄存器位功能:

在这里插入图片描述

SPI_SEL1~0:SPI 片选选择位
00:SPI_SEL 选通触摸屏模块
01:SPI_SEL 选通 SD 卡模块
10:SPI_SEL 选通外部 SPI0 模块
11:SPI_SEL 选通外部 SPI1 模块

在使用 SD/MMC 卡接口时时,需将 SPI_SEL0 位设置为 1,将 SPI_SEL1 位设置为 0。

硬件连接示意图

在这里插入图片描述

代码实现功能

代码实现了对 SD/MMC 卡扇区的写入和读取,并将读出的数据与写入的数据做比较,并打印比较结果。

测试步骤

1. 将仿真器(ICE)与 ADSP-EDU-BF53x 开发板和计算机连接好。
2. 将 SD 或 MMC 卡插入 SD 卡接口。
3. 先给 ADSP-EDU-BF53x 开发板上电,再为仿真器(ICE)上电。
4. 运行 VisualDSP++ 5.0 软件,选择合适的 BF533 的 session 将仿真器与软件连接。
5. 加载 VisualDSP++ 5.0 工程文件 BF53x_SD_MMC.dpj,编译并全速运行。

测试结果

在 VisualDSP++ 软件上打印校验数据的结果。

在这里插入图片描述

SD/MMC 卡校验完成

在这里插入图片描述

写入的数据和读出的数据内存比较。

程序源码

CPU.C

#include <cdefBF533.h>

void Init_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}

void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc07bb0;
*pEBIU_AMGCTL = 0x000f;
}

void Set_PLL(int pmsel,int pssel)
{
int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}

SD_mmc.c

#include <cdefBF533.h>
#include “sd_mmc.h”

void MMC_HardwareInitial(void)
{
*pSPI_FLG = FLS2;
*pSPI_BAUD = 550;
*pSPI_CTL = 0x0000;
*pSPI_CTL = 0x0001 | MSTR ;
*pSPI_CTL = (*pSPI_CTL | SPE);
}

/****************************************************************************

  • 名称 : SPI_TransferByte

  • 功能 : 将数据value发出

  • 入口参数 :value

  • 出口参数 :无
    ****************************************************************************/
    unsigned char SPI_TransferByte(unsigned char value)
    {
    unsigned char incoming=0;
    while((*pSPI_STAT & TXS));
    *pSPI_TDBR = value;

    while(*pSPI_STAT & RXS)
    incoming = *pSPI_RDBR;

    return(incoming);
    }
    /****************************************************************************

  • 名称 : MMC_Init

  • 功能 : 初始化MMC Card

  • 入口参数 :无

  • 出口参数 :无
    ****************************************************************************/
    void MMC_Init(void)
    {
    unsigned char retry,temp;
    unsigned char i;
    unsigned char r1;

tryagain:
for (i=0;i<10;i++)
{
SPI_TransferByte(0xff); //send 74 clock at least!!!
}

SPI_TransferByte(MMC_RESET);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x95);
SPI_TransferByte(0xff);
SPI_TransferByte(0xff);

retry=0;
do{
	
	temp=Write_Command_MMC(MMC_INIT,0);
    retry++;
	if(retry==100)
    {
		printf("SD/MMC_INIT is ERROR!\n "); 
		goto tryagain;     
    }
}while(temp!=0);
printf("SD/MMC_INIT is OK!\n");

}

/****************************************************************************

  • 名称 : Write_Command_MMC

  • 功能 : 向MCC卡写命令 ,将命令字cmd送入地址address,返回状态值tmp

  • 入口参数 :cmd,address

  • 出口参数 :tmp
    ****************************************************************************/
    unsigned char Write_Command_MMC(unsigned int cmd, unsigned int address)
    {
    unsigned char tmp;
    unsigned char retry=0;

    SPI_TransferByte(cmd);
    SPI_TransferByte(address>>24);
    SPI_TransferByte(address>>16);
    SPI_TransferByte(address>>8);
    SPI_TransferByte(address);
    SPI_TransferByte(0xFF);

    do{
    tmp = SPI_TransferByte(0xFF);
    retry++;
    }while((tmp==0xff)&&(retry<8));

    return(tmp);
    }

/*********************************************************************************

  • 名称 : Write_Command_MMCCRC

  • 功能 : 向MCC卡写命令 ,将命令字cmd送入地址address,和crc,返回状态值tmp

  • 入口参数 :cmd,address, crc

  • 出口参数 :tmp
    **********************************************************************************/
    unsigned char Write_Command_MMCCRC(unsigned int cmd, unsigned int address,unsigned char crc)
    {
    unsigned char tmp;
    unsigned char retry=0;
    SPI_TransferByte(0xFF);

    SPI_TransferByte(cmd);
    SPI_TransferByte(address>>24);
    SPI_TransferByte(address>>16);
    SPI_TransferByte(address>>8);
    SPI_TransferByte(address);
    SPI_TransferByte(crc);

    do{
    tmp = SPI_TransferByte(0xFF);
    retry++;
    }while((tmp==0xff)&&(retry<0xfe));

    SPI_TransferByte(0xFF);

    return(tmp);
    }

/*********************************************************************************

  • 名称 : Write_Command_MMCCRC_NoDeassert

  • 功能 : 向MCC卡写命令 ,将命令字cmd送入地址address,和crc,返回状态值tmp

  • 入口参数 :cmd,address, crc

  • 出口参数 :tmp
    **********************************************************************************/
    unsigned char Write_Command_MMCCRC_NoDeassert(unsigned int cmd, unsigned int address,unsigned char crc)
    {
    unsigned char tmp;
    unsigned char retry=0;
    SPI_TransferByte(0xFF);

    SPI_TransferByte(cmd);
    SPI_TransferByte(address>>24);
    SPI_TransferByte(address>>16);
    SPI_TransferByte(address>>8);
    SPI_TransferByte(address);
    SPI_TransferByte(crc);

    do{
    tmp = SPI_TransferByte(0xFF);
    retry++;
    }while((tmp==0xff)&&(retry<0xfe));

    return(tmp);
    }

/****************************************************************************

  • 名称 : MMC_read_sector

  • 功能 : 读取MMC卡扇区数据,指定要读的扇区号和将数据传入的buff地址

  • 入口参数 :addrBuffer

  • 出口参数 :1
    ****************************************************************************/
    unsigned char MMC_read_sector(unsigned int addr,unsigned char *Buffer)
    {
    unsigned char temp;
    unsigned int i;

    SPI_TransferByte(0xff);
    temp = Write_Command_MMC(MMC_READ_BLOCK,addr<<9);
    if(temp != 0x00)
    {
    return(READ_BLOCK_ERROR);
    }

    while(SPI_TransferByte(0xff) != 0xfe);

    for(i=0;i<512;i++)
    {
    *Buffer++ = SPI_TransferByte(0xff);
    }
    SPI_TransferByte(0xff);
    SPI_TransferByte(0xff);

    return (1);
    }
    /****************************************************************************

  • 名称 : MMC_Write_sector

  • 功能 : 写MMC卡扇区,将BUF的数据写入扇区号sector

  • 入口参数 :sector,buf

  • 出口参数 :0
    ****************************************************************************/
    unsigned char MMC_Write_sector(unsigned int sector, unsigned char *buf)
    {
    unsigned char *p, by;
    unsigned int i,flag;
    unsigned int startadr;

    p = buf;
    startadr = sector*(unsigned int)BYTE_PER_SEC;
    Write_Command_MMC (MMC_WRITE_BLOCK,startadr);

    SPI_TransferByte(0xFF);
    SPI_TransferByte(0xFF);
    SPI_TransferByte(0xFE);
    for(i=0; i<BYTE_PER_SEC; i++)
    {
    SPI_TransferByte(*p++);
    }
    SPI_TransferByte(0xFF);
    SPI_TransferByte(0xFF);
    do
    {
    flag = SPI_TransferByte(0xFF);
    by=flag & 0x1F;
    }while(by != 0x05);

    do
    {
    flag = SPI_TransferByte(0xFF);
    }while(flag !=0xFF);

    return 0;
    }

main.c

#include <cdefBF533.h>
#include “sd_mmc.h”

unsigned char buff_w[512];
unsigned char buff_r[512];

/****************************************************************************

  • 名称 : check_test

  • 功能 : 校验写入数据的正确性,将写入的数据读出比较

  • 入口参数 :无

  • 出口参数 :无
    ****************************************************************************/
    void check_test(void)
    {
    int i;

    for(i=0;i<512;i++)
    buff_w[i] = i;

    MMC_Write_sector(1000,buff_w);
    MMC_read_sector(1000,buff_r);

    for(i=0;i<512;i++)
    {
    if(buff_w[i] != buff_r[i])
    {
    printf(“SD/MMC TEST ERROR!\n”);
    break;
    }
    }
    printf(“SD/MMC TEST OK!\n”);

}

int main()
{
Set_PLL(16,4);
Init_EBIU();
SD_Enable();

MMC_HardwareInitial();
MMC_Init();
check_test();
printf("SD/MMC Check END!\r\n");
while(1);		

}

我在程序里尽量写了一些我认为有必要的注释,还有看不明白的可以问我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/76501.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#使用 Async 和 Await 的异步编程

总目录 文章目录总目录前言一、概述二、命名规范三、await/async的作用四、基本使用五、使用Async和Await实现多任务顺序执行且不阻塞1.同步执行2.并行执行3.并行且可指定顺序执行总结前言 C# 中的 Async 和 Await 关键字是异步编程的核心。 通过这两个关键字&#xff0c;可以…

spring依赖查找、依赖注入深入学习及源码分析

文章目录一、依赖查找1、单一类型依赖查找&#xff08;接口 - BeanFactory&#xff09;根据Bean名称查找根据Bean类型实时查找根据Bean类型延迟查找&#xff08;Spring 5.1&#xff09;根据Bean名称类型查找2、集合类型依赖查找&#xff08;接口 - ListableBeanFactory&#xf…

Metal每日分享,颜色转换滤镜效果

本案例的目的是理解如何用Metal实现像素颜色转换滤镜&#xff0c;通过对像素颜色的不同读取方式获取到相应像素颜色&#xff0c;灰度图移除场景中除了黑白灰以外所有的颜色&#xff0c;让整个图像灰度化&#xff1b; Demo HarbethDemo地址 实操代码 // 转成灰度图滤镜 let f…

js深拷贝浅拷贝与lodash

title: js深拷贝浅拷贝与lodash date: 2022/9/27 14:46:25 categories: lodashjs入门 深拷贝和浅拷贝 ref&#xff1a;JS传递参数时的内部存储逻辑 JS 變數傳遞探討&#xff1a;pass by value 、 pass by reference 還是 pass by sharing&#xff1f; 在这个问题前&#xff…

LeetCode HOT 100 —— 169.多数元素

题目 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 思路 方法一&#xff1a;哈希表 遍历整个数组&#xff0c;记录每个数值出…

JAVA IO详解

目录 一、流的概念与作用 二、Java IO的用途和特征 三、流的使用详解 一、流的概念与作用 流(Stream)&#xff1a; 在Java IO中&#xff0c;流是一个核心的概念。流从概念上来说是一个连续的数据传输过程。人们根据数据传输特性将流抽象为各种类&#xff0c;方便更直观的进…

【服务器数据恢复】服务器raid5崩溃导致上层应用不可用的数据恢复案例

服务器数据故障&#xff1a; 某公司服务器8块硬盘组成raid5磁盘阵列&#xff0c;其中有2块硬盘故障指示灯报警&#xff0c;其他硬盘指示灯正常&#xff0c;上层应用不可用。 服务器数据恢复过程&#xff1a; 1、服务器数据恢复工程师拿到故障服务器所有硬盘后对出现物理故障的…

ADI Blackfin DSP处理器-BF533的开发详解18:用触摸屏的例程来理解中断(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 硬件实现原理 ADSP-EDU-BF533 开发板上的中断资源连接到了 CPLD&#xff0c;并通过 CPLD 将中断信号连接到 PF0 触发&#xff0c;通过 CPLD映射的…

ubuntu交叉编译(armv7_32位)onnx源码_cpu版本

1 下载onnx git clone https://github.com/microsoft/onnxruntime cd onnxruntime git submodule update --init --recursive2 编译 由于是交叉编译&#xff0c;所以需要设置一下编译工具&#xff0c;在网上搜索看到了这个 chineseocr_lite/build-onnxruntime-android.sh a…

Jmeter(一):jmeter概述与工作原理,安装与基本配置介绍

Jmeter(1)&#xff1a;jmeter概述与工作原理 jmeter概述与工作原理 JMeter 是 Apache 基金会 Jakarta 上的一个纯 Java 开源项目&#xff0c;起初用于基 于 Web 的压力测试&#xff08;pressure test&#xff09;&#xff0c;后来其应用范围逐渐扩展到对文件传输 FTP, 大型数据…

基于JavaWeb+JSP的校园二手交易平台(源码+数据库+说明文档)

目录 一、前后端功能模块 1.用户web前端页面功能模块 2.后台信息管理模块 二、开发环境 三、开发技术 四、页面设计 1.登录注册界面 2.网页主页界面 3.商品列表界面 4.商品详情界面 5.支付页面 6.支付成功后页面 7.我的订单页面 ​8.个人已发布与待处理订单界面…

google外链重要性高吗?谷歌外链作用大不大

google外链重要性高吗&#xff1f; 答案是&#xff1a;非常重要&#xff0c;而且要注重建设付费GPB外链。 要相信有价值的外链一般都比较难获取&#xff0c;那种高流量的外链一般要靠自己去outreach, 但是成功率比较低&#xff0c;我们需要用金钱和优质外链资源去交换 做高质…

程序员的浪费,Python一对一还原《点燃我,温暖你》里面比较火的那个爱心代码 | 附源码

前言 包子们&#xff0c;上午好 最近有个剧挺火的 就是那个程序员的剧&#xff0c;叫《点燃我&#xff0c;温暖你》 最近听说很火呀&#xff0c;那作为程序员&#xff0c;Python中的战斗机的小编&#xff0c;能不给大家安排一波&#xff01; 怎么说呢&#xff0c;用这个表白也…

我凭借这 1000 道 java 真题,顺利拿下京东、饿了么、阿里大厂 offer

今天这篇文章也算是一次面试总结了吧&#xff01; 毕竟金九银十过去了&#xff0c;总得给大家来点东西交代交代&#xff01; 所以今天&#xff0c;这篇文章就应运而生了&#xff0c;给大家来点正正经经的干货教学&#xff0c;让大家体验一下干货的魅力&#xff01; 小编今天这里…

【C语言数据结构(基础篇)】第一站:时间复杂度与空间复杂度

目录 一、什么是时间复杂度和空间复杂度 1.算法效率 2.时间复杂度的概念 3.空间复杂度的概念 二、如何计算常见的时间复杂度 1.大O的渐进表示法 2.一些时间复杂度的例子 &#xff08;1&#xff09;例1 &#xff08;2&#xff09;例2 (3)例3 (4)例4 &#xff08;5&a…

【计算机视觉+自动驾驶】二、多任务深度学习网络并联式、级联式构建详细讲解(图像解释 超详细必看)

觉得有帮助麻烦点赞关注收藏~~~ 一、多任务网络的主要分类 目前建立的多任务网络可以分为两种方法&#xff0c;一种为并联多任务网络结构&#xff0c;另一种为级联多任务网络结构&#xff0c;两种网络构建方式分别如下图所示 并联式 级联式 并联网络结构大多为共享基础网络而…

ADI Blackfin DSP处理器-BF533的开发详解14:LED跑马灯(含源代码)

接口讲完了&#xff0c;下面写点应用程序&#xff0c;GPIO最典型的应用&#xff0c;LED跑马灯。 硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 *硬件实现原理 ADSP-EDU-BF533开发板上共设计了…

2005-2020年全国31省劳动力市场分割指数

2005-2020年全国31省劳动力市场分割指数 1、时间&#xff1a;2005-2020年 2、范围&#xff1a;包括全国31省&#xff0c; 3、数据内容&#xff1a;数据存在缺失&#xff0c;下载链接界面有数据预览&#xff0c;具体缺失情况参看链接内数据预览&#xff0c; 内含原始数据、A…

把废旧监控改无人机遥控车红外远程摄像头

像我们这些精打细算的业余玩家&#xff0c;淘个新宝贝都要掂量掂量。很羡慕能买到专用红外摄像头配无人机。可是手头不宽裕&#xff0c;只有一些旧零件。这都是废物再利用&#xff0c;所以说不要太追求性能了&#xff0c;自然让他工作就好&#xff0c;测试这条路线的可行性。 …

blneder 蜡笔

文章目录简介.打开蜡笔.基本操作.自由线.图形工具.图层.遮罩.画布.画布原点.![在这里插入图片描述](https://img-blog.csdnimg.cn/46cb7019e8ff41e6b391e056c616ce32.png)画布旋转.辅助.圆形.径向.平行.栅格.等距.编辑模式.顶部工具栏.选择.曲线编辑.左侧工具栏.快捷键.画笔深度…