|
概述 本例程主要讲解如何对芯片自带Flash进行读写,用芯片内部Flash可以对一些需要断电保存的数据进行保存,无需加外部得存储芯片,本例程采用的是STM32F030R8T6,64K大小的Flash。 4 u7 D8 o7 G4 s5 t% `! D6 E
硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板: ! E, T( p5 J* J) s- S, D% i* {
+ H8 t1 i" l$ |9 _* L& _2 u
3 v M$ F1 w; G! n
选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
6 A% B. R3 S6 h: K0 {; ~
$ T$ k; W, \6 A9 I, C; {% a
配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:
( E2 E' x, \* V4 m 6 g; C/ h# ~$ N; v
配置时钟树 STM32F0的最高主频到48M,所以配置48即可:* w; G5 I' I' V
; U8 p0 a2 R3 Z- @
* W0 O6 X, p" Y, D- F# W1 r5 {
" }, F% P: I q3 ~' v- O! n* a( {串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。5 w& a; c9 O$ A5 {, O
$ k2 u3 G" H0 m8 `& Y7 V% h- P F( f" l' U3 g" r- G1 _' L4 A( P
生成工程设置 注意在生产工程设置中不能出现中文,不然会报错。
% D4 e4 N. x9 T# f1 X4 T; w; ?
6 T! O0 \, C, \& e! N
! R$ v; |8 W8 d8 D) ^' H* v, _* h
生成代码; R: L' q8 u, `4 {( l9 ~9 A) J9 u
) x0 x+ U4 U, {. d& k" C& ^
配置keil
$ f7 r5 K9 f9 a9 p- \& {$ h$ E
" k) ]. |/ E4 h m4 e 在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。 - /* USER CODE BEGIN Includes */+ ~9 V2 ^+ u8 }. J
- #include "stdio.h"
6 u3 C5 s9 L j6 g9 P, X - /* USER CODE END Includes */
复制代码
: l4 w" t2 B: p) H8 z4 f" C7 A 函数声明和串口重定向: - /* USER CODE BEGIN PV */
# n$ G5 K$ X( u5 } - void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr);//flash写函数7 i7 Q- z' {6 l% g* P l. H( G. {
- void PrintFlashTest(uint32_t L,uint32_t addr);//flash读取
/ n; V" Q, ]: W" B" _ - #ifdef __GNUC__
2 Z) i5 Y7 @+ S4 y - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
6 T* Q' k& \" T; e+ _; a - #else
; E8 Q. T; D" e# c- F - #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)2 h- {- y% g4 U2 S5 L, s
- #endif /* __GNUC__ */
* {, [2 M. O4 q$ w
4 o, y8 f% T! ?( L! N$ d0 g0 F8 C- \- 4 V* |: w! R; }1 f4 f. J, R' G
- int fputc(int ch, FILE *f)
' p( F# _. w2 w' j* ` - {
~2 }! e$ j+ I - HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1, 0xFFFF);
% @! z1 G' X$ q) }/ L Q+ U - return ch;" p5 t/ A% H2 z6 r7 y, T: i z+ M; v
- }
# w) Y+ F& V4 O5 X9 A+ W - /* USER CODE END PV */
复制代码 # U L. D9 o( D$ K8 k4 s5 y
变量定义: - /* USER CODE BEGIN 0 */( ^# p. i7 s# x
- uint32_t WriteFlashData[3] = {0x11111111,0x22222222,0x33333333};//数据7 [0 F% m% H5 o. {9 U
- uint32_t addr = 0x08007000;
' A6 {3 z2 r' [0 U- k4 } - /* USER CODE END 0 */
复制代码 如果要对FLASH进行写入数据,需要执行以下四步: 1. 解锁FLASH 2. 擦除FLASH 3. 写入FLASH 4. 锁住FLASH 擦除只能是按页或者整块擦除。 ! J/ A& ]8 i& `) O3 @- X) G
STM32F030芯片内部的Flash存储器内存分布如下:
$ A R5 S: t q8 A d0 A7 ~. I5 @3 Y% p, o# e6 y$ P5 m
STM32F030R8T6的Flash容量是64KB,所以只有63页,每页1KB。 我们可以写入到页60中,即0x08007000-0x080073FF中。 由于单片机是32位,故连续写入多个uint32_t的数据时,地址应该依次增加4。 - /* USER CODE BEGIN 4 */
" S N8 S1 R' j* Q6 \: V. P4 x4 r
5 |7 K6 O' g2 h7 y$ X6 Q1 z1 z- /*FLASH写入程序*/) Z" \2 N. [* E8 K
- void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr)
5 y O: P) d" K3 T# { - {7 A I3 e9 N, p, G0 Q
- uint32_t i=0;) x8 \/ u3 y) H- V$ V, b; e
- /* 1/4解锁FLASH*/+ S v" l v( U4 N- U1 I% a
- HAL_FLASH_Unlock();
& p4 g y5 ]9 E1 C - /* 2/4擦除FLASH*/6 C' q' r- a7 w7 ]5 V7 s( O2 p' N {
- /*初始化FLASH_EraseInitTypeDef*/' O4 {: e1 ~7 B$ |
- /*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*/4 [5 Y# _7 p& W4 i. C* j) r6 b. m
- /*擦除页数*/
1 }: z6 x0 ?/ _+ G5 g# q/ { - /*擦除地址*/
5 A' u1 D$ O/ v9 Z3 Y5 Q - FLASH_EraseInitTypeDef FlashSet;. m8 i; m9 J% c/ I, I
- FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;* R( j4 J- \# V% |7 u* f
- FlashSet.PageAddress = addr;4 Z' l/ J% P1 a# k3 }% f0 [
- FlashSet.NbPages = 1;
* ~, a( `9 X. S; d8 f r - /*设置PageError,调用擦除函数*/, ]7 ?( E/ x/ Y1 A- i
- uint32_t PageError = 0;) H1 s# K# j. X# W: {% W% n
- HAL_FLASHEx_Erase(&FlashSet, &PageError);) Z" r5 L" S9 k
- /* 3/4对FLASH烧写*/
" a7 s$ M& J5 \) r6 ?% L7 ? - for(i=0;i<L;i++)
( }0 A' O% Q+ H6 Z( O) T7 S1 { - {
. [5 k1 k9 t9 l+ | - HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr+4*i, Data[i]);
( d3 z2 G) k- P6 l3 o- Z - }
8 u$ \4 n) _. l9 j5 ?! l% Z3 O4 o - /* 4/4锁住FLASH*/
- Z1 V( e! h6 f8 y0 \ - HAL_FLASH_Lock();
4 A3 f# s% d$ Z. } - }
. I+ A& `7 \- H - * v2 a& n$ l$ r5 b9 ^* P Q
2 i- b9 M- x m5 F- /*FLASH读取打印程序*/$ t& e% n5 L- C2 y" E
- void PrintFlashTest(uint32_t L,uint32_t addr)) \5 Y2 I4 l% q! b
- {
2 Q1 X+ ]! F0 d* P! I0 U - uint32_t i=0;
5 o; G9 ], [% U) _ - for(i=0;i<L;i++)5 m) V$ E6 {6 w5 g ]# B, ~% n8 c
- {
* x: k- P, G3 f5 |' M - printf("\naddr is:0x%x, data is:0x%x", addr+i*4, *(__IO uint32_t*)(addr+i*4));) R2 H' d$ k4 @2 P, e& }
- }
) o$ |, q- L; B, ~1 K- {' @2 Z - / X8 ~$ a" d2 O
- }
6 H! d% c' u X( u: z5 X - /* USER CODE END 4 */
复制代码
. E5 ^9 ^ v/ B, u8 m4 E 主程序 - /* USER CODE BEGIN WHILE */$ k; }4 z6 v8 r
- while (1)
4 K' |0 O' r1 u0 j' _. n - {8 M$ a3 `( e+ ~) P) D
- /* USER CODE END WHILE */' P0 r, N* S8 C/ g
' H5 v& f( u$ L+ M- /* USER CODE BEGIN 3 */ # Y3 U, }" Z5 k: C4 g
- WriteFlashTest(3,WriteFlashData,addr);& D3 l8 o9 N& _8 R* |, H' _
- PrintFlashTest(3,addr);
/ L& V$ H2 c! }3 }+ {9 x I+ X7 w/ O - HAL_Delay(5000);
4 K; Y/ ?% j8 e3 J+ \ - }
! M( w3 J6 U1 K) O! i4 R - /* USER CODE END 3 */
复制代码
/ b6 _8 x6 P' ?! ], @! C" ?% D- R演示效果
" r+ G8 R8 g o% H4 o1 N
* S8 u0 {/ A9 B9 g( v
$ a: ]7 Q3 {+ f! J6 l& { |