一、开发板平台简介: g1 X" G; ?+ \2 V2 h0 W
1、开发板资源简介& c, _0 H$ t. ]$ x; X
(1)开发板主芯片型号:STM32L431RCT6! g) T: v7 ~" @
(2)开发板主芯片封装:LQFP-64_10x10x05P
+ t' X& _; S5 U3 _5 H* c(3)开发板主芯片内核:ARM® Cortex®-M4! q, I4 ?0 w1 {6 `
(4)开发板主芯片主频:80MHz# {1 F B$ k; c2 z) v9 i3 h( C9 ?
(5)开发板主芯片Flash大小:256KB( n! X! `- i* f0 ~! u
(6)开发板主芯片RAM大小:64KB
1 B1 T, K0 {3 P0 h; r (7)其他外设:请参考芯片手册. }; { J. a0 v% L! s
0 `( ^5 l, M: p R$ `2 W$ Q
1 N0 o$ b i8 a/ W
. `; C+ e/ l& }8 p0 S$ H
( E% g4 {: T2 @6 H" b3 j
6 b; {) S/ N: ^3 r8 W
2、串口简介7 _ b" X( ^( p4 H
串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。
2 R- Y6 _, H* Z ~& g$ z (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也试验该串口1进行。0 F* S2 @* p/ y- y2 j3 D
(2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。
& C6 E% J$ L, x% T( g
/ \+ ?7 n! a4 W 二、新建工程3 [: b( Z4 i4 n
1、新建STM32CubeMX基础工程+ ?2 v4 a7 r/ a8 l: i+ T5 q4 N" k
(1)打开STM32CubeMX,点击“File”-->"New Project"; t; g6 Z' R. _. [6 x
* s4 k8 a7 q; z9 @- w ]* j% ?1 J$ A
, A+ A8 \! E) l' F5 x/ T% Z D" N: y {
+ h" x; ]3 S5 W& r9 z) s
(2)等待打开主芯片选项界面(大约1分钟时间)。7 i# M) F* m3 R; z: h+ J* t
" X$ e, x- \0 X6 ^' k
9 b6 H' J# W& S1 U1 N; L
# ]7 [# U# g! J z- S: v) U! b- c: z0 d(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处现在STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
7 z6 U5 |5 J% r) t
" n) x8 d% b3 D
: g2 S0 e- k8 z/ {
; r" D) a% p- h
0 \% n, O( k% {7 J' z5 r8 t; d(4)选择时钟源。; v# l! D J- _4 V) p1 {
(1)因为开发板上有8M外部时钟,此处选择外部高速时钟(HSE)。
) K( o: M3 _0 C3 y( c& |(2)因为我们没有用到外部低速时钟(LSE),此处不做处理。
. \+ ^9 u9 ?, a }; e1 D U' {9 R) k+ h
, ? x6 m/ u! T( ~/ a
5 {+ c$ K' B' m- z; j A2、配置GPIO控制LED
& N$ ?+ i8 G$ k7 T2 J$ O, K/ q* r备注:LED灯用来指示系统是否正常工作。
+ \5 G0 Y* p7 m- D, E* X(1)查STM32L431RCT6开发板原理图得LED1控制引脚为PC0,则配置GPIO的引脚PC0。2 S. Z! ^. A$ C. F
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。* `( ]+ F$ i$ m) c: k p1 ^! G
+ H, A( m2 ^1 J' ?0 a: q; o2 s* b3 s
H' N8 a+ `* [0 {
: ^$ h% }: J/ X% P2 v! n5 K! i6 h(2)根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。, J( W) t4 F" k" u) b
8 Q+ u+ `8 p: z& K" Q( B: B
9 Z6 h5 O8 M2 e: w* @& z" Z1 N+ H2 M6 v4 C
3、设置串口1参数/ f; v1 f$ H1 l
1、查原理图得知,串口0使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:
: b8 J3 a& }# s, f7 u6 m* T
% T. M) \% a$ Z, P1 y: @
5 k( R4 [: r$ Z, n+ i4 k
9 v1 G6 F ]4 T4 J (1)序号1用来设置串口收发引脚的选择。" v" G2 M: q" X U6 A
(2)序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。
+ d0 a2 R+ Y a6 F, \3 s0 e9 E% A9 z4 B4 f1 b
4、配置SPI Flash接口& w/ P8 j) w6 B3 y4 O' M
(1)查看STM32L431RCT6开发板原理图得知,芯片原理图如下:. ^) }. N/ N' T4 L/ I& s
5 ]" H& ?5 f* m6 J9 I
. u" W6 E; D- ~* P I
: L8 C% L: Y( c0 {' M) ^4 o (2)SPI Flash接口对应芯片的PB12、 PB13、 PB14 PB15,芯片引脚配置如下:
- m% O2 b. R1 g* ~2 MPB12:SPI2_NSS,此处设置普通输出IO即可。不能配置成NSS。
; Z5 t' k7 ]" p$ ?: @. p/ XPB13:SPI2_SCK
8 y! }) {& x; WPB14:SPI2_MISO
0 m/ Q% y; k2 Q aPB15:SPI_MOSI/ e+ j/ @8 j# `8 `9 l
: X8 P4 S) v4 Q* x0 \, _' ~- @
+ V# R0 p1 S. H5 [' k- U
) L' I5 z. [( z, j8 W: O8 d, U (3)设置SPI引脚参数,并选择 Full-Duplex Master 全双工主模式,此处不开启 NSS 即不使用硬件片选信号。( t! L( k4 [# l7 \2 H
5 ^0 \ r. C% z! p. U7 q
2 U) r! \& I1 u3 J( U3 N
, X4 W) ^8 L6 [: v(4)设置SPI基础参数以及时钟。
9 m2 o+ l2 ` C q1 X9 v# s
* [1 H: V M' G6 n; ^
5 v. B$ ?1 `- l, e4 r: a0 f5 k) U: X0 O7 o! t. d
3 w4 E1 M I$ W. m! Q! T8 _3 G5 H& [ `) Y* z8 O
4、配置项目工程参数7 `# W9 F# X% R! F) C: ^9 r0 ~
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。9 p+ l3 g0 `8 U- { S) K, \
- U) F; u: o! }* b u* k c
, X; Z- e7 q% L2 H
" s$ I) y& n5 ^) P(2)完成配置工程。
5 o5 Z; a% S* O( A: q+ [ L* k备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)
6 j \, { S. _. \. P% \. n! {) Y, X4 Z
. r+ y- D+ m" C) W/ v) z! Z7 {
S) V/ s% H& v4 y& j3 O. h
4 D) i0 S5 {$ y; k5 W, S& J3 B
" X I* y6 O. g2 z8 b(3)生成代码。8 ?3 l$ {& v, F
3 C5 `% S/ ]6 Q/ ~! o$ K$ a$ i
6 y" j) B: h9 U' x2 L# l' U
7 y0 y6 }+ o( I; i! ~% v
三、在KEIL 5中编写代码5 M7 j) G0 b. W6 J
1、使用KEIL 5(MDK)打开项目工程文件3 Y8 T3 N& P4 {# r/ I
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程。% b9 D8 w# d$ g
+ X* ^8 B5 C: j3 V
8 _+ q1 ~: s/ ^. V2 A4 G/ z6 [0 e% H3 T# D6 G
(2)添加每隔500ms,LED1闪烁一次的系统提示,用于提示程序运行正常。
; W$ D5 [' j, J! y2 V0 }' Q2 ^8 Y8 N2 x9 @
: A7 j' {$ i% b: g% ~$ F; e
3 C5 R1 i* O7 Z8 _# I
2、添加使用printf函数打印log的代码! T' @7 I7 ?/ y7 d- z6 I" K9 V( j
(1)在项目选项中勾选Use Micro LIB选项,勾选该项目后,可以正常使用基本的C语言库。
- p# z7 B2 @$ ~2 J) Z
& n' u* o6 F& m3 Y& U! S' J" b
1 X) x# t5 [# z* y5 }1 N
& k1 @1 l8 q* V5 _+ }" u
(2)printf函数会调用fputs函数,fputs函数为弱定义函数,即使用__weak修饰符修饰的函数,可通过自己编写函数定义覆盖原定义,我们在此处重写fputs函数。在usart.c中添加如下代码。) e, Z& Q( c5 f$ f7 W; k6 Q
备注:开发者自己的代码需要注意添加位置,一定要放置到一对《USER CODE BEGIN和USER CODE END》之间,避免重新生成工程后被覆盖。1 X0 d/ j; b9 J+ K( q! h; {
8 W0 s- m8 F2 e2 E
3 N6 U/ i5 a6 N; N
) r& ?1 u. Q5 V; K; c 代码段如下:可直接复制使用。5 x q& B4 U$ }- B+ _: m" L* @
- /* USER CODE BEGIN 1 */' l0 H; c! K6 V: z. u
- + a, o9 O% X3 Q" |! L* C, s
- #include <stdio.h>
* W' O2 ?# i+ e - #ifdef __GNUC__* a) s1 E1 i- I) `% C1 ]% Y
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
0 Q$ Q* L. S2 T. a9 r - #else( T3 C0 S/ H. l- B/ ~7 M( k1 Q6 t
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f): R( v9 W, V2 I" M" q+ s7 o
- #endif2 [4 B) I5 d7 M" X) B
- PUTCHAR_PROTOTYPE6 Y& Y8 X( I5 b
- {, h2 q7 L0 q7 f5 u* F P: ^
- HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
$ R4 j0 o" s2 u; ?$ @ - return ch;' Q# L- r1 }6 U* j3 L5 Z
- }8 F0 x' Z" b4 @1 F
- . i0 e/ V& F; F" {; |. v
-
4 s# ^. I% } s/ r - /* USER CODE END 1 */
复制代码
; h6 R% ~4 B2 ]* r$ X9 `. i# W. C; }8 x
(3)使用printf打印log数据。需要注意main.c位置添加"stdio.h"头文件(printf的函数声明头文件)。
6 b$ V% x! ]) ]" A: X! q4 T# H- }2 ~+ L9 \
4 A. e3 Q* S( V2 U# D
" r- D1 v% k | l3 C7 W% W( u) z
- printf("hello world,this is printf function!\r\n"); //printf 打印函数
0 {/ C- t: [8 i! {5 q
复制代码
: m& i; O4 |) g1 X+ y& M' K 3、在w25qxx.c文件中添加SPI底层驱动函数
" T2 u. j/ o( I- l7 I0 p- #include "main.h"
8 S1 \' o) f: s, ] - #include "spi.h"2 @% d$ E, f3 @
- #include "w25qxx.h"
7 z/ ^; N" j( w- | - /**
3 ?6 U" {# d( @4 U3 M - * @brief SPI1 读一个字节
_+ y$ a0 S5 n: M& e' ?! ` - * @param None) L% m% K* ~! f: O+ N
- * @retval None3 L ]* n! H/ ^
- */
/ Q1 v8 q. J* b+ y - static uint8_t spi2_flash_read_byte(void)
8 _; S- A+ Y* b/ y - {5 k1 P2 o# M9 k1 E+ K. ^8 ?7 c
- uint8_t t_data, r_data;
F4 K9 |2 v$ @! h+ F! ^ - $ p1 n" Z" s \! G8 g, [) }
- if(HAL_SPI_TransmitReceive(&hspi2, &t_data, &r_data, 1, 0xFFFFFF) != HAL_OK)
' }5 a& x# d& Y2 Z - {
- G# N- b" ?/ {+ P, J7 x/ v# b - r_data = 0xff;
% d K2 x3 S* M0 b+ y - }
' L6 O. Y0 W/ t, c - return r_data; R$ V8 E% R6 e* Z
- }
: I; m& p. P/ G - /**1 H) [6 x: a4 I' s' h( h9 ?2 x
- * @brief SPI1 写一个字节
/ x- W- S* G& e" [ a - * @param byte 写入的字节% x" W2 S! n; o8 L' m' ~; t+ G) h2 u
- * @retval 写状态 0成功 1失败) z% W2 D' Q3 ^" f6 k1 g
- */( U8 P E1 x. S) B$ |
- static uint8_t spi2_flash_send_byte(uint8_t byte)* Z5 r, R% V7 ^/ k4 M
- {
7 {- o" z4 ~6 O: j9 O0 }% T - uint8_t r_data;
* I' i9 q' r4 [/ C, V+ ~ -
4 o% x2 z. k: t# d; A - if(HAL_SPI_TransmitReceive(&hspi2, &byte, &r_data, 1, 0xFFFFFF) != HAL_OK)
: Y, Q6 Q9 }2 r5 r - {
' f r$ T" D" k - return 1;
H7 k. \9 P( f% } - }! O; P' A( ~- y- }: e
- return 0;
% A4 G; U7 l( [5 d - }2 i C+ \/ s* Z
- /**. y/ T# b9 x* w6 A
- * @brief FLASH 写使能
/ L% C+ R, Z/ H8 u/ c" l - * @param None3 e5 u' A# l8 B1 V5 e( ]3 `
- * @retval None# t! k9 ~2 S$ G8 `& b
- */7 D; V! N8 |! v9 O" I# H6 \
- static void spi2_flash_write_enable(void)& ]9 P% ]4 e4 c4 z+ A2 k, z
- {' u8 l1 B! ?$ Y+ e
- SPI_FLASH_CS_LOW();, x5 c8 S0 q% x3 N& d
- spi2_flash_send_byte(W25X_WriteEnable);
! P4 e p6 y" z: }) e1 K. L( r7 c4 s" f - SPI_FLASH_CS_HIGH();
" x& M' c0 K8 J; ? - }) i3 y' }. b" `; ^
- /**
$ p6 [1 e/ c r5 P) O" x" ^- b - * @brief FLASH 等待写结束: s6 c. `8 B( }2 A7 n; y j
- * @param None
% \+ ^' P, D/ y3 B; h Z$ P4 B - * @retval None9 R) ?& Q/ E8 u# Z
- */" k! r% r$ t, H0 Q& y) l
- static void spi2_flash_wait_for_write_end(void)4 t( }( M' ?! k2 R+ d* t5 o% m4 ?6 r
- {8 W2 z0 K0 ~# n S
- uint8_t state = 0;
4 N9 W* L0 `1 q -
& d5 `% ?' s) Y - SPI_FLASH_CS_LOW();! O9 D$ o* k, G. d; n, J0 E# m
- , v3 x# z1 `; e
- spi2_flash_send_byte(W25X_ReadStatusReg);
1 y/ W# \$ ^0 s- H: t - 8 K+ @' n, K4 v4 p* Q
- do
" S$ h4 }0 H" t( u1 U. R* P - {
* ]) h1 ~9 V* ^ - state = spi2_flash_read_byte();
, l6 i; G, ~% |7 P- k# m; { - }
; J5 j: d) V0 @ u& _" u; Y - while((state & 0x01) == SET);
6 S( V9 q! }5 I2 a1 e z% G -
7 ^; r# L+ J3 z& E6 k1 @% @" Y7 J - SPI_FLASH_CS_HIGH();' b0 k c# ~# U" h
- }8 M0 p, T9 _! p
- /**
, R( x1 @. q" ?! h* R% a$ I# f5 g - * @brief FLASH 读ID
& q) q: j. E- e& B - * @param None
) k1 ~6 a' ~. A" O5 H1 ? - * @retval None. w* B- y! d0 N! q/ H9 j
- */
, s9 P9 h: C- J4 H& j. K" _ - uint32_t spi_flash_read_ID(void)! v+ d4 }" L+ f- `. N4 k% r0 F" y& M
- {# |) \) r- f- L
- uint32_t temp, temp0, temp1, temp2;6 U" e" |% i' A) o
-
! u6 z$ _+ g7 _, E4 m - SPI_FLASH_CS_LOW();
5 n ^4 k) h8 _) |, O - spi2_flash_send_byte(W25X_JedecDeviceID);
0 v `# [/ ^( w# l5 I - # }2 u3 Q4 o i0 b% I% Y
- temp0 = spi2_flash_read_byte();' t# Q# D9 K- e9 X
- temp1 = spi2_flash_read_byte();" p" l* }# {, x- `" y
- temp2 = spi2_flash_read_byte();
2 `" \; B/ w# V* A5 v; b5 ^8 \ -
: ?4 B, a9 R ?8 r7 D4 Q - SPI_FLASH_CS_HIGH();3 A0 f! S' Q' O
- & ?3 _; R+ v% R. p
- temp = (temp0 << 16) | (temp1 << 8) | temp2;; ^' p6 U4 y9 ~4 M8 I$ b
-
7 o$ P6 s! B% b - return temp;
B+ E- V$ Y& c! O, C5 ]9 E - }8 |4 j6 x; i: @ _! S8 } E
- /**; I# s5 H+ v% h
- * @brief 读FLASH9 h0 L4 v" k8 [/ v
- * @param addr 读flash的起始地址
$ R9 y. X5 |9 n8 o6 P - * @param pdata 读到的数据存放起始地址( _1 ^% l( U( m+ w3 T. F
- * pdata size 读数据大小
) p) [) c1 l$ q4 b5 \8 q - * @retval None, p& i5 M) D& O
- */
; X% A& q) _+ s- A: o - void spi2_flash_read(uint32_t addr,uint8_t *pdata, uint16_t size)
% o6 _6 A+ r/ D6 q* ^ - {
5 S5 b) z: x" e - SPI_FLASH_CS_LOW();9 t4 w7 i1 f9 E4 S) I$ K# K2 v1 D
- : z& r/ c& t% G( w5 w! F
- spi2_flash_send_byte(W25X_ReadData);
# e4 G( q& G% P. K: L% H -
$ ?& ~! m) Z* M% l* A5 C! f8 D - spi2_flash_send_byte((addr & 0xFF0000) >> 16);' P: R: Y; F( q. y# t! A9 G
- spi2_flash_send_byte((addr & 0xFF00) >> 8);6 O) J# E& {' u6 X T
- spi2_flash_send_byte(addr & 0xFF);
, v. X6 t' t6 l/ W) N! m! H! q; @* | - . Q' f/ L* D% b( G: z. K
- while (size--)% O7 Z/ V& B3 @! x6 l$ c' G. I
- {5 H- F& w, p/ R7 `: Q/ u
- *pdata = spi2_flash_read_byte();* p- f* _6 ]! D
- pdata++;
. f% U4 j7 t* s - }
5 k" r" E( B6 t; q2 L - * I: p v3 b: Q9 \& v; g3 E
- SPI_FLASH_CS_HIGH();
0 [9 n' P8 |7 j2 {8 ~# U( R - }
) p) t9 m' B$ L s+ |" m' o - /**
9 \& g! R3 i F( ` - * @brief 按页写FLASH
5 N8 F! z3 r1 C- W) ]' a - * @param addr 写入flash的起始地址: m* w/ S! b' V# `. ^
- * @param pdata 写入数据的起始地址; I4 r8 D' B) }3 ?# G2 |: I! i
- * pdata size 写数据大小
. h8 ]: ?( d% ]# g' r - * @retval None; @3 u9 u. {- |
- */* P, s( w1 v: r% f' {( t3 e
- void spi2_flash_page_write(uint32_t addr, uint8_t *pdata, uint16_t size)8 h) Y3 }* P8 L5 r7 \: c0 C$ m/ [7 m
- {
* |6 \' H* z! X) u - uint16_t i;( x' a' T+ i- k, V }) h
-
# h+ G5 y' q2 b! P0 ?8 R6 e: k$ Q; } - spi2_flash_write_enable();9 z2 f+ }, _4 C( ?* n+ F
- 1 s9 i! w& m: c; o" {
- SPI_FLASH_CS_LOW();
" ~% l# \! i7 L1 X - 2 R H9 t" G4 o, h
- spi2_flash_send_byte(W25X_PageProgram);+ h* \. G, G; X+ K" i2 N& l
- spi2_flash_send_byte((uint8_t)((addr)>>16));, g" ]! X. f3 O1 P9 f% [
- spi2_flash_send_byte((uint8_t)((addr)>>8));
0 t) g8 i. o9 Z4 Z1 P$ a+ W" Y% ^ - spi2_flash_send_byte((uint8_t)addr);
9 `6 |: B# X5 `% ]1 k -
8 u' v0 ~2 H7 |( q, ?$ s W2 S - for(i = 0; i < size; i++)
8 E6 t1 M% H7 \. W- W' E/ n' a8 h - { }9 K1 O- j7 V+ Q4 C
- spi2_flash_send_byte(pdata[i]);5 ] }2 ~ V) n. m
- }8 f- `8 _8 i7 }; v9 C2 _
- ! I* q4 D0 n# Q' z9 g* L3 Y Y
- SPI_FLASH_CS_HIGH();: v) T7 e, O4 r6 Y; V7 y
- spi2_flash_wait_for_write_end();
m9 U, Q3 B: s, X - }
' `7 s t2 }+ q - /**
4 S; q/ y$ f/ ` - * @brief 写FLASH2 [; M' E% S k% S
- * @param addr 写入flash的起始地址6 ~. ^& `" w- W
- * @param pdata 写入数据的起始地址' O6 O: P$ ]7 ~# T, ]3 \
- * pdata size 写数据大小& n) `2 P8 w8 ] ?
- * @retval None1 d- g8 ?" y/ v/ Y) _" f
- */( G" [" }. Y* B0 r1 O6 i# `
- void spi2_flash_write(uint32_t addr, uint8_t *pdata, uint32_t size)
" M% ?0 U4 v6 l z1 D/ ~ - {
# g! ?2 Z, f3 ~* U! X - uint32_t page_remain;5 L |* _( Z( ^
-
6 x% a6 P8 b- W - page_remain = 256 - addr%256;' X, j9 e% G& L9 R( t6 m4 g
- 5 ^. k p1 s6 a9 s, K
- if(size <= page_remain)
; o4 t1 Y' Z A$ c& Y - {
) C, x% F, V1 o - page_remain = size;& } ^! y6 \1 Z* E m
- }, ~1 B& C* ?* h E4 G! |- U* a0 z
- while(1)- J' r* f; f3 y$ _2 }
- {
- D a6 p' k$ T) M& | - spi2_flash_page_write(addr, pdata, page_remain);
7 y& `) w! j& m, p/ o! n7 g8 V - 6 o: |" o) l& F! C$ l9 A$ ~
- if(size == page_remain); Q8 D6 G. S( o* P( F9 D4 i
- break;; M; I& A2 U4 d% r7 I( H
- else" D4 w) \1 f/ q. T; C; Z' O# m
- {
& B* e# E; h* I- c: a1 P: O$ g - pdata += page_remain;% w: x+ h3 l2 I
- addr += page_remain;" u# j" E2 z$ R6 t3 O
-
8 k5 I) e( E" {! Y- m7 `$ V' Y! l - size -= page_remain;
7 V2 l9 g& j. j$ _( G6 j8 n - if(size > 256): U9 Z# Z( f( Z3 T3 x, q8 {
- page_remain = 256;
) P# Z6 V% e! i+ ]" w - else1 _6 ^% i3 d* F& }2 a h( a( K$ a
- page_remain = size;" j: W* ~- {( B8 u5 [ c2 D
- }
8 @' R, k# y; N. _+ E - }
8 I, P! e5 Q1 h8 m- I - }) x# y' l8 [3 X/ R) ?9 w; `
- /**
2 Z1 @: M; U' Q- P f7 X - * @brief 擦除FLASH扇区
2 [& y$ Q: N0 _5 ?) W P6 W - * @param sector_addr 扇区的起始地址
& f* c$ |/ }8 v6 K# ^. b } - * @retval None1 v$ p' q' ]3 Z, v
- */
# l+ I _* q3 f. O: m - void spi2_flash_sector_erase(uint32_t sector_addr)% O( [: x: K$ [- b* C
- {
$ Q" k& \1 ?* ]1 Z - spi2_flash_write_enable();( ?* e6 W1 e/ n
- spi2_flash_wait_for_write_end();7 \! z& ~7 P1 u) K; n4 k- ~2 r$ g
-
% F, m8 C& a+ T - SPI_FLASH_CS_LOW();( F8 K" b) l, g5 w7 P( }
- spi2_flash_send_byte(W25X_SectorErase);, E0 w' _8 R D* X/ R: q7 J4 U; K
- spi2_flash_send_byte((sector_addr & 0xFF0000) >> 16);8 M: @5 B! G9 u; `4 Q
- spi2_flash_send_byte((sector_addr & 0xFF00) >> 8);
$ @0 l2 ^9 C, }* }# @" [1 k - spi2_flash_send_byte(sector_addr & 0xFF);- X/ {" W- r1 K3 ~5 m/ V
-
4 n6 [7 m; l5 @/ B - SPI_FLASH_CS_HIGH();
: a9 `* ~7 d1 S4 W5 r -
2 Z, F9 c5 r* t6 N - spi2_flash_wait_for_write_end();
2 H0 W; G; o- W: h& h7 L; f - }
, y/ x% g) Z1 V3 V -
- {: q+ @/ I1 T+ \- T - /**
" w8 k- `: a5 Z( a, z1 k3 P8 S - * @brief 擦除FLASH块
* [' m: j9 b/ r - * @param None/ e- C6 L5 C; e
- * @retval None
' ?2 _- S- D/ r - */
5 b9 z) l: K' }/ s# \" z7 z$ M - void spi2_flash_block_erase(void)
% x4 K: K1 H/ y0 U. E, \8 f, a - {/ R! s" ], H+ X1 B; c
- spi2_flash_write_enable();, X4 x/ N* ?7 s( F" s
- 7 |+ O* G" f9 u) M. d- e6 x$ r9 d: D
- SPI_FLASH_CS_LOW();$ W$ Z5 E5 Z" G! O
- spi2_flash_send_byte(W25X_ChipErase);1 z1 `+ |" w2 R
- SPI_FLASH_CS_HIGH();# q3 S i. B/ y& C- d8 ]! `5 w) q
-
! E5 p( t; V3 Y, n - spi2_flash_wait_for_write_end();5 Y2 M0 J; R' x# B& C2 G, h J( d$ K
- }
0 `' @* N( r9 J# d -
复制代码 " ^$ h; z. s$ l2 B0 e7 e
0 P- ~0 O9 J9 e$ }% F
4、在main.c中添加功能函数* M) J/ l/ f1 f3 j- z9 B
- /**
! J5 b/ B9 x7 ^ - * @brief The application entry point.
6 \* [( R% a9 r$ j - * @retval int
: X6 C/ \' r# V/ o1 O5 h& n. \8 c - */
5 _" @5 H- g, O; Z0 b; G. J - int main(void)5 c4 N7 z) a+ j8 \/ B
- {7 R' e% {+ O( x
- /* USER CODE BEGIN 1 */1 Q3 F) s8 u- t
- uint32_t w25q_chip_id=0; //读取芯片ID/ s; M6 O G* l J. z6 o
- uint8_t onebyte_read[8]={0}; //读取的数据) J: S6 [8 u0 w0 i0 T
- uint8_t onebyte_write[8]={0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80}; //写入的数据
/ ^, @1 f1 X5 v8 u - /* USER CODE END 1 */* B; w6 {& Z- V, |/ t
-
. J) Y6 Y5 B% J -
( Q, R% q' s7 G7 \$ ~$ V - /* MCU Configuration--------------------------------------------------------*/0 j+ `6 u4 R: c& |9 X" P
- $ i0 {% a$ c' ^+ l W
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */1 ?9 h) x, W# d1 P6 _& C
- HAL_Init();
7 k" s7 b# P, c. Q8 B; ~: d/ U - 2 P* z6 H. g! }0 A. @
- /* USER CODE BEGIN Init */
" i. ~8 u: e9 _. x5 [( D& r -
) ^; [9 \% N3 B* W! d4 A - /* USER CODE END Init */- o( I7 g+ w- M/ S
- . i/ F. P, R. ]3 N; ^" t5 h
- /* Configure the system clock */
7 v" x# h) \2 v+ } - SystemClock_Config();
: I) \$ f: f6 A- b - - \! k8 X) _3 @
- /* USER CODE BEGIN SysInit */9 I* z- j* o; t* x
- 4 V6 @. }( I) O$ r( b- r0 e
- /* USER CODE END SysInit *// X- `! [# w/ Q0 a2 f' K. ^
- ( |# q5 p4 R3 Z
- /* Initialize all configured peripherals */
. n) y7 W9 |: n - MX_GPIO_Init();2 E, d3 w. _7 x( k( x0 {3 _; Z
- MX_DMA_Init();
' C$ N' L. r6 I) a9 J - MX_USART1_UART_Init();+ v% I* V# y2 _
- MX_SPI2_Init(); W: M* j6 F r9 `
- /* USER CODE BEGIN 2 */! J9 N7 H& B& A2 ]0 j% B
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET); //初始化LED13 n s! E& Y8 q+ P8 B6 T: O. i
- w25q_chip_id=spi_flash_read_ID(); //读取flash芯片ID
3 c6 S7 B, Q( k9 z& {" x% \ - HAL_Delay(100);3 p2 u7 @9 w; j
- printf("hello world,spi_flash_read_ID==0x%0x!\r\n",w25q_chip_id); //printf 芯片ID
8 ]8 [# ~, [8 r o - spi2_flash_sector_erase(0x0); //写之前需要先擦除扇区
: K4 ]' \7 p4 c8 a% V) z3 u - spi2_flash_write(0x0,onebyte_write,8); //写八个字节7 [# k: ]1 I F: x
- spi2_flash_read(0x00,onebyte_read,8); //读取写入的字节4 J* G7 U' b2 V# L* L5 a( {9 `
- /* USER CODE END 2 */
: c6 C7 i, p4 Y, ?+ f0 m8 T. M# y% ^ -
$ M! }) @" u( d: _+ e. s6 B9 d* }2 k - /* Infinite loop *// K6 V! ? _; m' J y8 J# f6 o
- /* USER CODE BEGIN WHILE */
/ R2 }3 Q! o- b0 } - while (1)
K3 j" I6 _* s0 u" Z9 o( y - {: H( v: b# c# S8 s
- /* USER CODE END WHILE */
) k5 r l" t, d( k - 9 Z, b8 }% z5 B' @; a
- /* USER CODE BEGIN 3 */3 ]3 n" G$ Q9 v' u [" \
- HAL_Delay(500);
\& F, k0 W* U+ D4 g0 T - HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0); //每隔500ms闪烁一次LED1& ?0 q' ]% n. P5 \
- printf("hello world,spi2_flash_read =0x%0x,0x%0x,0x%0x,0x%0x,0x%0x,0x%0x,0x%0x,0x%0x\r\n",onebyte_read[0],onebyte_read[1],onebyte_read[2],onebyte_read[3],onebyte_read[4],onebyte_read[5],onebyte_read[6],onebyte_read[7]); //printf . n- z6 B7 v( ]% `4 c6 s* t
-
/ a) H @" \ z$ I- E( Q' s! G$ Z - }
1 B: ]+ ?% E9 X( H- d2 }) d- w. [+ y - /* USER CODE END 3 */
: n: ~7 H T3 s1 e, D/ R2 I' ?. G - }
复制代码
7 j( c+ w* f: N# j/ Q5 J. P
4 d. j- Q5 D" y& z2 U 5、设置编程仿真下载模式" ^$ P. X6 e8 u$ n
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。
( F- S/ c2 _$ z7 X8 E9 {4 V$ U7 c
h: b/ x! I4 }
5 a# [5 |4 `) @! d% g7 p" U. C
" ^, a) L/ y; n- x5 I' v3 E+ |(2)点击Download(或者快捷键F8),即可下载程序。
; E; m8 X6 Q9 J( ^ e/ |& }* Q* n! L, \$ `; r$ t
) Y! D4 B, g! j& q8 ?2 c' R/ u9 b# O8 |& F# {7 A
(3) 如果下载程序后,没有看到LED1灯闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
- y8 B+ b% J: J1 G
; N" |3 m8 D- F6 R/ m0 n
3 R; H; } d" L2 L7 `3 ^2 C
% C7 w/ r2 ?3 B: U: T
6、查看串口printf函数打印log效果
1 R+ `0 e" E8 n/ F/ u4 o(1)设置串口助手参数为:115200、NONE、8、 1(和代码中串口初始化参数一致)。
2 f+ O' }4 l) O. j% K/ s9 N6 U(2)设置成功后,就可以看到串口打印的效果。每隔500ms闪烁LED1指示灯一次,且串口输出一个log。" S- T4 q% ?0 J4 a! u9 _: D1 o/ `$ p
' W/ \# b' E/ N
" o9 B$ T; P9 C6 ~
3 v. p$ J0 k( G3 i0 ~, C————————————————
0 D' ?' ]- y9 C版权声明:智能小屋ZYXC
" V6 j! i0 m1 W6 Z) f) ~' b2 ]7 N# m
# Z7 M! k* c' B% w& }$ d; A( Q |