|
概述 本例程主要讲解如何对芯片自带Flash进行读写,用芯片内部Flash可以对一些需要断电保存的数据进行保存,无需加外部得存储芯片,本例程采用的是STM32F030R8T6,64K大小的Flash。
+ c' ?: u- p t2 c. e 硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板: 6 N0 c' O$ m: E) p# m- s) _4 q
/ x4 P& X" x, s% }: A' J; J4 Y
3 h7 B" Y; f# J9 I选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示: 6 |- q {8 I8 t! a; h+ ]6 i0 C3 C' R
r, W3 v c8 N/ B 配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:) X' Q( F6 N x1 _) y
. E+ X, K2 k) B/ t
配置时钟树 STM32F0的最高主频到48M,所以配置48即可:5 }6 S4 f5 b! s. A* T% ]
+ A6 M" g( l8 n# N! a/ E+ s
: Y, O' S, N+ Q4 O% o
" f$ B7 ?. e P4 u. U串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。
8 `. z7 j9 Y# u1 S& M7 B7 o, H
$ F7 T7 h5 U* H# q/ x. x3 w4 ^2 z3 I" {
生成工程设置 注意在生产工程设置中不能出现中文,不然会报错。. f. A' ^* e i& I& P1 x6 R
7 p% t' B B9 m0 D9 D2 M: n9 F
% Z+ G! L7 m; b9 `. Y* z* @7 l7 u
生成代码
Y, ~" }% z. P( A1 h
/ z# s3 w8 `2 i0 V/ }. a% H q配置keil
4 y, q+ F. w" p5 w( L9 u9 K$ \. ]- T
在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。 - /* USER CODE BEGIN Includes */; x+ F5 ] r/ _* h
- #include "stdio.h"* W) O& T' b3 e( l
- /* USER CODE END Includes */
复制代码 " p2 V7 @6 h+ V; ]$ l& g9 P
函数声明和串口重定向: - /* USER CODE BEGIN PV */
( q( ?. |7 e1 b2 G# Y - void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr);//flash写函数
3 j: @3 O2 x+ x" z - void PrintFlashTest(uint32_t L,uint32_t addr);//flash读取
! y! i: D% V, c T( }1 W - #ifdef __GNUC__
2 E3 E9 A. e& Y+ G o - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) ~1 \% j% E# x, j! v
- #else7 n2 u" w' E! P
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)) v/ ^( S/ u8 @! A1 m
- #endif /* __GNUC__ */
! Y9 o7 Z, J1 W6 s- _4 `, v: ]
( ~% S2 T9 v7 u6 i
8 i5 ~( E% f% ?, ~: ]8 A- int fputc(int ch, FILE *f)
1 W3 u- G$ v. A$ G) u( @/ e - {$ ]/ p+ ^+ A ~
- HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1, 0xFFFF);4 V3 O/ z+ U% ?% n; x* g
- return ch;
+ ]% D2 x$ O$ M8 o. D7 }9 I - }
- b! Z1 H9 m3 G6 f - /* USER CODE END PV */
复制代码 " j3 B' Z5 M$ I# a
变量定义: - /* USER CODE BEGIN 0 */5 }+ G F! [* y$ O
- uint32_t WriteFlashData[3] = {0x11111111,0x22222222,0x33333333};//数据- I0 T) q2 f/ ] l6 X% ?
- uint32_t addr = 0x08007000;
* R9 O- H& l. i9 @' ?& h - /* USER CODE END 0 */
复制代码 如果要对FLASH进行写入数据,需要执行以下四步: 1. 解锁FLASH 2. 擦除FLASH 3. 写入FLASH 4. 锁住FLASH 擦除只能是按页或者整块擦除。
7 G( E& [6 ]# r: y; J3 t2 DSTM32F030芯片内部的Flash存储器内存分布如下:
" h, a7 t3 {: O& ~! ]4 ~* V( W Q N; z
STM32F030R8T6的Flash容量是64KB,所以只有63页,每页1KB。 我们可以写入到页60中,即0x08007000-0x080073FF中。 由于单片机是32位,故连续写入多个uint32_t的数据时,地址应该依次增加4。 - /* USER CODE BEGIN 4 */
# q. p6 }" b9 l4 b5 U - - {' `4 s$ ~1 m8 _) {
- /*FLASH写入程序*/
' n8 _0 H+ \8 Q" m - void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr); o7 P1 `$ o0 r( Z) S! T
- {
" w" Y: i5 I7 U! W" N# r4 ` - uint32_t i=0;
3 s3 B$ P8 m- w5 G7 p - /* 1/4解锁FLASH*/
! B# s; ?# q1 L4 ^2 ] - HAL_FLASH_Unlock();2 a( X2 X* O. L0 S+ `3 V
- /* 2/4擦除FLASH*/
: L+ p+ S8 F, p9 }' B; e% f2 J1 c2 i$ l - /*初始化FLASH_EraseInitTypeDef*/
1 Z+ L# o+ W0 k" b6 b; ?( l - /*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*/
/ ?" Y, T& T1 Z/ e, M m - /*擦除页数*/
/ S8 d' p. q/ H; o; g5 e% q5 I - /*擦除地址*/
! `; ^+ ~ i! N$ ] - FLASH_EraseInitTypeDef FlashSet;! u0 Q# ?% ^, O4 W' ]% p) @$ z
- FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;" {6 y2 o* u8 G. b7 f9 e/ P
- FlashSet.PageAddress = addr;. h5 j7 k9 b. b* n6 { U" I; o& x
- FlashSet.NbPages = 1;
+ n9 H& k0 u! ^- {6 O4 l( C1 v( t# l - /*设置PageError,调用擦除函数*/2 n$ J F& h! i1 D3 E
- uint32_t PageError = 0;) E# _/ }9 a8 C" u6 M K
- HAL_FLASHEx_Erase(&FlashSet, &PageError);1 v( x, W1 H6 X _7 R; v# F5 \
- /* 3/4对FLASH烧写*/$ k6 ^9 r6 {0 b' U
- for(i=0;i<L;i++)* p+ Z4 L+ j' {
- {; X( B. R8 r4 y
- HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr+4*i, Data[i]);
5 Y+ c: u$ @6 o- b - }
3 X/ M q: Y& p8 c$ L0 \ - /* 4/4锁住FLASH*/; n& E2 }$ ~# z+ w
- HAL_FLASH_Lock();
! d4 Q, d8 T4 n - }$ n7 i- ^) E, U! u9 e. h2 _ g
- 0 M/ k" O, O7 |" o
8 j( d* f! n5 Y) Y6 R- /*FLASH读取打印程序*/* V0 [ F' p5 W3 V7 y
- void PrintFlashTest(uint32_t L,uint32_t addr)( X6 W/ ^" G% O
- {
5 b9 U$ f8 |; R5 w - uint32_t i=0;
# I/ C& p, w( y - for(i=0;i<L;i++)
3 B- @. Z; r1 m0 M% `3 T - {
. k; |; [4 d, T) a5 m4 h - printf("\naddr is:0x%x, data is:0x%x", addr+i*4, *(__IO uint32_t*)(addr+i*4));* T& R) v- C3 r% w
- }
" W# i. v6 r$ W9 l4 v -
/ |: [9 G4 I( N: c - }+ o& u2 q7 M* Y" i* f
- /* USER CODE END 4 */
复制代码 # _5 ~. Z8 H7 W5 v
主程序 - /* USER CODE BEGIN WHILE */
$ ^; j' K' b' S7 O9 O! Y$ e1 E - while (1)
/ S7 j1 J; [* X& K - {, m1 A0 A5 N9 A- M
- /* USER CODE END WHILE */
0 ^' l5 O. o; v" ]
, d0 G9 [7 g5 F) H# f- /* USER CODE BEGIN 3 */
8 d m* p2 u; C) {4 `4 i0 v4 j' e - WriteFlashTest(3,WriteFlashData,addr);
c4 h- ?4 Y) S) `7 x) u6 W0 h - PrintFlashTest(3,addr);
$ N) k* a; U; d$ a! Z8 e/ ^, v/ y - HAL_Delay(5000);, U+ d% D; ]: v
- }
! z* Q S4 Z# `0 I; V - /* USER CODE END 3 */
复制代码 5 D1 L2 K* e( ^& k
演示效果 + q$ h+ z8 `, w, ? Z- ~3 L2 y
' J* e( W$ {3 M
/ w# u+ ~9 o r8 e4 B
* r1 d0 y: j5 \3 g5 O9 @" F; t
|