目录
一、具体要求
1. 预备实验
1)在SD卡创建一个test-speed.txt文件,循环(不加延时)分批一次写入256字节,累计写入不少于64KB字节;然后读取此文件数据,通过串口显示出来。分析写入和读取的速率。
2)Flash地址空间的数据读取。stm32f103c8t6只有20KB 内存(RAM)供程序代码和数组变量存放,因此,针对内部Flash的总计64KB存储空间(地址从0x08000000开始),运行一次写入8KB数据,总计复位运行代码4次,将32KB数据写入Flash。并验证写入数据的正确性和读写速率。(用cubemx写stm32f103c8t6的内部Flash)
2. 基于片内Flash的提示音播放程序。
1)实验数据准备:用Adobe audition或goldwave等音频编辑软件录制“您好欢迎光临!”的几秒钟的声音(8khz采样、8bit量化编码的单声道wav格式),确保音频数据尽量小(最大不超64KB)。然后编程将其分批次写入stm32f103c8t6芯片内部flash区域。
2)数字音频还原播放任务:编程读取此段音频,分别通过 (a)stm32f103c8t6自带的DAC通道,转换为模拟音频进行播放,并用示波器观察波形,用耳机/喇叭收听,评判音乐还原效果;
提示:建议先用单音音频(比如2000Hz的正弦波)的wav数据进行实验,通过DAC或PCM音频模块能够基本还原出原始正弦波声音后,再用语音和音乐信号进行实验。
二、关于Flash
1.内存映射
stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同。
RAM起始地址是0x2000 0000,结束地址是0x2000 0000加上芯片的RAM大小。不同的芯片RAM也不同。
Flash中的内容一般用来存储代码和一些定义为const的数据,断电不丢失,
RAM可以理解为内存,用来存储代码运行时的数据,变量等等。掉电数据丢失。
STM32将外设等都映射为地址的形式,对地址的操作就是对外设的操作。
stm32的外设地址从0x4000 0000开始,可以看到在库文件中,是通过基于0x4000 0000地址的偏移量来操作寄存器以及外设的。
一般情况下,程序文件是从 0x0800 0000 地址写入,这个是STM32开始执行的地方,0x0800 0004是STM32的中断向量表的起始地址。
在使用keil进行编写程序时,其编程地址的设置一般是这样的:
程序的写入地址从0x08000000(数好零的个数)开始的,其大小为0x80000也就是512K的空间,换句话说就是告诉编译器flash的空间是从0x08000000-0x08080000,RAM的地址从0x20000000开始,大小为0x10000也就是64K的RAM。这与STM32的内存地址映射关系是对应的。
M3复位后,从0x08000004取出复位中断的地址,并且跳转到复位中断程序,中断执行完之后会跳到我们的main函数,main函数里边一般是一个死循环,进去后就不会再退出,当有中断发生的时候,M3将PC指针强制跳转回中断向量表,然后根据中断源进入对应的中断函数,执行完中断函数之后,再次返回main函数中。大致的流程就是这样。
2.内部Flash构成
STM32F103的中容量内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及大小如下:
1.主存储器:一般我们说 STM32 内部 FLASH 的时候,都是指这个主存储器区域它是存储用户应用程序的空间,芯片型号说明中的 1M FLASH、 2M FLASH 都是指这个区域的大小。与其它 FLASH 一样,在写入数据前,要先按扇区擦除,
2.系统存储区:系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动代码,它负责实现串口、 USB 以及 CAN 等 ISP 烧录功能。
3.OTP 区域:OTP(One Time Program),指的是只能写入一次的存储区域,容量为 512 字节,写入后数据就无法再更改, OTP 常用于存储应用程序的加密密钥。
4.选项字节:选项字节用于配置 FLASH 的读写保护、电源管理中的 BOR 级别、软件/硬件看门狗等功能,这部分共 32 字节。可以通过修改 FLASH 的选项控制寄存器修改。
3.对内部Flash的写入过程
1. 解锁 (固定的KEY值)
(1) 往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY1 = 0x45670123
(2) 再往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY2 = 0xCDEF89AB
2. 数据操作位数
最大操作位数会影响擦除和写入的速度,其中 64 位宽度的操作除了配置寄存器位外,还需要在 Vpp 引脚外加一个 8-9V 的电压源,且其供电间不得超过一小时,否则 FLASH可能损坏,所以 64 位宽度的操作一般是在量产时对 FLASH 写入应用程序时才使用,大部分应用场合都是用 32 位的宽度。
3. 擦除扇区
在写入新的数据前,需要先擦除存储区域, STM32 提供了扇区擦除指令和整个FLASH 擦除(批量擦除)的指令,批量擦除指令仅针对主存储区。
扇区擦除的过程如下:
(1) 检查 FLASH_SR 寄存器中的“忙碌寄存器位 BSY”,以确认当前未执行任何
Flash 操作;
(2) 在 FLASH_CR 寄存器中,将“激活扇区擦除寄存器位 SER ”置 1,并设置“扇
区编号寄存器位 SNB”,选择要擦除的扇区;
(3) 将 FLASH_CR 寄存器中的“开始擦除寄存器位 STRT ”置 1,开始擦除;
(4) 等待 BSY 位被清零时,表示擦除完成。
4. 写入数据
擦除完毕后即可写入数据,写入数据的过程并不是仅仅使用指针向地址赋值,赋值前还还需要配置一系列的寄存器,步骤如下:
(1) 检查 FLASH_SR 中的 BSY 位,以确认当前未执行任何其它的内部 Flash 操作;
(2) 将 FLASH_CR 寄存器中的 “激活编程寄存器位 PG” 置 1;
(3) 针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作;
(4) 等待 BSY 位被清零时,表示写入完成。
三、STM32的内部FLASH写入数据
这里借用别人的flash工程
链接:百度网盘 请输入提取码
提取码:pmvn
将路径stm32_Flash\Drivers\CMSIS\Device\ST\STM32F1xx\Include下的system_stm32f1xx_20190722_092746.h文件修改为system_stm32f1xx.h,否则后面编译会报错
将事先准备好的flash.c 及flash.h加入到工程中(flash.h文件放在inc文件夹下即可)
在main.c中加入如下代码
以下部分添加自定义内容
编译无误
点击Debug按钮,进入硬件仿真调试(断点已自动设置好)
点击View->memory windows->memory 1打开内存观察窗口
在地址栏中输入:0x800c000,按下回车键,观察将要修改的flash区间内容:
右击某一字符可选择显示格式,修改为Ascii
点击View->Watch windows->Watch 1打开一个变量观察窗口
把变量FlashWBuff和FlashRBuff加入到Watch 1观察窗口(右击需要添加的变量即可)
View->Periodic Windows Update开启变量自动更新,勾选即可
全速运行程序,由于缺少ST-Link,使用的是软件仿真,这里出现了错误,暂未找到解决办法。不过使用ST-Link进行硬件仿真的话应该不会出错。
四、DAC音频播放
1、使用DAC输出周期2khz的正弦波
建议先用单音音频(比如2000Hz的正弦波)的wav数据进行实验,通过DAC或PCM音频模块能够基本还原出原始正弦波声音后,再用语言/音乐信号进行实验。
下载Adobe Audition,地址:https://www.zdfans.com/html/58109.html
生成单音正弦波
点击文件—>新建—>音频文件,进行相关设置
点击效果->生成->音调,设置相关频率,然后点击确定
文件->导出->设置导出为wav文件
下载UltraEdit,链接:IDM Community Resources and Documentation
用UltraEdit打开刚才保存的wav文件
CTRL+A,接着鼠标右键,选择十六进制复制选定视图,将内容粘贴到一个新建文件中
在新建文件中,CTRL+A,接着鼠标右键,选择范围输入起始的行号和列号,确定就选中了整个我们需要的内容,复制到notepad++中
Edit编辑->列块编辑->输入0x
这里借用DAC生成正弦波的例程代码
链接:百度网盘 请输入提取码
提取码:706i
将内容复制到keil文件对应的位置,在下图红框中进行替换
之后,编译下载,看能否观察到预期的正弦波
2、使用DAC输出数字音频歌曲数据转换为模拟音频波形输出
使用Adobe Audition打开音乐
截取一段音频,右键,点击存储选取为,点击更改,配置如下
其余步骤同上
编辑好代码后,烧录,借助音频模块听听看能否还原。
这里由于手头没有音频播放模块,暂时不详述。
五、参考资料
https://www.cnblogs.com/pertor/p/9484663.html
https://www.cnblogs.com/pertor/p/9484663.html
https://blog.csdn.net/qq_46467126/article/details/122098829