Flash地址空间的数据读取
创建工程
打开STM32CubeMX,创建一个工程
配置定时器
引脚配置
中断配置,将下面红线勾画的15改为0
- 调整堆栈大,将栈大小设为大于2k,因为本案例操作flash会用到:
配置时钟
之后点击创建工程即可。
修改工程
打开刚刚创建的工程文件
再此处添加一个flash.c文件。代码如下
/*
* flash.c
*
* Created: 2018-01-29
* Author: zhanglifu
*/
/*********************************************************************/
// Í·Îļþ
/*********************************************************************/
#include "flash.h"
// ²»¼ì²éµÄдÈë
// WriteAddr:ÆðʼµØÖ·
// pBuffer: Êý¾ÝÖ¸Õë
// NumToWrite:×Ö½ÚÊýÊý
void FlashWriteNoCheck( uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite )
{
uint16_t i;
for( i=0; i<NumToWrite; i+=4 )
{
while( HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, WriteAddr+i,*(uint32_t *)(pBuffer+i) ) );
}
}
extern void FLASH_PageErase(uint32_t PageAddress);
void FlashWriteBuff( const uint32_t destination_address, uint8_t *const buffer,uint32_t length )
{
uint16_t i;
uint8_t FlashBuff[FMC_SECTOR_SIZE];
uint32_t StartAddress = destination_address - destination_address%FMC_SECTOR_SIZE;
uint16_t Offset = destination_address - StartAddress;
uint8_t *pBuf = buffer;
uint32_t remaindNum = length;
HAL_StatusTypeDef status = HAL_ERROR;
// µØÖ·¼ì²é
if( (destination_address < FMC_FLASH_BASE) || ( destination_address + length >= FMC_FLASH_END) || (length <= 0) )
return;
HAL_FLASH_Unlock(); // ½âËø
do
{
// ¶Á³öÒ»Ò³Êý¾Ý
for(i=0; i < FMC_SECTOR_SIZE; i += 4 )
*(uint32_t *)(FlashBuff+i) = *(uint32_t *)(StartAddress+i);
// ÐÞ¸ÄÒª¸ÄÈëµÄÊý¾Ý
for ( i=0; (i+Offset)<FMC_SECTOR_SIZE && i< remaindNum; i++ )
*(FlashBuff+Offset+i) = *(pBuf+i);
// ²Á³ýÒ»ROWÊý¾Ý
FLASH_PageErase( StartAddress );
// HAL¿â FLASH_PageEraseÓÐBUFF,Òª¼ÓÉÏÏÂÃæÈýÐдúÂë
while( status != HAL_OK )
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
// дÈëÊý¾Ý
FlashWriteNoCheck( StartAddress,FlashBuff,FMC_SECTOR_SIZE );
// ΪÏÂÒ»Ò³×ö×¼±¸
StartAddress += FMC_SECTOR_SIZE;
remaindNum -= i;
pBuf += i;
Offset = 0;
} while( remaindNum > 0 );
HAL_FLASH_Lock(); // ÉÏËø
}
// ´ÓFLASHÖжÁÖ¸¶¨³¤¶ÈÊý¾Ý
void FlashReadBuff(const uint32_t source_address,uint8_t *const buffer,uint16_t length)
{
uint16_t i;
uint8_t Offset = 0;
uint32_t StartAddress = source_address;
uint16_t data;
// µØÖ·¼ì²â
if( source_address + length > FMC_FLASH_END ) return;
// Èç¹ûûÓжÔ16Æë
if( source_address & 1 )
{
Offset = 1;
StartAddress = source_address-1;
}
// flashµÄ²Ù×÷ÒªÇó16¶ÔÆë ×îС¶Áд²Ù×÷16¸ö±ÈÌØ
if ( Offset )
{
data = *(uint16_t *)(StartAddress);
buffer[0] = data >> 8;
StartAddress += 2;
}
for ( i = 0; i < (length-Offset); i += 2)
{
data = *(uint16_t *)(StartAddress+i);
buffer[i+Offset] = (data & 0xFF);
if ( (i+Offset) < (length - 1) )
buffer[i + Offset + 1] = (data >> 8);
}
}
再在INC文件了添加一个flash.h文件,flash.h可在下面的链接中提取。
链接:https://pan.baidu.com/s/1dn5vGVMufnqcsyRVrIvKsg
提取码:jack
添加代码
在main.c添加如下代码
此处添加 #include "flash.h"
此处添加uint8_t FlashWBuff[255];
uint8_t FlashRBuff[255];
此处添加 uint8_t i;
uint8_t FlashTest[]="Hello This is 631907030411 lan Flash Test";
此处添加 FlashWriteBuff( DEVICE_INFO_ADDRESS, FlashTest,sizeof(FlashTest) ); // дÈëÊý¾Ýµ½Flash
for(i=0;i<255;i++)
FlashWBuff[i] = i;
FlashWriteBuff( DEVICE_INFO_ADDRESS + sizeof(FlashTest), FlashWBuff,255 ); // дÈëÊý¾Ýµ½Flash
FlashReadBuff( DEVICE_INFO_ADDRESS + sizeof(FlashTest),FlashRBuff,255 ); // ´ÓFlashÖжÁÈ¡Êý
编辑工程,没有错误即可开始调试程序。
程序调试
在这里需要用到ST-link,之前我们都是用FlyMCU直接进行烧录的,但是如果我们还是像之前一样的话我们就将无法进行测试,因为这次实验的现象是将数据写进内存,并没有配置串口输出。所以我们需要用ST-link直接在Keil中观察测试结果(数据是否存储进去)。
ST-link连线:
ST-link STM32
SWCLK SWCLK
SWDIO SWDIO
GND GND
VCC VCC
View->memory windows->memory 1打开内存观察窗口,并在地址栏中输入:0x800c000,观察将要修改的flash区间区容:
View->Watch windows->Watch 1打开一个变量观察窗口,将变量FlashWBuff 和 FlashRBuff加入到 Watch 1 观察窗口:
View->Periodic Windows Update开启变量自动更新
F5,全速运行程序,可以看到数组FlashRBuff中内容与数组FlashWBuff中内容一样了:
基于片内Flash的提示音播放程序
使用Adobe Audition生成正弦波数据
创建文件
参数设置,点击
点击效果-生成-音调
修改完成点击确定
点击文件-点击导出,生成wav文件
生成wav文件之后,用UltraEdit将其打开,Ctrl+A选择全部然后右键点击选择选择范围,输入12-59列
Edit编辑->列块编辑->输入0x 一列一列加不要急。
这里借用DAC生成正弦波的例程代码
链接:百度网盘 请输入提取码
提取码:706i
将内容复制到keil文件对应的位置,在下图红框中进行替换。
使用DAC输出数字音频歌曲数据转换为模拟音频波形输出
打开我们的下好的mp3文件,先转化为wav。之后操作时一样的直接烧录就行,有条件可以听一下(我没盐)