多语言展示
当前在线:716今日阅读:60今日分享:41

基于STM32的SD读卡器的制作

SD读卡器就是读取sd存储卡的设备。目前在市面上最常见的存储卡SD Memory(SD卡)。该存储卡现在被广泛应用于数码相机、DV、MP4、MP3随身听、PDA掌上电脑、多媒体手机。为了便于使存储卡所携带资料能够被更多人使用,读卡器随之产生。  SD 卡( Secure Digital Memory Card)中文翻译为安全数码卡,它是在 MMC 的基础上发展而来, 是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD 卡由日本松下、东芝及美国 SanDisk公司于 1999 年 8 月共同开发研制。大小犹如一张邮票的 SD 记忆卡,重量只有 2 克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。 按容量分类,可以将SD 卡分为 3 类: SD 卡、 SDHC 卡、 SDXC 卡。SD卡一般支持两种操作模式:1.SD卡模式(通过SDIO通信)2.SPI模式SD 卡的引脚排序如下今天 就来教大家如何用STM32f103zet6自己制作一个读卡器。
工具/原料

STM32f103zet6 最好是开发板 要是能自己焊接也可以 keil usb数据线

方法/步骤
1

SD卡接口的硬件设计    STM32F103xx增强型系列生产的基于Cortex-M3的高性能的32位RISC内核,工作频率为72 MHz,内置高速存储器(128 KB的闪存和20 KB的SRAM),以及丰富的增强I/O端口和连接到2条APB总线的外设。STM32F103xx系列工作于-40~+105℃的温度范围,供电电压为2.0~3.6 V,与SD卡工作电压兼容,一系列的省电模式可满足低功耗应用的要求。 SD卡支持SD模式和SPI模式两种通信方式。采用SPI模式时,占用较少的I/O资源。STM32F103VB包含串行外设SPI接口,可方便地与SD卡进行连接。通过4条信号线即可完成数据的传输,分别是时钟SCLK、主机输入从机输出MISO、主机输出从机输入MOSI和片选CS。SD 卡有 5 个寄存器,如下:

2

SD卡的最高数据读写速度为10 MB/s,接口电压为2.7~3.6 V,具有9个引脚。SD卡使用卡座代替传输电缆,减少了环境干扰,降低了出错率,而且1对1传输没有共享信道的问题。SD卡在SPI模式下各引脚的定义如表1所列。

3

对STM32F103的SPI_CRl(SPI控制寄存器)以及SPI_SR(SPI状态寄存器)进行初始化设置,使能SPI并使用主机模式;同时设置好时钟,在时钟上升沿锁存数据。SPI通道传输的基本单位是字节,由STM32F103VB控制其和SD卡之间的所有通信。要读写SD卡,首先要对其进行初始化。初始化成功后,即可通过发送相应的读写命令对SD卡进行读写。这里是流程 按照流程编程。当然 也会发程序的。

4

程序部分我会发附件 在这里就来看主函数:在主函数的程序里设置了SD卡的容量,因为超过4G的话 就要用u32来表示 因为4G是4194304字节,u32是4294967296,大于4G,所以用u32来表示SD卡的容量,这这次制作中用到EN25Q64,是一个64兆位(8192k字节)串行闪存,具有先进写防保护机制,支持标准串行外围接口(SPI)和一个高性能双输出和I/O口:  在使用SPI接口的时候: 串行时钟,片选,串行DQ 0(DI),DQ1(DO),DQ 2(WP#)和DQ 3(NC)高达80MHzSPI时钟频率被支持,允许为160MHz双输出,当使用双输出快速阅读说明相当于时钟频率,和高达50MHzSPI时钟频率被支持,允许为200MHz等效时钟速率采用四路输出快速读取指令时,四路输出。该内存可以被编程为1〜256个字节时间,使用页面编程指令。该EN25Q64被设计为允许任何单扇区/块在同一时间或整片擦除操作。该EN25Q64可以被配置为防护护存储器作为软件防护护模式一部分。装置能够维持最低100K编程/擦除每一个扇区周期或块  对于EN25Q64的初始化void EN25QXX_Init(){ GPIO_InitTypeDef  GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOG|RCC_APB2Periph_GPIOF, ENABLE); /* FLASH_CS PG13 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化 GPIO_SetBits(GPIOG,GPIO_Pin_13); /* SD_CS PG14 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化 GPIO_SetBits(GPIOG,GPIO_Pin_14); /* ENC28J60_CS PB12 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 GPIO_SetBits(GPIOB, GPIO_Pin_12);  /* NRF24L01_CS PF9 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//PF7 GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO_SetBits(GPIOF,GPIO_Pin_9);//PF9输出1,防止NRF干扰SPI FLASH的通信 EN25QXX_CS=1; //SPI FLASH不选中 SPI2_Init();   //初始化SPI EN25QXX_TYPE=EN25QXX_ReadID(); //读取FLASH ID}

6

这一是对SRAM的初始化要的是接的引脚 void FSMC_SRAM_Init(void){ GPIO_InitTypeDef  GPIO_InitStructure; FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef  FSMC_ReadWriteNORSRAMTiming;  //PD,PE-FSMC_DATA  PF,PG-FSMC_A RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE                        | RCC_APB2Periph_GPIOF|RCC_APB2Periph_GPIOG, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10;  //FSMC_NE3 PG10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOG, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1;  //FSMC_NBL0-1 PE0 PE1 GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4|GPIO_Pin_5;  //FSMC_NOE,FSMC_NWE PD4 PD5 GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8    | GPIO_Pin_9 | GPIO_Pin_10 |GPIO_Pin_11  | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14  | GPIO_Pin_15 ); GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9                               | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12   | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15); GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2    | GPIO_Pin_3 | GPIO_Pin_4 |GPIO_Pin_5  | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14  | GPIO_Pin_15 ); GPIO_Init(GPIOF, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2    | GPIO_Pin_3 | GPIO_Pin_4 |GPIO_Pin_5); GPIO_Init(GPIOG, &GPIO_InitStructure);       FSMC_ReadWriteNORSRAMTiming.FSMC_AddressSetupTime = 0x00; //地址建立时间(ADDSET)为1个HCLK  FSMC_ReadWriteNORSRAMTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间(ADDHLD)模式A未用到 FSMC_ReadWriteNORSRAMTiming.FSMC_DataSetupTime = 0x08; ////数据保持时间(DATAST)为9个HCLK   FSMC_ReadWriteNORSRAMTiming.FSMC_BusTurnAroundDuration = 0x00; FSMC_ReadWriteNORSRAMTiming.FSMC_CLKDivision = 0x00; FSMC_ReadWriteNORSRAMTiming.FSMC_DataLatency = 0x00; FSMC_ReadWriteNORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A      FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;//  这里我们使用NE3 ,也就对应BTCR[4],[5]。 FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;  FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM;  //SRAM    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit   FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable;  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable; FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;   FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; //存储器写使能  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;   FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; // 读写使用相同的时序 FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;   FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_ReadWriteNORSRAMTiming; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_ReadWriteNORSRAMTiming; //读写同样时序 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  //初始化FSMC配置  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);  // 使能BANK1区域3   }

7

因为用到SPI(串行外围接口),所以要对SPI进行初始化void SPI1_Init(void){ GPIO_InitTypeDef  GPIO_InitStructure; SPI_InitTypeDef  SPI_InitStructure; /* SPI的IO口和SPI外设打开时钟 */    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); /* SPI的IO口设置 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(SPI1, ENABLE); //使能SPI外设 SPI1_ReadWriteByte(0xff);//启动传输 }程序可以直接复制 但是在用的时候请看好引脚

8

在这里当将程序download到开发板或者是自己做的系统上时,有可能需要将开发板复位,然后才会download到开发板上,然后可以将数据线插到usb口,将另一头插到电脑上,然后就能看见电脑上多了一个硬盘。

9

用到的彩屏是用来看读取信息的,当然也可以用串口调试助手,将读取的信息放到串口调试助手上看,这里讲如何用J-LINKdownload程序到开发板。  然后在FLASH Download 将Reset and Run用上就可以了

注意事项
1

看程序的时候 要看引脚

2

就是有可能需要复位开发板才能工作

推荐信息