|
概述 本例程主要讲解如何对芯片自带Flash进行读写,用芯片内部Flash可以对一些需要断电保存的数据进行保存,无需加外部得存储芯片,本例程采用的是STM32F030R8T6,64K大小的Flash。
\4 {$ i; X0 S 硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板: ; ?0 s9 g; K7 Y# W( U
4 ~9 Y6 H$ w F- {6 B) g
1 i7 d y* K/ d V选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示: 3 v( a; a. X7 _* J& ]; _# A
$ v! n% }1 s6 ^8 I; d( h
配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:
* ^$ O0 A* Y9 x5 w
1 p6 o2 k! N; Z4 i6 L/ e, W 配置时钟树 STM32F0的最高主频到48M,所以配置48即可:1 q; T# A) e+ L
) C% r8 V3 E0 @' a
* h @" v' y7 D0 I8 I% k! L5 {6 ~' J- J( ?% I
串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。8 x' v3 ]2 j a* u
* S* o) {" D ^ V( S3 |8 A- p& R
/ L& g i2 j" [& A+ q
生成工程设置 注意在生产工程设置中不能出现中文,不然会报错。6 u; R5 w& g% ?) o s
& \& N# I$ D2 s' {
3 p' q7 q7 e$ X* W6 d* Y, {
生成代码
. f( }6 `7 |9 q8 ]4 ?- M# Z, V
6 r/ i4 O) M5 j7 F; a% o5 b5 K& [6 W配置keil
& W$ P Z2 S. `1 c( h3 r! ~- Y. M: e
% h7 ? S5 M, s3 \3 e 在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。 - /* USER CODE BEGIN Includes */. z2 Z+ I: n! T5 c
- #include "stdio.h"
- y8 \$ s5 |% d( V- o0 y) v: D - /* USER CODE END Includes */
复制代码 : _2 m& p. D8 ?3 @
函数声明和串口重定向: - /* USER CODE BEGIN PV *// i; p6 |, w( Y) ~" P& v a
- void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr);//flash写函数
! ~9 E# x8 t- W+ c% v - void PrintFlashTest(uint32_t L,uint32_t addr);//flash读取
( ?0 T5 [9 @! V" [3 L7 q - #ifdef __GNUC__) a$ ]4 o, G, A4 ? p) t8 O) x
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch); j4 Y- e% G) _, w
- #else7 i; D+ B# R ~) S8 c0 U7 z
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
& X* q5 ?8 Q5 q1 X( l - #endif /* __GNUC__ */. B3 c' Y( u& Z$ i1 V- m5 R! J5 ^! A
" z0 V5 q" h* k8 W' B2 C- * M4 | R, N+ D4 }. J* }4 L0 K
- int fputc(int ch, FILE *f)8 o/ n8 B# W H1 f* S" }. j
- {: G. e/ ?1 M9 w' _* P
- HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1, 0xFFFF);7 C5 Y8 {# l* Y9 Y# y4 w
- return ch;" ]% L* k" J& w9 r+ ~ K# a
- }! Q; H7 F! e/ C6 B: x- f
- /* USER CODE END PV */
复制代码 7 Y, R2 j% f* p* c& [: q* i" y& w
变量定义: - /* USER CODE BEGIN 0 */2 `* t! s& x7 J; O4 |; f, t7 h: f3 u
- uint32_t WriteFlashData[3] = {0x11111111,0x22222222,0x33333333};//数据6 h4 w# T% o( T+ M7 F1 ^& I8 J
- uint32_t addr = 0x08007000;
" H8 g$ o+ f7 L6 d( y- s' d6 {" h - /* USER CODE END 0 */
复制代码 如果要对FLASH进行写入数据,需要执行以下四步: 1. 解锁FLASH 2. 擦除FLASH 3. 写入FLASH 4. 锁住FLASH 擦除只能是按页或者整块擦除。
8 W% l; c/ _$ W* W4 Q. p5 JSTM32F030芯片内部的Flash存储器内存分布如下: ! i, ]. m2 l/ t- p3 r; p( r1 p$ e. p
, ~) i L: V4 U7 {) h STM32F030R8T6的Flash容量是64KB,所以只有63页,每页1KB。 我们可以写入到页60中,即0x08007000-0x080073FF中。 由于单片机是32位,故连续写入多个uint32_t的数据时,地址应该依次增加4。 - /* USER CODE BEGIN 4 */
9 Y; U" k5 y- u3 T! ~ - " e9 d: _2 x! ?: n& M+ |
- /*FLASH写入程序*/4 p; w& j4 d, U5 l) x5 v3 @
- void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr)
: F3 w3 K6 |2 G - {
$ K }% Q) {/ A. y - uint32_t i=0;, ?. G' T! { ?
- /* 1/4解锁FLASH*/
* x' P7 O7 Y9 U) @0 @) { - HAL_FLASH_Unlock();
& I& K1 G9 f ]9 X - /* 2/4擦除FLASH*/1 x( _, I& ]$ t$ p. L9 E* S% H+ J
- /*初始化FLASH_EraseInitTypeDef*/1 y; t x4 ?1 G5 i" ~
- /*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*/
/ U, f, \3 t1 [7 A - /*擦除页数*/
0 C2 @' K+ s2 R8 x3 G2 J" k - /*擦除地址*/
- W2 L( B( C. p3 \; @$ z+ y - FLASH_EraseInitTypeDef FlashSet;
" j! F {! L7 q - FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;1 g2 y* k/ `; b0 k: i. z0 }
- FlashSet.PageAddress = addr;
0 k% D8 k' [7 C5 V2 g - FlashSet.NbPages = 1;$ a0 f! K3 R' W' x- ?
- /*设置PageError,调用擦除函数*/' f6 E& k+ V0 l0 `4 ?/ u2 j" s( }6 T
- uint32_t PageError = 0;
* y5 }4 w0 w" B! J6 `: N0 A4 B - HAL_FLASHEx_Erase(&FlashSet, &PageError);
) D* U, A% b1 f( ~ - /* 3/4对FLASH烧写*/
4 m6 r6 `* f2 d$ G7 b' z5 } - for(i=0;i<L;i++)& I! a+ P0 F, P% e( j; X* \
- {! _9 J3 b2 {0 }
- HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr+4*i, Data[i]);; H0 h5 I! X) P$ q0 q* _& h, @) L
- }
1 N% e. i( B, N" c0 J* C - /* 4/4锁住FLASH*/
) Q; W# m7 K ~7 u T - HAL_FLASH_Lock();- s+ O4 F1 [* S, S
- }8 V( @- I5 {! w( x2 w
2 ?+ N: w5 v" |
+ d% w, l0 b: ?1 w4 U; ^7 e- `- /*FLASH读取打印程序*/; D& O5 h g# N, O1 b# \
- void PrintFlashTest(uint32_t L,uint32_t addr)
) ?) Z5 N' W- P. L' |) K - {
0 ]$ |- w4 i+ }6 d' g - uint32_t i=0;
5 W. ]4 n F* W, ^ - for(i=0;i<L;i++)3 W3 M, M- `2 h4 U- K; N( y% R0 L7 p
- {
' S# j! ?8 t& L; W) R0 Q$ W* X3 V - printf("\naddr is:0x%x, data is:0x%x", addr+i*4, *(__IO uint32_t*)(addr+i*4));; F8 w, w z7 H& i
- } l! l. }. w9 i' K' v# q3 z
-
E; ~; r( a" F! B - }4 o7 o* `9 E1 Q6 @8 y# P. C$ m
- /* USER CODE END 4 */
复制代码 0 y# C/ Z( J" s
主程序 - /* USER CODE BEGIN WHILE */
- _ z( k4 f4 C) S% ? - while (1)
9 P+ W2 C$ a4 g$ H! j$ U6 p - {
: Q" e4 k9 Q8 V3 W0 ]5 |5 k - /* USER CODE END WHILE */6 }8 {& _' a4 c& K& ?5 Z; Z% m
- ' t$ U' v* i4 l* N5 o/ l* v, p
- /* USER CODE BEGIN 3 */ / I8 p; g/ K8 x
- WriteFlashTest(3,WriteFlashData,addr);; U3 F j b0 t- O) j ^! K! p5 z
- PrintFlashTest(3,addr);
$ ^% i; @* R' v1 ^5 j+ f - HAL_Delay(5000);
, Q6 `9 ?- u% Z8 y0 ?1 C - }
& G; z, @, g9 w6 Z: K1 i - /* USER CODE END 3 */
复制代码
9 U/ J) u9 W- U" e演示效果
. ^5 x1 z' \. E4 [ `
/ k( G+ u K3 k) e# \
! @& F9 r2 s y- \, ?5 I |