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