<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>SD卡 on CLing</title>
        <link>https://clingyang.github.io/tags/sd%E5%8D%A1/</link>
        <description>Recent content in SD卡 on CLing</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <copyright>CLing</copyright>
        <lastBuildDate>Wed, 09 Sep 2026 09:51:13 +0800</lastBuildDate><atom:link href="https://clingyang.github.io/tags/sd%E5%8D%A1/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>HC32 SD 卡读写 — 擦除、写入与读回校验</title>
        <link>https://clingyang.github.io/p/hc32-sd-%E5%8D%A1%E8%AF%BB%E5%86%99-%E6%93%A6%E9%99%A4%E5%86%99%E5%85%A5%E4%B8%8E%E8%AF%BB%E5%9B%9E%E6%A0%A1%E9%AA%8C/</link>
        <pubDate>Wed, 09 Sep 2026 09:00:00 +0800</pubDate>
        
        <guid>https://clingyang.github.io/p/hc32-sd-%E5%8D%A1%E8%AF%BB%E5%86%99-%E6%93%A6%E9%99%A4%E5%86%99%E5%85%A5%E4%B8%8E%E8%AF%BB%E5%9B%9E%E6%A0%A1%E9%AA%8C/</guid>
        <description>&lt;h1 id=&#34;sd-卡读写擦除写入与读回校验&#34;&gt;SD 卡读写：擦除、写入与读回校验
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;源码路径：&lt;code&gt;example/HC32F460JEUA/6.sdioc/sd_multi_write_multi_read_4bit_50mhz/source/main.c&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;1-功能简介&#34;&gt;1. 功能简介
&lt;/h2&gt;&lt;p&gt;这个例子做的是一次&lt;strong&gt;完整的 SD 卡读写自检&lt;/strong&gt;，就像出厂测试程序一样，一步步验证卡到底能不能正常用。&lt;/p&gt;
&lt;p&gt;程序流程（上电自动跑一遍，不需要按键）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;初始化 SD 卡&lt;/strong&gt;：4 线总线 + 50MHz 高速模式。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;擦除&lt;/strong&gt;从第 0 个扇区开始的 4 个扇区。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;读回来检查擦除结果&lt;/strong&gt;：擦除后的数据应该全是 &lt;code&gt;0xFFFFFFFF&lt;/code&gt; 或 &lt;code&gt;0x00000000&lt;/code&gt;（不同卡的擦除填充值不同）。如果不是，说明擦除没成功。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写入数据&lt;/strong&gt;：往这 4 个扇区写入 0、1、2、3……递增的数字（这种「有规律的数据」最容易看出错在哪）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再读回来&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用 &lt;code&gt;memcmp&lt;/code&gt; 比对&lt;/strong&gt;写进去的和读出来的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全部通过亮绿灯，任何一步失败亮红灯&lt;/strong&gt;，然后进死循环。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;只要看到绿灯，就说明「SD 卡插好了、驱动没问题、读写都正常」。这是玩 SD 卡的第一步——先把底层通道验通，再谈上面的文件系统。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;2-硬件准备&#34;&gt;2. 硬件准备
&lt;/h2&gt;&lt;p&gt;用 HC32F460JEUA KIT 开发板，板载有 &lt;strong&gt;TF 卡（microSD）卡座&lt;/strong&gt;，插卡即用。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        HC32F460                          TF / SD 卡座
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ┌───────────┐                     ┌──────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      │ PB15  CK  ├────────────────────▶│ CLK          │
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      │ PA6   CMD ├◀───────────────────▶│ CMD          │
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      │ PB4   D0  ├◀───────────────────▶│ DAT0         │
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      │ PA8   D1  ├◀───────────────────▶│ DAT1         │
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      │ PA9   D2  ├◀───────────────────▶│ DAT2         │
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      │ PB5   D3  ├◀───────────────────▶│ DAT3 / CS    │
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      │ PH2   CD  ├◀────────────────────│ 卡检测（可选）│
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      └───────────┘                     └──────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                            3.3V 供电
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;准备工作&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一张 &lt;strong&gt;TF / microSD 卡&lt;/strong&gt;（建议 8GB 或 16GB 的正品卡，容量太大或杂牌卡容易初始化失败）。&lt;/li&gt;
&lt;li&gt;卡插到底、听到「咔」的一声。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;重要警告&lt;/strong&gt;
这个程序会&lt;strong&gt;擦除并覆写 SD 卡第 0~3 号扇区&lt;/strong&gt;！
**第 0 号扇区就是 MBR（主引导记录），存着分区表。**覆写它等于把卡「格式化坏了」——插到电脑上会提示「需要格式化」。
&lt;strong&gt;千万别用存着重要资料的卡跑这个例子！&lt;/strong&gt; 用一张空白的测试卡。
测完想恢复正常使用，在电脑上重新格式化一次就好。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;3-完整代码&#34;&gt;3. 完整代码
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;  1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 93
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 94
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 95
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 96
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 97
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 98
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 99
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;100
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;101
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;102
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;103
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;104
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;105
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;106
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;107
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;108
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;109
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;110
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;111
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;112
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;113
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;114
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;115
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;116
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;117
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;118
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;119
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;120
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;121
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;122
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;123
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;124
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;125
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;126
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;127
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;128
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;129
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;130
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;131
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;132
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;133
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;134
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;135
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;136
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;137
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;138
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;139
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;140
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;141
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;142
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;143
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;144
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;145
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;146
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;147
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;148
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;149
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;150
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;151
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;152
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;153
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;#34;sd_card.h&amp;#34;              // SD 卡驱动库（内部已包含 hc32_ddl.h）&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/* ---------- SDIOC 引脚定义 ---------- */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_CD_PORT    (PortH)  &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 卡检测（本例未启用）*/&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_CD_PIN     (Pin02)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_CK_PORT    (PortB)  &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 时钟 */&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_CK_PIN     (Pin15)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_CMD_PORT   (PortA)  &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 命令线 */&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_CMD_PIN    (Pin06)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D0_PORT    (PortB)  &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 数据线 0 */&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D0_PIN     (Pin04)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D1_PORT    (PortA)  &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 数据线 1 */&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D1_PIN     (Pin08)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D2_PORT    (PortA)  &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 数据线 2 */&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D2_PIN     (Pin09)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D3_PORT    (PortB)  &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 数据线 3 */&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_D3_PIN     (Pin05)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/* 测试范围：从第 0 个扇区开始，共 4 个扇区 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SD_SECTOR_START  (0u)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SD_SECTOR_COUNT  (4u)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/* 用 SDIOC 单元 1 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SDIOC_UNIT       (M4_SDIOC1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/*==============================================================
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt; * 把 7 根引脚全部复用为 SDIO 功能
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt; *=============================================================*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;en_result_t&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SdiocInitPins&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_SetFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOC_D0_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;SDIOC_D0_PIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;Func_Sdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_SetFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOC_D1_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;SDIOC_D1_PIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;Func_Sdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_SetFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOC_D2_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;SDIOC_D2_PIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;Func_Sdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_SetFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOC_D3_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;SDIOC_D3_PIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;Func_Sdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//  PORT_SetFunc(SDIOC_CD_PORT,  SDIOC_CD_PIN,  Func_Sdio, Disable);  /* 卡检测未用 */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_SetFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOC_CK_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;SDIOC_CK_PIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;Func_Sdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_SetFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOC_CMD_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SDIOC_CMD_PIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Func_Sdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/*==============================================================
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt; * 主函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt; *=============================================================*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int32_t&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;uint32_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;en_result_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                 &lt;span class=&#34;cm&#34;&gt;/* 测试结果累积标志 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;stc_sd_handle_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;            &lt;span class=&#34;cm&#34;&gt;/* SD 卡句柄 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* 写缓冲区：512 个 uint32_t = 2048 字节 = 正好 4 个扇区（4×512）*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint32_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* 读缓冲区：和写缓冲区一样大 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint32_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ARRAY_SZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* SD 卡初始化配置：4 线、50MHz、高速模式、不用 DMA */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;stc_sdcard_init_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stcCardInitCfg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;SdiocBusWidth4Bit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;       &lt;span class=&#34;cm&#34;&gt;/* 4 位总线宽度 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;SdiocClk50M&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;             &lt;span class=&#34;cm&#34;&gt;/* 50MHz 时钟 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;SdiocHighSpeedMode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;      &lt;span class=&#34;cm&#34;&gt;/* 高速模式 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;                    &lt;span class=&#34;cm&#34;&gt;/* DMA 配置为空 → 用轮询方式传输 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* 准备写入的数据：填 0,1,2,3,... 递增值，方便看出错在哪一位 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ARRAY_SZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;MEM_ZERO_STRUCT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;      &lt;span class=&#34;cm&#34;&gt;/* 读缓冲区清零 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* BSP 初始化 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;BSP_CLK_Init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;BSP_LED_Init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* 关掉 JTAG 调试脚复用（TDI/TDO/TRST 和 SDIOC 引脚有冲突）*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_DebugPortSetting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TDI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_DebugPortSetting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TDO_SWO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;PORT_DebugPortSetting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TRST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SdiocInitPins&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;                       &lt;span class=&#34;cm&#34;&gt;/* 配置 SDIOC 引脚 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* ===== ① 初始化 SD 卡 ===== */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOCx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SDIOC_UNIT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_Init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcCardInitCfg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* ===== ② 擦除 4 个扇区（超时给 20000）===== */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_Erase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_START&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* ===== ③ 读回来，验证擦除是否真的成功 ===== */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_START&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* 擦除后每个字应该是全 F 或全 0（不同卡的填充值不一样，两种都算合格）*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ARRAY_SZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xFFFFFFFFul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x00000000ul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* ===== ④ 写入数据 ===== */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_START&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                 &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* ===== ⑤ 再读回来 ===== */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_START&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SD_SECTOR_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* ===== ⑥ 比对写进去的和读出来的 ===== */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;memcmp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* ===== ⑦ 用 LED 显示最终结果 ===== */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nf&#34;&gt;BSP_LED_On&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LED_GREEN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;    &lt;span class=&#34;cm&#34;&gt;/* 全部通过 → 绿灯 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nf&#34;&gt;BSP_LED_On&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LED_RED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;      &lt;span class=&#34;cm&#34;&gt;/* 有任何一步失败 → 红灯 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;cm&#34;&gt;/* 测完就停在这里 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;4-代码分段讲解&#34;&gt;4. 代码分段讲解
&lt;/h2&gt;&lt;h3 id=&#34;41-缓冲区大小和扇区数必须严格对应&#34;&gt;4.1 缓冲区大小和扇区数必须严格对应
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint32_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 512 × 4 字节 = 2048 字节
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SD_SECTOR_COUNT   (4u)          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 4 × 512 字节 = 2048 字节  ✓ 相等
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;这是 SD 卡编程的第一要点&lt;/strong&gt;。SD 卡按 512 字节扇区读写，你要读 4 个扇区，缓冲区就必须至少有 4×512 = 2048 字节。&lt;/p&gt;
&lt;p&gt;这里 &lt;code&gt;uint32_t[512]&lt;/code&gt; 刚好是 2048 字节，完美对应。&lt;/p&gt;
&lt;p&gt;如果你改成读 8 个扇区却不改数组大小，&lt;code&gt;SDCARD_ReadBlocks&lt;/code&gt; 会往数组外面写 2048 字节——&lt;strong&gt;栈/内存直接被踩坏&lt;/strong&gt;，程序表现会极其诡异（随机崩溃、其他变量莫名变化）。这种 bug 非常难查，所以两个数字&lt;strong&gt;一定要一起改&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;安全的写法是让扇区数从数组大小推导出来：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SD_SECTOR_COUNT  (sizeof(au32WriteBlocks) / 512u)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;42-为什么要关掉-jtag-调试脚&#34;&gt;4.2 为什么要关掉 JTAG 调试脚
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;PORT_DebugPortSetting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TDI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;PORT_DebugPortSetting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TDO_SWO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;PORT_DebugPortSetting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TRST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;芯片刚上电时，一部分引脚默认是 &lt;strong&gt;JTAG 调试功能&lt;/strong&gt;（TDI、TDO、TRST）。而 SDIOC 用到的 PA8、PA9、PB4 这些引脚，正好和 JTAG 脚有复用冲突。&lt;/p&gt;
&lt;p&gt;不关掉的话，你 &lt;code&gt;PORT_SetFunc&lt;/code&gt; 设成 SDIO 功能也不生效——引脚还被 JTAG 占着。&lt;strong&gt;这就是「代码看着完全正确但外设死活不工作」的又一个经典原因。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;注意关掉这些脚会影响 JTAG 调试（SWD 调试不受影响，因为 SWD 只用 SWCLK/SWDIO）。所以正常用 SWD 下载调试没问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;43-错误累积的写法&#34;&gt;4.3 错误累积的写法
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;en_result_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_Init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...))&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_Erase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;绿灯&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;红灯&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;注意这里的设计：&lt;strong&gt;每一步失败都只是标记一下，不立刻退出&lt;/strong&gt;，最后统一看结果。&lt;/p&gt;
&lt;p&gt;好处是不管中间哪一步出错，最终都会有明确的 LED 指示。缺点是初始化失败后还会继续跑后面的读写（这些必然也失败），有点浪费。&lt;/p&gt;
&lt;p&gt;工程实践中更常见的写法是&lt;strong&gt;失败立即返回&lt;/strong&gt;（early return），或者用 &lt;code&gt;goto error_handler&lt;/code&gt; 跳到统一的错误处理。这样逻辑更清晰、也不会在坏状态下继续操作硬件。&lt;/p&gt;
&lt;h3 id=&#34;44-擦除后的验证很有讲究&#34;&gt;4.4 擦除后的验证很有讲究
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xFFFFFFFFul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x00000000ul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;为什么要接受&lt;strong&gt;两种&lt;/strong&gt;值？因为 &lt;strong&gt;SD 卡擦除后的填充值不是统一标准&lt;/strong&gt;——有的卡擦成全 1（&lt;code&gt;0xFF&lt;/code&gt;），有的卡擦成全 0（&lt;code&gt;0x00&lt;/code&gt;）。这取决于卡内部控制器的实现。&lt;/p&gt;
&lt;p&gt;所以代码宽容地认为「全 F 或全 0 都算擦干净了」。这是很实用的兼容性处理，说明写代码的人真正踩过不同品牌卡的坑。&lt;/p&gt;
&lt;h3 id=&#34;45-用递增数据做测试的妙处&#34;&gt;4.5 用递增数据做测试的妙处
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ARRAY_SZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;// 0, 1, 2, 3, 4, ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;为什么不用随机数、不用全 0？因为&lt;strong&gt;递增序列是最好的调试数据&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果读回来的是 &lt;code&gt;0,1,2,3,...&lt;/code&gt; 但从中间某处开始错乱，你一眼就能看出&lt;strong&gt;错在第几个字&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;如果整体偏移了（读回来是 &lt;code&gt;128,129,130...&lt;/code&gt;），说明&lt;strong&gt;起始扇区算错了&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;如果每 128 个字重复一次，说明&lt;strong&gt;扇区边界处理有问题&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;用全 0 或全 F 就完全看不出这些规律。&lt;strong&gt;测试存储器一定要用有规律但不重复的数据&lt;/strong&gt;，这是个很实用的技巧。&lt;/p&gt;
&lt;h3 id=&#34;46-超时参数为什么不一样&#34;&gt;4.6 超时参数为什么不一样
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;SDCARD_Erase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;// 擦除给 20000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;SDCARD_ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 读给 2000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;SDCARD_WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// 写给 2000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;SDCARD_ReadBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20000u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// 这次读又给 20000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;因为不同操作耗时差异很大：&lt;strong&gt;擦除 &amp;raquo; 写 &amp;gt; 读&lt;/strong&gt;。擦除是 SD 卡最慢的操作，超时必须给得宽松，否则明明在正常工作却被判超时失败。&lt;/p&gt;
&lt;p&gt;（代码里两次读的超时值不一致，属于示例的随意之处，实际用统一给足即可。）&lt;/p&gt;
&lt;h3 id=&#34;47-array_sz-和-mem_zero_struct&#34;&gt;4.7 &lt;code&gt;ARRAY_SZ&lt;/code&gt; 和 &lt;code&gt;MEM_ZERO_STRUCT&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;这两个是 ddl 库的实用宏：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;ARRAY_SZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;// 求数组元素个数 = sizeof(arr)/sizeof(arr[0])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;MEM_ZERO_STRUCT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;     &lt;span class=&#34;c1&#34;&gt;// 把 x 清零 = memset(&amp;amp;x, 0, sizeof(x))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;用 &lt;code&gt;ARRAY_SZ&lt;/code&gt; 而不是写死 &lt;code&gt;512&lt;/code&gt;，是好习惯——以后改数组大小，循环次数自动跟着变，不会漏改。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;5-实验现象&#34;&gt;5. 实验现象
&lt;/h2&gt;&lt;p&gt;插好 TF 卡，上电或复位：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;绿灯亮&lt;/strong&gt; → 全部测试通过 ✓（初始化 OK、擦除 OK、写入 OK、读回数据完全一致）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;红灯亮&lt;/strong&gt; → 某一步失败 ✗&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;程序跑完就停在 &lt;code&gt;while(1)&lt;/code&gt;，灯的状态保持不变。想再测一次就按复位键。&lt;/p&gt;
&lt;p&gt;测试完成后，这张卡的第 0~3 扇区已经被写成递增数据了。插到电脑上会提示「需要格式化」——这是正常的，因为 MBR 被覆盖了。重新格式化即可恢复。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;6-常见问题&#34;&gt;6. 常见问题
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Q1：一直红灯，怎么定位到底哪一步失败？&lt;/strong&gt;
最有效的办法是&lt;strong&gt;加串口打印&lt;/strong&gt;。先初始化串口，然后：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;DDL_PrintfInit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BSP_PRINTF_DEVICE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BSP_PRINTF_BAUDRATE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BSP_PRINTF_PortInit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_Init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcCardInitCfg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;SDCARD_Init failed!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\r\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SDCARD_Erase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Erase failed!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\r\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;enTestResult&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// ... 每一步都加
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样串口助手里直接告诉你卡在哪儿。&lt;strong&gt;这就是串口章节说的「打印大法」的实战价值。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q2：&lt;code&gt;SDCARD_Init&lt;/code&gt; 就失败了？&lt;/strong&gt;
最常见，按顺序查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;卡插到底了吗？&lt;/strong&gt; 听到「咔」声才算到位。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;PORT_DebugPortSetting&lt;/code&gt; 三行写了吗？&lt;/strong&gt; 漏了 JTAG 会占着 PA8/PA9 等引脚。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;换张卡试试。&lt;/strong&gt; 杂牌卡、容量特别大（64GB 以上 SDXC）的卡兼容性差，初始化协议可能不支持。建议用 8GB/16GB 正品 Class10 卡。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;降速试试&lt;/strong&gt;：把 &lt;code&gt;SdiocClk50M&lt;/code&gt; 改成更低的时钟、&lt;code&gt;SdiocHighSpeedMode&lt;/code&gt; 改成 &lt;code&gt;SdiocNormalSpeedMode&lt;/code&gt;。50MHz 对信号质量要求高，杜邦线飞线基本跑不起来。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;先用 1 线模式&lt;/strong&gt;：&lt;code&gt;SdiocBusWidth4Bit&lt;/code&gt; 改成 &lt;code&gt;SdiocBusWidth1Bit&lt;/code&gt;。能通说明是 D1/D2/D3 那几根线的问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Q3：初始化过了，但擦除或读写失败？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;超时给太小了。&lt;/strong&gt; 试着把超时参数加大 10 倍。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;降低时钟频率&lt;/strong&gt;。速度越快越容易出错。&lt;/li&gt;
&lt;li&gt;检查 D1/D2/D3 三根线（只有 4 线模式才用到它们，1 线模式下不影响初始化但影响读写）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Q4：&lt;code&gt;memcmp&lt;/code&gt; 比对失败，但读写函数都返回 Ok？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;说明数据传输过程中出错了（信号质量问题）。&lt;strong&gt;降低时钟频率&lt;/strong&gt;是第一手段。&lt;/li&gt;
&lt;li&gt;也检查缓冲区大小和扇区数是否匹配（见 4.1）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Q5：我的卡插上后电脑不认了！&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这是&lt;strong&gt;预期行为&lt;/strong&gt;，因为程序覆写了第 0 扇区（MBR）。在电脑上重新格式化即可恢复。&lt;/li&gt;
&lt;li&gt;想避免破坏文件系统，把 &lt;code&gt;SD_SECTOR_START&lt;/code&gt; 改成一个很大的值（比如 &lt;code&gt;100000u&lt;/code&gt;），去测卡的中后段区域，就不会碰到 MBR 和文件系统的关键结构了。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Q6：怎么让读写更快？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 &lt;strong&gt;DMA 版本&lt;/strong&gt;。把 &lt;code&gt;stcCardInitCfg&lt;/code&gt; 最后那个 &lt;code&gt;NULL&lt;/code&gt; 换成 DMA 配置，CPU 就不用参与搬数据了。SDK 里有现成的 &lt;code&gt;sd_multi_write_multi_read_4bit_dma_50mhz&lt;/code&gt; 示例。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一次多读几个扇区&lt;/strong&gt;。读 100 个扇区比读 100 次单扇区快得多（命令开销省下来了）。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;7-小结&#34;&gt;7. 小结
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;SD 卡&lt;strong&gt;按 512 字节扇区读写&lt;/strong&gt;，缓冲区大小和扇区数&lt;strong&gt;必须严格对应&lt;/strong&gt;，否则内存越界。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;SDCARD_Init&lt;/code&gt; / &lt;code&gt;Erase&lt;/code&gt; / &lt;code&gt;WriteBlocks&lt;/code&gt; / &lt;code&gt;ReadBlocks&lt;/code&gt; 四个函数，每个都带&lt;strong&gt;超时参数&lt;/strong&gt;（擦除要给大）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;必须先关 JTAG 调试脚复用&lt;/strong&gt;（&lt;code&gt;PORT_DebugPortSetting&lt;/code&gt;），否则引脚被占用。&lt;/li&gt;
&lt;li&gt;擦除后的值可能是&lt;strong&gt;全 F 或全 0&lt;/strong&gt;，两种都要当成正常。&lt;/li&gt;
&lt;li&gt;测存储器用&lt;strong&gt;递增数据&lt;/strong&gt;，最容易定位错在哪。&lt;/li&gt;
&lt;li&gt;出问题按这个顺序试：&lt;strong&gt;降时钟 → 换 1 线 → 换卡 → 加串口打印定位&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;本例会覆写第 0 扇区（MBR），&lt;strong&gt;用测试卡，别用有重要数据的卡&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;8-拓展应用&#34;&gt;8. 拓展应用
&lt;/h2&gt;&lt;p&gt;底层通道验通之后，SD 卡真正的威力才开始：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;移植 FatFS 文件系统&lt;/strong&gt;（最重要的下一步）
把 &lt;code&gt;SDCARD_ReadBlocks&lt;/code&gt; / &lt;code&gt;WriteBlocks&lt;/code&gt; 接到 FatFS 的 &lt;code&gt;disk_read&lt;/code&gt; / &lt;code&gt;disk_write&lt;/code&gt; 接口上，你就能这样写代码：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;f_open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;data.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FA_WRITE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FA_CREATE_ALWAYS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;f_printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;%d,%d&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\r\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;temperature&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;f_close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;生成的文件电脑能直接打开！&lt;/strong&gt; 这是 SD 卡最大的价值所在——数据不再是裸扇区，而是人能看懂的文件。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;数据记录仪 / 数据采集器&lt;/strong&gt;
传感器数据按时间戳存成 CSV 文件，拔卡插电脑，Excel 直接打开画曲线。温湿度记录、电池测试、振动监测都这么做。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;黑匣子 / 运行日志&lt;/strong&gt;
设备运行状态、错误码持续写入日志文件。出故障了把卡拔出来分析，比接串口盯着看实用得多。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;音频播放器&lt;/strong&gt;
WAV 文件存卡里，用 FatFS 读出 PCM 数据送给 DAC 或 I2S 功放，就是个音乐播放器。语音提示、报警音同理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;图片 / 界面资源加载&lt;/strong&gt;
GUI 的图片、字库、皮肤存在卡里，需要时读出来显示。好处是&lt;strong&gt;改素材不用重新编译固件&lt;/strong&gt;，换张卡就换了界面。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;固件升级（OTA / 卡升级）&lt;/strong&gt;
把新固件 &lt;code&gt;.bin&lt;/code&gt; 放到卡里，设备上电时 Bootloader 检测到有升级文件就自动更新。这是工业设备最省事的升级方式——现场维护人员只需要插张卡。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;配置文件&lt;/strong&gt;
设备参数写成卡里的 &lt;code&gt;config.txt&lt;/code&gt;，用户用记事本改改就能配置设备，不用专门做上位机软件。非常适合小批量产品。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;摄像头存图&lt;/strong&gt;
接个 OV2640 摄像头，拍照存成 JPG 到卡里，做个简易行车记录仪或监控。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>HC32 SDIOC — SD 卡接口</title>
        <link>https://clingyang.github.io/post/mcu_hc32/sdioc/</link>
        <pubDate>Wed, 09 Sep 2026 09:00:00 +0800</pubDate>
        
        <guid>https://clingyang.github.io/post/mcu_hc32/sdioc/</guid>
        <description>&lt;h1 id=&#34;sdioc--给单片机插一张存储卡&#34;&gt;SDIOC — 给单片机插一张存储卡
&lt;/h1&gt;&lt;h2 id=&#34;这一章讲什么&#34;&gt;这一章讲什么
&lt;/h2&gt;&lt;p&gt;上一章的 QSPI Flash 是&lt;strong&gt;焊死在板子上&lt;/strong&gt;的，容量 8MB 左右。如果你要存&lt;strong&gt;几个 GB 的数据&lt;/strong&gt;，或者希望&lt;strong&gt;把存储介质拔下来插到电脑上看&lt;/strong&gt;，那就该用 &lt;strong&gt;SD 卡 / TF 卡&lt;/strong&gt;了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDIOC&lt;/strong&gt;（SD Input/Output Controller）就是 HC32F460 里专门驱动 SD 卡的硬件控制器。&lt;/p&gt;
&lt;p&gt;SD 卡的好处很直白：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;容量大&lt;/strong&gt;：几 GB 到几十 GB，随便买。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可插拔&lt;/strong&gt;：数据存好了，卡拔下来插电脑读，超方便。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有文件系统&lt;/strong&gt;：配合 FatFS 就能直接读写 &lt;code&gt;.txt&lt;/code&gt;、&lt;code&gt;.csv&lt;/code&gt;、&lt;code&gt;.wav&lt;/code&gt; 文件，电脑也认。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代价是：SD 卡的协议比 SPI Flash 复杂得多（初始化要走一整套握手流程），好在 ddl 库把这些都封装好了。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;sdioc-的引脚&#34;&gt;SDIOC 的引脚
&lt;/h2&gt;&lt;p&gt;SD 卡通信需要 &lt;strong&gt;CLK + CMD + 数据线&lt;/strong&gt; 三类信号：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;信号&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;引脚&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;作用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;CK&lt;/strong&gt;（时钟）&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;PB15&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;主机给卡的时钟&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;CMD&lt;/strong&gt;（命令）&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;PA6&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;双向，发命令、收响应&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;D0&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;PB4&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;数据线 0&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;D1&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;PA8&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;数据线 1&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;D2&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;PA9&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;数据线 2&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;D3&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;PB5&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;数据线 3&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;CD&lt;/strong&gt;（检测）&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;PH2&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;检测卡有没有插入（可选）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;引脚复用统一用 &lt;code&gt;Func_Sdio&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;PORT_SetFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PortB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Pin15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Func_Sdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Disable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 每根线都这样配
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;HC32F460 有两个 SDIOC 单元：&lt;code&gt;M4_SDIOC1&lt;/code&gt;、&lt;code&gt;M4_SDIOC2&lt;/code&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总线宽度1-线还是-4-线&#34;&gt;总线宽度：1 线还是 4 线
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;总线宽度&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;ddl 写法&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;数据线&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;速度&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;1 位&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;SdiocBusWidth1Bit&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;只用 D0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;慢，但省引脚&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;4 位&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;SdiocBusWidth4Bit&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;D0~D3 一起用&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;快 4 倍，推荐&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;和 QSPI 一个道理——多开几条车道就快几倍。4 线模式是标准做法。&lt;/p&gt;
&lt;h2 id=&#34;时钟频率与速度模式&#34;&gt;时钟频率与速度模式
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SdiocClk50M&lt;/span&gt;              &lt;span class=&#34;c1&#34;&gt;// 50MHz 时钟
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SdiocHighSpeedMode&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;// 高速模式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;模式&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;最高时钟&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;理论带宽（4 线）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;普通速度 &lt;code&gt;SdiocNormalSpeedMode&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;25MHz&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;~12.5 MB/s&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;高速&lt;/strong&gt; &lt;code&gt;SdiocHighSpeedMode&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;50MHz&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;~25 MB/s&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;高速 + 4 线是性能最优组合，本章示例用的就是这个。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;实际速度还受卡本身速度等级（Class 10、U1、U3）限制。买卡别买山寨的，杂牌卡不仅慢，还容易初始化失败。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;核心概念sd-卡按扇区读写&#34;&gt;核心概念：SD 卡按「扇区」读写
&lt;/h2&gt;&lt;p&gt;这是 SD 卡最重要的概念，理解了它才能写对代码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SD 卡的最小读写单位是一个「块」（Block），也叫「扇区」（Sector），固定 512 字节。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你&lt;strong&gt;不能&lt;/strong&gt;只读一个字节，也&lt;strong&gt;不能&lt;/strong&gt;只写 100 字节。所有操作都是「从第 N 个扇区开始，读/写 M 个扇区」。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   SD 卡内部（就是一长串 512 字节的格子）
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ┌────────┬────────┬────────┬────────┬─────
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   │ 扇区0  │ 扇区1  │ 扇区2  │ 扇区3  │ ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   │ 512B   │ 512B   │ 512B   │ 512B   │
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   └────────┴────────┴────────┴────────┴─────
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     ↑
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     地址 = 扇区号（不是字节地址！）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;所以数据缓冲区的大小必须是 &lt;strong&gt;512 的整数倍&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint32_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;au32WriteBlocks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 512 个 uint32_t = 2048 字节 = 4 个扇区
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SD_SECTOR_COUNT   (4u)          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 正好对应 4 个扇区
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;这个对应关系必须严格匹配&lt;/strong&gt;，不匹配就会读写越界，是新手最容易出错的地方。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;对比一下三种存储器的操作单位，很好记：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;存储器&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;读单位&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;写单位&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;擦除单位&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;SPI Flash (QSPI)&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;任意字节&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;≤256B 页&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;4KB 扇区&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;SD 卡&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;512B 扇区&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;512B 扇区&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;512B 扇区&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;内部 EEPROM&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;任意字节&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;任意字节&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;—&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;sdcard-驱动库接口&#34;&gt;SDCARD 驱动库接口
&lt;/h2&gt;&lt;p&gt;ddl 库在 SDIOC 之上封装了一层 &lt;code&gt;SDCARD_xxx&lt;/code&gt; 函数（在 &lt;code&gt;sd_card.h&lt;/code&gt; 里），用起来很简单：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;函数&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;作用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;SDCARD_Init(&amp;amp;handle, &amp;amp;cfg)&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;初始化 SD 卡（内部完成一整套上电握手、识别容量）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;SDCARD_ReadBlocks(&amp;amp;handle, 起始扇区, 扇区数, 缓冲区, 超时)&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;读多个扇区&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;SDCARD_WriteBlocks(&amp;amp;handle, 起始扇区, 扇区数, 缓冲区, 超时)&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;写多个扇区&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;SDCARD_Erase(&amp;amp;handle, 起始扇区, 扇区数, 超时)&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;擦除多个扇区&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;注意每个函数最后都有个&lt;strong&gt;超时参数&lt;/strong&gt;（单位是内部循环次数/毫秒量级）。SD 卡操作可能很慢（尤其擦除），超时给太小会误判失败。示例里擦除给 20000、读写给 2000~20000。&lt;/p&gt;
&lt;p&gt;初始化用两个结构体：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;stc_sd_handle_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                 &lt;span class=&#34;c1&#34;&gt;// 卡句柄，保存卡的信息和状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SDIOCx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;M4_SDIOC1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;              &lt;span class=&#34;c1&#34;&gt;// 指定用哪个 SDIOC 单元
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;stc_sdcard_init_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stcCardInitCfg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;SdiocBusWidth4Bit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;// 4 线
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;SdiocClk50M&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;              &lt;span class=&#34;c1&#34;&gt;// 50MHz
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;SdiocHighSpeedMode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;// 高速
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;                     &lt;span class=&#34;c1&#34;&gt;// DMA 配置（NULL = 不用 DMA，走轮询）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;SDCARD_Init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcSdhandle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stcCardInitCfg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;最后那个 &lt;code&gt;NULL&lt;/code&gt; 就是 DMA 配置。传 NULL 表示&lt;strong&gt;用 CPU 轮询搬数据&lt;/strong&gt;；传 DMA 配置结构体就变成 &lt;strong&gt;DMA 传输&lt;/strong&gt;（CPU 不参与搬运，效率高得多，适合大数据量）。SDK 里有对应的 DMA 版本示例。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;本章示例&#34;&gt;本章示例
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;示例&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;学到什么&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;a class=&#34;link&#34; href=&#34;../sdioc_read_write/&#34; &gt;SD 卡读写：擦除、写入、读回校验&lt;/a&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;SDIOC 引脚配置、4 线高速初始化、扇区读写、擦除后数据验证、&lt;code&gt;memcmp&lt;/code&gt; 校验&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;SDIOC 是 HC32F460 驱动 SD/TF 卡的硬件控制器，有两个单元。&lt;/li&gt;
&lt;li&gt;引脚：&lt;strong&gt;CK + CMD + D0~D3&lt;/strong&gt;（4 线），复用为 &lt;code&gt;Func_Sdio&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4 线 + 高速（50MHz）&lt;/strong&gt; 是性能最优组合。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SD 卡按 512 字节扇区读写&lt;/strong&gt;，缓冲区大小必须是 512 的整数倍，且和扇区数严格对应。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;SDCARD_Init&lt;/code&gt; / &lt;code&gt;ReadBlocks&lt;/code&gt; / &lt;code&gt;WriteBlocks&lt;/code&gt; / &lt;code&gt;Erase&lt;/code&gt; 四个函数即可，每个都带超时参数。&lt;/li&gt;
&lt;li&gt;传 &lt;code&gt;NULL&lt;/code&gt; 走轮询，传 DMA 配置走 DMA（大数据量首选）。&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
