OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 34|回复: 0

《STM32H7R7开发指南 V1.1 》第五十二章 SD NAND实验

[复制链接]

1339

主题

1355

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
5719
金钱
5719
注册时间
2019-5-8
在线时间
1548 小时
发表于 7 小时前 | 显示全部楼层 |阅读模式
第五十二章 SD NAND实验

1)实验平台:正点原子STM32H7R7开发板

2)章节摘自【正点原子】STM32H7R7开发指南 V1.1

3)购买链接: https://detail.tmall.com/item.htm?id=820823382459

4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/stm32/zdyz_stm32h7rx.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子STM32开发板技术交流群:756580169


2.jpg

3.png

在单片机系统中,大部分人喜欢用SD卡来存储数据,因为它小巧便携,简单易用,但是用SD卡存在不能机贴、容易脱落、占用PCB面积大的问题。本章介绍的SD NAND可以很好的解决SD卡的缺点,它的使用和SD卡基本一致,被称为是贴片式SD卡。SD NAND具有使用寿命长、性能稳定等优势。
STM32H7R7开发板板载了SD NAND芯片,板载的SD NAND根据不同版本的核心板分为容量为4Gb的MKDV4GCL和容量为16Gb的MKDV16GIL,这两款不同型号的SD NAND除了容量大小不同之外,其他参数和特性基本一致,均使用SPI接口驱动、4位模式,最高通信速度可达50MHz,对于一般应用是足够的。在本章,我们将以MKDV4GCL为例,向大家介绍如何在开发板上实现SD NAND的读取。
本章分为如下几个部分:
52.1 SD NAND简介
52.2 SPI寄存器
52.3 硬件设计
52.4 程序设计
52.5 下载验证


52.1 SD NAND简介

52.1.1 SD NAND特点
SD NAND是一个采用LGA封装形式设计的嵌入式存储芯片,跟SD卡的使用一样,SD NAND完全符合SD2.0接口,允许大多数通用CPU使用。SD NAND内置SLC晶圆,读写寿命可达5-10万次,为嵌入式而生。 SD NAND的特点包括:
1,时钟频率最高支持50MHz
2,兼容SD协议
3,支持SPI模式和SD模式
4,内置HW ECC引擎和高可靠的NAND管理机制
5,写入速度可达6级
6,先进的热管理功能,以最大限度地提高性能和数据保护
7,坏块管理,智能垃圾收集和支持交错,缓和和多平面编程
8,读取干扰管理和动态数据刷新
9,程序/擦除:60,000周期
SD NAND 的内部结构图,如图52.1.1.1所示:


第五十二章 SD NAND实验786.png
图52.1.1.1 SD NAND内部结构图

可以看出SD NAND内部是由一个控制器和一个flash组成,支持SD模式和SPI模式,内部控制器包含ECC、磨损均衡、电源管理、时钟控制等功能,不需要额外的驱动去做处理。
下面来看看SD NAND的引脚分配,如图52.1.1.2所示:


第五十二章 SD NAND实验930.png
图52.1.1.2 SD NAND的引脚分配图

上述表格的“脚位数”,对应于实卡上的“金手指”数,不同类型的卡的触点数量不同,访问的速度也不相同。SD NAND允许了不同的接口来访问它的内部存储单元。最常见的是SD模式和SPI模式,根据这两种接口模式,我们也列出SD卡引脚对应于这两种不同的电路模式的引脚功能定义,如表52.1.1.1 所示。

1.png
表52.1.1.1 SD NAND引脚编号(注:S:电源 I:输入 O:推挽输出 PP:推挽)

本例程我们选择SPI模式来驱动SD NAND。但是要注意的是SPI接口只是定义了物理传输层,并没有定义完整的数据传输协议,因此在读写数据时还是需要遵循SD接口协议。
SD NAND有自己的寄存器,但它不能直接进行读写操作,需要通过命令来控制,SDIO协议定义了一些命令用于实现某一特定功能,SD NAND根据收到的命令要求对内部寄存器进行修改。表52.1.1.2中描述的SD NAND的6个寄存器和SD状态信息,是我们和SD NAND进行数据通讯的主要通道(注意:此卡不支持DSR),如下:


2.png
表52.1.1.2 SD  NAND寄存器信息

关于SD NAND的更多信息和硬件设计规范可以参考SD卡协议《Physical Layer Simplified Specification Version 2.00》的相关章节(注:因为STM32的SDIO匹配的是SD协议2.0版本,后续版本也兼容此旧协议版本,故本章仍以2.0版本为介绍对象)。

52.1.2 命令和响应
命令在CMD线上串行传输。命令是启动从主机到设备的操作的令牌。
响应也在CMD线上串行传输,是应答先前接收到的命令的令牌。
这里SD NAND的命令和响应和SD卡的一样,详情请见SD卡章节的53.1.2小节。


52.1.3 SD NAND初始化流程
SPI模式下的SD  NAND初始化
《SD卡2.0协议.pdf》中提供了SD卡的SPI初始化时序,我们可以按它建议的流程进行SD NAND的初始化,如图52.1.3.1所示。


第五十二章 SD NAND实验2251.png
图52.1.3.1 SD NAND的SPI初始化流程(SPI Mode Initialization Flow)

要使用SPI模式驱动SD NAND,先得让SD NAND进入SPI模式。方法如下:在SD NAND收到复位命令(CMD0)时,CS为有效电平(低电平)则SPI模式被启用。不过在发送CMD0之前,要发送>74个时钟,这是因为SD卡内部有个供电电压上升时间,大概为64个CLK,剩下的10个CLK用于SD卡同步,之后才能开始CMD0的操作,在卡初始化的时候,CLK时钟最大不能超过400Khz!
接着我们看看SD NAND的初始化,由于SD NAND是先发送数据高位的,初始化过程如下:
1、初始化与SD NAND连接的硬件条件(MCU的SPI配置,IO口配置);
2、拉低片选信号,上电延时(>74个CLK);
3、复位卡(CMD0),进入IDLE状态;
4、发送CMD8,检查是否支持2.0协议;
5、根据不同协议检查SD卡(命令包括:CMD55、ACMD41、CMD58和CMD1等);
6、取消片选,发多8个CLK,结束初始化
这样我们就完成了对SD NAND的初始化,注意末尾发送的8个CLK是提供SD卡额外的时钟,完成某些操作。在完成了初始化之后,就可以开始读写数据了。
SD NAND单扇区读取数据,这里通过CMD17来实现,具体过程如下:        
1、发送CMD17;
2、接收卡响应R1;
3、接收数据起始令牌0XFE;
4、接收数据;
5、接收2个字节的CRC,如果不使用CRC,这两个字节在读取后可以丢掉。
6、禁止片选之后,发多8个CLK;
以上就是一个典型的读取SD NAND数据过程,SD NAND的写与读数据差不多,写数据通过CMD24来实现,具体过程如下:
1、发送CMD24;
2、接收卡响应R1;
3、发送写数据起始令牌0XFE;
4、发送数据;
5、发送2字节的伪CRC;
6、禁止片选之后,发多8个CLK;
以上就是一个典型的写SD NAND过程。关于SD NAND的介绍,我们就介绍到这里,更详细的介绍请参考光盘资料→7,硬件资料→SD卡资料→SD卡V2.0协议。


52.2 SPI寄存器
由于前面第四十七章无线通信章节已经介绍过SPI接口了,这里就不赘述了,有需要可以查看47.1.4小节的内容。接下来给大家介绍一下本实验用到的SPI寄存器。
SPI配置寄存器1 (SPI_CFG1)
SPI配置寄存器1,该寄存器定义如图52.2.1.1所示:


第五十二章 SD NAND实验3300.png
图52.2.1.1 SPI_CFG1配置寄存器1

该寄存器我们关注位MBR[2:0],配置为111,即使用256分频,速度最低;
SPI配置寄存器2 (SPI_CFG2)
SPI配置寄存器2,该寄存器定义如图52.2.1.2所示:


第五十二章 SD NAND实验3418.png
图52.2.1.2 SPI配置寄存器2

下面讲解一下本实验配置的位,我们配置位CPHA为1,数据采样从第二个时钟边沿开始;位CPOL置1,在空闲状态是2,SCK保持高电平;位MASTER置1,配置为主机模式;位LSBFRST置0,MSB先传输,

52.3 硬件设计

1. 例程功能
本章实验功能简介:开机的时候先初始化SD NAND,如果SD NAND初始化完成,则提示LCD初始化成功。按下KEY0,读取SD NAND第0个块的数据,然后通过串口发送到电脑。如果没初始化通过,则在LCD上提示初始化失败。同样用LED0来指示程序正在运行。

2. 硬件资源
1)LED灯
       LED0:LED0 – PD14
2)独立按键
       KEY0 – PE9
3)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(包括MCU屏和RGB屏,都支持)
4)串口1 (PB14/PB15连接在板载USB转串口芯片CH340上面)
5)SD NAND(SPI5接口,SPI5_SCK – PF15、SPI5_MOSI – PF14、SPI5_MISO – PF12)

3. 原理图
前面介绍SD卡时我们已经介绍了SD卡对外的接口部分,实际上SD卡对于我们来说是可以灵活变更的部分,实际使用时,业界常用SD卡卡座用于专门放置SD卡。
下面我们介绍一下板载的SD卡接口和STM32的连接关系,如图53.4.1所示:


第五十二章 SD NAND实验4031.png
图52.4.1 SD卡接口与STM32连接原理图

microSD卡座在开发板正面,卡座和STM32开发板上是直接连接在一起的,硬件上不需要任何改动。

52.4 程序设计

52.4.1 程序解析

1. SD NAND驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。SD NAND驱动源码包括两个文件:spi_sdnand.c和spi_sdnand.h。
首先是spi_sdnand.h文件,根据我们STM32的复用功能和我们的硬件设计,我们把用到的管脚用宏定义,需要更换其它的引脚时也可以通过修改宏实现快速移植。这里与SD NAND相关的引脚共有四个,SPI_SCK、SPI_MISO、SPI_MOSI和SD_CS,它们列出如下:

  1. #define SDNAND_SPI                        SPI5
  2. #define SDNAND_SPI_CLK_ENABLE()           do { __HAL_RCC_SPI5_CLK_ENABLE(); } while (0)
  3. #define SDNAND_SPI_CLK_DISABLE()          do { __HAL_RCC_SPI5_CLK_DISABLE(); } while (0)
  4. #define SDNAND_SPI_SCK_GPIO_PORT          GPIOF
  5. #define SDNAND_SPI_SCK_GPIO_PIN           GPIO_PIN_15
  6. #define SDNAND_SPI_SCK_GPIO_AF            GPIO_AF5_SPI5
  7. #define SDNAND_SPI_SCK_GPIO_CLK_ENABLE()  do { __HAL_RCC_GPIOF_CLK_ENABLE(); } while (0)
  8. #define SDNAND_SPI_MOSI_GPIO_PORT         GPIOF
  9. #define SDNAND_SPI_MOSI_GPIO_PIN          GPIO_PIN_14
  10. #define SDNAND_SPI_MOSI_GPIO_AF           GPIO_AF5_SPI5
  11. #define SDNAND_SPI_MOSI_GPIO_CLK_ENABLE() do { __HAL_RCC_GPIOF_CLK_ENABLE(); } while (0)
  12. #define SDNAND_SPI_MISO_GPIO_PORT         GPIOF
  13. #define SDNAND_SPI_MISO_GPIO_PIN          GPIO_PIN_12
  14. #define SDNAND_SPI_MISO_GPIO_AF           GPIO_AF5_SPI5
  15. #define SDNAND_SPI_MISO_GPIO_CLK_ENABLE() do { __HAL_RCC_GPIOF_CLK_ENABLE(); } while (0)
  16. #define SDNAND_CS_GPIO_PORT               GPIOF
  17. #define SDNAND_CS_GPIO_PIN                GPIO_PIN_13
  18. #define SDNAND_CS_GPIO_CLK_ENABLE()       do { __HAL_RCC_GPIOF_CLK_ENABLE(); } while (0)
复制代码
接下来我们看一下sdnand_init.c代码中的初始化函数,代码如下:
  1. /**
  2. * @brief   初始化SD NAND
  3. * [url=home.php?mod=space&uid=271674]@param[/url]   无
  4. * @retval  初始化结果
  5. * @arg     0: 初始化成功
  6. * @arg     1: 初始化失败
  7. */
  8. uint8_t sdnand_init(void)
  9. {
  10.     uint8_t index;
  11.     uint16_t t;
  12.     uint8_t resp7[4];
  13.    
  14.     /* 初始化片选信号 */
  15.     sdnand_chip_select_init();
  16.    
  17.     /* SD NAND初始化前低速模式初始化SPI */
  18.     sdnand_spi_init(SDNAND_SPI_SPEED_LOW);
  19.    
  20.     /* 发送至少74个时钟以上电SD */
  21.     for (index = 0; index < ((74 + 7) / 8); index++)
  22.     {
  23.        sdnand_spi_read_write_byte(0xFF);
  24.     }
  25.    
  26.     /* 进入IDLE状态 */
  27.     t = 20;
  28.     while (t--)
  29.     {
  30.         if (sdnand_send_cmd(SDNAND_CMD0, 0UL) == 0x01)
  31.         {
  32.             break;
  33.         }
  34.     }
  35.     if (t == 0)
  36.     {
  37.         sdnand_chip_select_disable();
  38.         return 1;
  39.     }
  40.    
  41.     /* 发送容量支持信息并激活SD NAND初始化程序 */
  42.     t = 20;
  43.     while (t--)
  44.     {
  45.         if (sdnand_send_cmd(SDNAND_CMD55, 0UL) <= 0x01)
  46.         {
  47.             if (sdnand_send_cmd(SDNAND_ACMD41, 0UL) == 0x00)
  48.             {
  49.                 break;
  50.             }
  51.         }
  52.     }
  53.     if (t == 0)
  54.     {
  55.         sdnand_chip_select_disable();
  56.         return 1;
  57.     }
  58.    
  59.     /* SD NAND初始化后高速模式初始化SPI */
  60.     sdnand_spi_init(SDNAND_SPI_SPEED_HIGH);
  61.    
  62.     /* 设置块大小 */
  63.     if (sdnand_send_cmd(SDNAND_CMD16, SDNAND_BLOCK_SIZE) != 0x00)
  64.     {
  65.         sdnand_chip_select_disable();
  66.         return 1;
  67.     }
  68.     if (sdnand_recv_data(sdnand_info.csd, sizeof(sdnand_info.csd)) != 0)
  69.     {
  70.         sdnand_chip_select_disable();
  71.         return 1;
  72.     }
  73.    
  74.     /* 读取CSD */
  75.     if (sdnand_send_cmd(SDNAND_CMD9, 0UL) != 0x00)
  76.     {
  77.         sdnand_chip_select_disable();
  78.         return 1;
  79.     }
  80.     if (sdnand_recv_data(sdnand_info.csd, sizeof(sdnand_info.csd)) != 0)
  81.     {
  82.         sdnand_chip_select_disable();
  83.         return 1;
  84.     }
  85.     sdnand_chip_select_disable();
  86.    
  87.     /* 计算SD NAND参数信息 */
  88.     sdnand_info.block_size = (1UL << (sdnand_info.csd[5] & 0x0FUL));
  89. sdnand_info.block_num = (((((((uint32_t)sdnand_info.csd[6] & 0x03UL) << 8)
  90. | sdnand_info.csd[7]) << 2UL) | (((uint32_t)sdnand_info.csd[8] & 0xC0UL)
  91. >> 6UL)) + 1UL) * (1UL << ((((sdnand_info.csd[9] & 0x03UL) << 1UL) |
  92. ((sdnand_info.csd[10] & 0x80UL) >> 7UL)) + 2));
  93.     sdnand_info.chip_size = sdnand_info.block_num * sdnand_info.block_size;
  94.     sdnand_info.logic_block_size = SDNAND_BLOCK_SIZE;
  95. sdnand_info.logic_block_num = sdnand_info.chip_size /
  96. sdnand_info.logic_block_size;
  97.    
  98.     return 0;
  99. }
复制代码
该函数先初始化与SD NAND相关的IO口以及SPI初始化,然后发送CMD0,进入IDLE状态,并设置SD NAND为SPI模式通信,然后判断SD NAND类型,完成SD NAND的初始化,注意该函数调用的sdnand_spi_init等函数,实际是对SPI5的相关函数进行了一层封装,方便移植。
下面介绍一下SD NAND读取函数,也是按照前面分析的读取数据的过程进行操作,主要是通过CMD17进行实现,用于从SD NAND读取扇区的数据,代码如下:

  1. /**
  2. * @brief   读SD NAND指定数量块的数据
  3. * @param   data: 数据缓冲区指针
  4. * @param   block_index: 起始块
  5. * @param   block_num: 块数量
  6. * @retval  读取结果
  7. * @arg     0: 读取成功
  8. * @arg     1: 读取失败
  9. */
  10. uint8_t sdnand_read_disk(uint8_t *data, uint32_t block_index, uint32_t block_num)
  11. {
  12.     uint32_t address;
  13.    
  14.     if (block_num == 0)
  15.     {
  16.         return 0;
  17.     }
  18.    
  19.     if (data == NULL)
  20.     {
  21.         return 1;
  22.     }
  23.    
  24.     if ((block_index + block_num) > sdnand_info.logic_block_num)
  25.     {
  26.         return 1;
  27.     }
  28.    
  29.     /* 计算块地址 */
  30.     address = block_index * sdnand_info.logic_block_size;
  31.    
  32.     /* 单块读 */
  33.     if (block_num == 1)
  34.     {
  35.         if (sdnand_send_cmd(SDNAND_CMD17, address) != 0x00)
  36.         {
  37.             sdnand_chip_select_disable();
  38.             return 1;
  39.         }
  40.         
  41.         if (sdnand_recv_data(data, sdnand_info.logic_block_size) != 0)
  42.         {
  43.             sdnand_chip_select_disable();
  44.             return 1;
  45.         }
  46.     }
  47.     /* 多块读 */
  48.     else
  49.     {
  50.         if (sdnand_send_cmd(SDNAND_CMD18, address) != 0x00)
  51.         {
  52.             sdnand_chip_select_disable();
  53.             return 1;
  54.         }
  55.         
  56.         while (block_num--)
  57.         {
  58.             if (sdnand_recv_data(data, sdnand_info.logic_block_size) != 0)
  59.             {
  60.                 sdnand_chip_select_disable();
  61.                 return 1;
  62.             }
  63.             data += sdnand_info.logic_block_size;
  64.         }
  65.         
  66.         sdnand_send_cmd(SDNAND_CMD12, 0);
  67.     }
  68.    
  69.     /* 取消片选 */
  70.     sdnand_chip_select_disable();
  71.    
  72.     return 0;
  73. }
复制代码
此函数根据要读取扇区的多少,发送CMD17/CMD18命令,然后读取一个/多个扇区的数据。这个扇区读取的过程在前面也有提及到了,实现过程也不是很难理解,所以这里就不做展开了。
SD NAND写函数跟读函数差异不大,写函数是通过CMD24来实现,代码如下:

  1. /**
  2. * @brief   写SD NAND指定数量块的数据
  3. * @param   data: 数据缓冲区指针
  4. * @param   block_index: 起始块
  5. * @param   block_num: 块数量
  6. * @retval  写入结果
  7. * @arg     0: 写入成功
  8. * @arg     1: 写入失败
  9. */
  10. uint8_t sdnand_write_disk(uint8_t *data, uint32_t block_index, uint32_t block_num)
  11. {
  12.     uint32_t address;
  13.     uint8_t t;
  14.    
  15.     if (block_num == 0)
  16.     {
  17.         return 0;
  18.     }
  19.    
  20.     if (data == NULL)
  21.     {
  22.         return 1;
  23.     }
  24.    
  25.     if ((block_index + block_num) > sdnand_info.logic_block_num)
  26.     {
  27.         return 1;
  28.     }
  29.    
  30.     /* 计算块地址 */
  31.     address = block_index * sdnand_info.logic_block_size;
  32.    
  33.     /* 单块写 */
  34.     if (block_num == 1)
  35.     {
  36.         if (sdnand_send_cmd(SDNAND_CMD24, address) != 0x00)
  37.         {
  38.             sdnand_chip_select_disable();
  39.             return 1;
  40.         }
  41.         
  42.         if (sdnand_send_block_data(0xFE, data) != 0)
  43.         {
  44.             sdnand_chip_select_disable();
  45.             return 1;
  46.         }
  47.     }
  48.     /* 多块写 */
  49.     else
  50.     {
  51.         t = 20;
  52.         while (t--)
  53.         {
  54.             if (sdnand_send_cmd(SDNAND_CMD55, 0UL) <= 0x01)
  55.             {
  56.                 if (sdnand_send_cmd(SDNAND_ACMD23, block_num) == 0x00)
  57.                 {
  58.                     break;
  59.                 }
  60.             }
  61.         }
  62.         if (t == 0)
  63.         {
  64.             sdnand_chip_select_disable();
  65.             return 1;
  66.         }
  67.         
  68.         if (sdnand_send_cmd(SDNAND_CMD25, address) != 0x00)
  69.         {
  70.             sdnand_chip_select_disable();
  71.             return 1;
  72.         }
  73.         
  74.         while (block_num--)
  75.         {
  76.             if (sdnand_send_block_data(0xFC, data) != 0)
  77.             {
  78.                 sdnand_chip_select_disable();
  79.                 return 1;
  80.             }
  81.             data += sdnand_info.logic_block_size;
  82.         }
  83.         if (sdnand_send_block_data(0xFD, NULL) != 0)
  84.         {
  85.             sdnand_chip_select_disable();
  86.             return 1;
  87.         }
  88.         
  89.         sdnand_send_cmd(SDNAND_CMD12, 0);
  90.     }
  91.    
  92.     /* 取消片选 */
  93.     sdnand_chip_select_disable();
  94.    
  95.     return 0;
  96. }
复制代码
此函数根据要写扇区的多少,发送CMD24/CMD23命令,然后写入一个/多个扇区的数据。这个扇区写入的过程在前面也提及到了。

2. main.c代码
最后,我们在main.c编写的程序如下:

  1. int main(void)
  2. {
  3.     uint8_t t = 0;
  4.     uint8_t key;
  5.    
  6.     sys_mpu_config();                   /* 配置MPU */
  7.     sys_cache_enable();                 /* 使能Cache */
  8.     HAL_Init();                         /* 初始化HAL库 */
  9.     sys_stm32_clock_init(300, 6, 2);    /* 配置时钟,600MHz */
  10.     delay_init(600);                    /* 初始化延时 */
  11.     usart_init(115200);                 /* 初始化串口 */
  12.     led_init();                         /* 初始化LED */
  13.     key_init();                         /* 初始化按键 */
  14.     hyperram_init();                    /* 初始化HyperRAM */
  15.     lcd_init();                         /* 初始化LCD */
  16.     my_mem_init(SRAMIN);                /* 初始化AXI-SRAM1~4内存池 */
  17.     my_mem_init(SRAMEX);                /* 初始化XSPI2 HyperRAM内存池 */
  18.     my_mem_init(SRAM12);                /* 初始化AHB-SRAM1~2内存池 */
  19.     my_mem_init(SRAMDTCM);              /* 初始化DTCM内存池 */
  20.     my_mem_init(SRAMITCM);              /* 初始化ITCM内存池 */
  21.     sdnand_init();                      /* SD NAND初始化 */
  22.    
  23.     lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  24.     lcd_show_string(30, 70, 200, 16, 16, "SD NAND TEST", RED);
  25.     lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  26.    
  27.     /* 显示SD NAND信息 */
  28.     show_sdnand_info();
  29.    
  30.     while (1)
  31.     {
  32.         key = key_scan(0);
  33.         if (key == KEY0_PRES)
  34.         {
  35.             /* SD NAND读测试 */
  36.             sdnand_read_test();
  37.         }
  38.         
  39.         if (++t == 20)
  40.         {
  41.             t = 0;
  42.             LED0_TOGGLE();
  43.         }
  44.         
  45.         delay_ms(10);
  46.     }
  47. }
复制代码
main函数先初始化相关外设和SD NAND,初始化成功后,调用show_sdnand_info函数获取SD NAND的信息。然后按下按键KEY0,则通过sdnand_read_test进行SD NAND读测试,用于读取SD NAND指定扇区的数据,并将读到的数据通过串口1输出。

52.5 下载验证
将程序下载到开发板后, SD NAND成功初始化后,LCD显示本程序的一些必要信息,如图52.5.1:

第五十二章 SD NAND实验13622.png
图52.5.1 程序运行效果图

伴随LED0的不停闪烁,提示程序在运行。此时,我们按下KEY0,调用我们编写的SD测试函数,这里我们只用到了读函数,写函数的测试大家可以添加代码进行演示。按下后LCD显示按下,信息如图52.5.2,数量较多的情况我们用串口打印,得到的SD NAND扇区0的信息如图52.5.3所示:

第五十二章 SD NAND实验13782.png
图52.5.2 按下KEY0的开发板界面

第五十二章 SD NAND实验13805.png
图52.5.3 串口调试助手界面
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

如发现本坛存在违规或侵权内容, 请点击这里发送邮件举报 (或致电020-38271790)。请提供侵权说明和联系方式。我们将及时审核依法处理,感谢配合。

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-5-28 17:30

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表