|
概述 本例程主要讲解如何对芯片自带Flash进行读写,用芯片内部Flash可以对一些需要断电保存的数据进行保存,无需加外部得存储芯片,本例程采用的是STM32F030R8T6,64K大小的Flash。 ) E/ T- ?. J# A! T
硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:
- v! o0 G) h: ] {7 k/ |4 A; e3 j
3 I$ e+ G: q: L |0 Y- J7 [# Z
( t. N l9 Z7 s1 F3 w7 N选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
2 e Y; e2 C# V4 E
/ I3 b5 W* [; K: q2 y1 R+ t6 M3 @6 t
配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:$ ^ ]0 \$ m: _4 }' t
' e- P4 C% {; o) T+ @
配置时钟树 STM32F0的最高主频到48M,所以配置48即可:' S) u* k. ]8 ]" P
0 L( z a* `, e" |2 k2 ^
" D$ ]9 j e9 m1 s# P8 @- i* U
z& y) `! x# y8 l9 ?8 A+ C
串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。
; a7 E- y) u$ }9 Q1 U( w9 B- w
7 l1 A1 ]3 d! T# T/ p5 z% |
9 [, \6 a0 Z: N8 h生成工程设置 注意在生产工程设置中不能出现中文,不然会报错。
) \" K& I- u, @ ! d! Y6 w' U8 O
3 m- E4 F( h/ Z. d/ F9 y 生成代码
/ v5 O5 E$ s3 b' ~7 F, w+ W* T( D6 b; B5 t7 e- o7 x
配置keil- q2 W. x: T8 z8 r2 `3 N8 J: M
! F- Y9 P( F% ]9 ]. \" ]& g4 L
在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。 - /* USER CODE BEGIN Includes */
2 i) \' _0 E( h2 @! t - #include "stdio.h"* x T7 A# n+ n- |% U
- /* USER CODE END Includes */
复制代码
4 x3 e8 H# Z0 T& D( p' K" J 函数声明和串口重定向: - /* USER CODE BEGIN PV */
% I- n9 p$ \. l( e9 `- t2 ~ - void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr);//flash写函数
# w% ~2 p7 T' |% r u/ k2 D' H9 E, Z - void PrintFlashTest(uint32_t L,uint32_t addr);//flash读取
0 F/ i0 X$ G* l) a! i8 O; r - #ifdef __GNUC__
# k, J" u3 z8 i7 w7 }8 @ - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)/ c" V% }1 H& w% m) j- v9 p
- #else
) A& F5 M f* v( W - #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
# x; Z9 H+ B7 P0 B% Y - #endif /* __GNUC__ */
7 ^9 C. T3 C4 N - / C. k& Z0 r6 U! U
, i9 _3 P0 Y/ ?( y3 D) l1 B8 i- int fputc(int ch, FILE *f)
2 P) q6 ?! T1 s3 h9 H - {
7 b3 ^2 y4 Z) [( y+ R" y - HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1, 0xFFFF);$ w% B/ l( b& o: U7 [! d
- return ch;
U6 N) l4 v9 u0 f5 z0 D - }
% m! H4 @! D' Y* `9 H: f e - /* USER CODE END PV */
复制代码 7 P& t' _( B; O- e7 P
变量定义: - /* USER CODE BEGIN 0 */
, i& f# s# r. v6 [& F - uint32_t WriteFlashData[3] = {0x11111111,0x22222222,0x33333333};//数据
1 }+ G+ Y4 W# E/ B' ~' z - uint32_t addr = 0x08007000;5 p/ ?. e; v: N" W" ]
- /* USER CODE END 0 */
复制代码 如果要对FLASH进行写入数据,需要执行以下四步: 1. 解锁FLASH 2. 擦除FLASH 3. 写入FLASH 4. 锁住FLASH 擦除只能是按页或者整块擦除。 - g+ X6 u; C9 J! N
STM32F030芯片内部的Flash存储器内存分布如下:
6 ?3 T; @, Y. N$ n; f5 b6 B+ _2 c$ o1 L
STM32F030R8T6的Flash容量是64KB,所以只有63页,每页1KB。 我们可以写入到页60中,即0x08007000-0x080073FF中。 由于单片机是32位,故连续写入多个uint32_t的数据时,地址应该依次增加4。 - /* USER CODE BEGIN 4 */$ }* F; T' _9 ?1 c: \7 z, e
) G- o' C q# k, }( l/ e- /*FLASH写入程序*/7 w& W' ^) m6 f. H3 D$ B1 e
- void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr)' y+ d0 t2 B3 I
- {2 {$ r- V% _' |2 H
- uint32_t i=0;
X& c" Z# V* r. l - /* 1/4解锁FLASH*/
* A% n) H% R+ }1 X. v8 T - HAL_FLASH_Unlock();
9 `! e9 ]: g0 y" u2 v' F - /* 2/4擦除FLASH*/
( Q# i. ^: _4 o/ T# S0 u - /*初始化FLASH_EraseInitTypeDef*/! _, r+ c. c1 E. A, y3 r1 p2 q
- /*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*/$ a0 r7 G& k% U4 A6 J! L
- /*擦除页数*/
) A; ^( V; a0 d! U0 I" \ - /*擦除地址*/
+ U! i. S8 B9 f K - FLASH_EraseInitTypeDef FlashSet;2 x9 {( U' J# Y9 r+ L
- FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;
. N# H( V7 z3 e! q6 q, e- n& u - FlashSet.PageAddress = addr;
! B/ w0 _8 r# ~ q - FlashSet.NbPages = 1;
/ I- r$ P" q- @5 {" Q3 X/ B - /*设置PageError,调用擦除函数*/5 M. a! M; b) R3 O& P: w2 F, V
- uint32_t PageError = 0;
+ H* o8 w7 m$ K6 u - HAL_FLASHEx_Erase(&FlashSet, &PageError);- f0 p t$ A3 r
- /* 3/4对FLASH烧写*/( P) o0 r* k& ^, a8 K9 C: |
- for(i=0;i<L;i++) E3 ]! g% X/ M+ C( _, v
- {
5 u" H" M9 a0 v; c5 x4 H) K - HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr+4*i, Data[i]);/ S; |* @+ x. f' a8 V( y: H
- }
+ U r L6 l, m! @+ Z - /* 4/4锁住FLASH*/. d) r# Q0 s& M1 H2 N+ `
- HAL_FLASH_Lock();+ \1 D# e+ G, R# W* i# s; _
- }! e6 ~0 C# {- P1 T' U$ g6 f
# h1 Z, ^9 z* h( Q' v- 9 u' ?: A4 ]: X
- /*FLASH读取打印程序*/
, Z+ O# Z6 k# P/ ?5 q7 l0 W) z - void PrintFlashTest(uint32_t L,uint32_t addr)8 b4 U8 i4 X* t% [. i
- {' ]. l8 j* y2 X7 P# h0 I
- uint32_t i=0;
( e D1 C7 s. h; s - for(i=0;i<L;i++)) x5 A) t# ]) a$ y
- {7 v9 ~5 P$ f, I n: L
- printf("\naddr is:0x%x, data is:0x%x", addr+i*4, *(__IO uint32_t*)(addr+i*4));
% [3 R6 Q8 \/ f# @6 B - }
) Q; ]6 w; d# ~. O, d M2 P0 M0 h -
1 B9 f( z; ~( @$ ]) x. a - }
( M+ v( U; X- S2 X) a: k4 R& \. k - /* USER CODE END 4 */
复制代码
: [: W* }0 S, X- O4 H: _ 主程序 - /* USER CODE BEGIN WHILE */
) C0 M" F/ K; U - while (1)
5 u: `* M, X W9 M5 B - {
* [7 d/ ^4 W# s6 _ - /* USER CODE END WHILE */
7 Q3 z) F B3 M+ J3 g$ F1 q - ' c! T0 ~- N' J1 V7 x( v$ m
- /* USER CODE BEGIN 3 */
! V) o6 B! u8 w - WriteFlashTest(3,WriteFlashData,addr);9 {5 T) b" W1 w* X8 r; [, \
- PrintFlashTest(3,addr);0 M5 m# |6 |2 f! R8 O( V
- HAL_Delay(5000);
4 R# q+ d. v' b* ?! @" q% A+ R - }$ V. m/ H2 f4 i; \; u* V
- /* USER CODE END 3 */
复制代码 ) K: h0 U/ k% `3 h
演示效果 7 @; n# Y6 o" C' x
" s1 g, ~0 v1 `9 _
: K* p: h! F$ d( Q0 ]1 A, l6 z i) @ q, O1 u s9 z, D
|