一、SPI 实验----I/O端口配置- T; Y) z- k' S: o, Z+ A. n7 J# s( {
在本次 SPI 实验中,STM32芯片做主控,主要使用 SPI1 功能。' a: d6 S2 W) a/ b* _% ~* m
9 s! W+ u A2 y! _& w9 U具体引脚配置如下:5 { L4 o% k/ N& q/ A; Y6 h, e4 g
% Z' z9 k; f$ K9 W$ B- F1 q' c4 T! i6 b. F' n Q# H' ~
具体引脚初始化程序如下:
% G, t0 S3 Z, ?6 {
6 d( z9 U# T* K5 n! I! O- D* q/ ^- /*
5 Q: ~& m G S# \4 ] - SPI引脚初始化配置0 v* Z% N: D; ?, G# c- \( o6 g5 ~
- **PA4------CS7 _1 e) d j, v+ P9 ?# R9 D$ z) ]; e
- **PA5------SCLK% p6 t+ K: {! N4 l- S
- **PA6------MISO. j7 ?" Q$ ~$ q7 \! D1 u. v4 \
- **PA7------MOSI
7 |4 R( Q3 _4 m7 T3 Y; J - */
; z! z8 E P. r& r- U - ( {9 ?; z# o* O. S# @
- void SPI1_GPIO_Config(void)
# D; D6 T3 U1 X: \$ {8 ?& V - {
3 w6 h0 X4 ^2 q5 G2 t: R - GPIO_InitTypeDef GPIO_InitStructure;
* m1 Y$ J: F( V& ~ ~" c: |: N - % l0 o7 L$ a, |" p' m B4 E" }
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTA时钟使能
5 H- e; |2 W4 g% X - - A9 Q- D/ J! g' k) a; V7 O
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5| GPIO_Pin_6|GPIO_Pin_7;
2 z v& c" `( v2 O8 }& } - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PA5/6/7复用推挽输出 , H' n; f6 E8 r5 h0 _3 D z
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;" A9 m3 ]+ ~! ] Q& q* t
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
1 z& H7 I2 [* N Q" G1 X: v7 _ k' g -
# f/ r% s& d# K, h- U3 { x) Z - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;8 D# b* c' q/ v& L+ G, R
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PA4推挽输出
- _7 u5 c2 |/ i9 A M - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
0 j( O3 z1 K. C - GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
! s- N1 N" h5 B
, a1 v4 h3 U) p F$ E- GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //初始上拉输出
' {- L- ?8 K/ [9 G$ v/ E( g5 C2 V - }
复制代码
. e5 E4 }( h; o V+ Z! \5 L二、SPI 实验----SPI初始化配置
; |% n' s% p9 Q9 R* U1. SPIC初始化句柄- z. |0 K9 ]8 v; T+ Z- N
具体结构体如下:+ S1 y7 r7 v K" X
! t- A" K* q3 {- s7 o! D1 k! j) J1 q
- typedef struct
' V- T* `1 A' I7 k- _* h4 X& O, i - {
, K* ~6 s0 p' C! S$ h2 T! a7 ` - uint16_t SPI_Direction; //设置SPI通信方式:半双工,全双工,串行发送和串行接收。
$ x: h, e2 b: ^! q* c% `
8 ]( L% Z* Y3 s7 N5 F1 G7 n H- uint16_t SPI_Mode; //设置SPI主从模式:主机模式,从机模式。
; {( _) f+ X# c1 |" m2 {: _5 s
H; U, {: d; F# ]( z% E- uint16_t SPI_DataSize; //设置数据帧结构:8位,16位。
0 o" M2 i1 o, \+ d. @
& e( j5 U6 N0 {; ~: B* h1 B! o- uint16_t SPI_CPOL; //设置时钟极性CPOL:空闲状态低电平或者高电平。
1 @+ A8 ^$ u) a% a, K3 E" p9 J
" w! M* u( V1 b* \- uint16_t SPI_CPHA; //设置时钟相位CPHA:第一个或者第二个跳边沿采样。/ G6 P/ C. }- z
2 T* O7 Y4 h; J% w: m5 N- uint16_t SPI_NSS; //片选信号由硬件控制还是软件控制。/ {) P' h1 W9 b2 A4 Y- I0 y' t$ T( c
- 9 z5 T9 c+ S V" y
- uint16_t SPI_BaudRatePrescaler; //设置波特率预分频值:2、4、8、16、32、64、128和256。
8 S8 R+ Y4 p7 j3 k; _% i
- v! M+ X# R7 F; j: [- uint16_t SPI_FirstBit; //设置数据传输顺序:MSB高位在前、LSB低位在前。+ q; {7 w% a3 D8 j, y1 z8 x n
- ' M7 h; P q& W* O6 `8 R5 p' m
- uint16_t SPI_CRCPolynomial; //设置CRC校验多项式,提高通信可靠性,大于1即可。1 m& B1 g' D+ ]* q$ Z- L7 W
- # u- K. D3 `6 s- H: i1 F
- }SPI_InitTypeDef;
复制代码 8 q$ ~8 m" s; \1 ]4 z2 g
2. SPI初始化配置* E) k6 T3 m0 y) }' w; l% g3 x
具体如下:0 g* D0 ]- D# s- ^, W; V% w
' `# M9 h( C! C/ ?. `9 b- void SPI1_Init(void)
$ D$ t* P# r$ } j8 n# W5 A - {3 f/ P( b7 Y3 ^; @# P) ~- d6 m
- SPI1_GPIO_Config();//SPI引脚初始化配置 - o }, s+ E; f3 t; Y$ `. K
7 u9 r9 @& q. l& @- SPI_InitTypeDef SPI_InitStructure;+ Z2 E/ T) W4 R% D3 L
- , L2 p+ v; [" u& r7 l1 C |$ c6 m$ G
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );//SPI1时钟使能 , X. a1 r0 {" }5 W$ y7 F3 O8 r
- - c# B1 K* f2 j5 u9 e6 N
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//SPI设置为双线双向全双工
3 f, _: O& C. A1 i4 V; k8 i - SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//SPI设置为主机模式
/ F6 p, }; s/ ~/ w, Z- r - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//设置SPI为8位帧数据结构
~8 }% B5 i, F/ F' K: n& m1 P( j - SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平$ {. f- s8 p4 D4 `2 M+ @( q- f
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//串行同步时钟的第二个跳变沿(上升或下降)数据被采样$ q' q* a; Y5 y
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//片选信号由软件控制
" f. }' D) b# a: k P$ B - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//定义波特率预分频的值:波特率预分频值为256
- D) T. q8 ?( b) R2 ] - SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
+ z, T8 C* t6 u+ H3 B# ^, J - SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC值计算的多项式为74 L2 @3 k) s q/ a3 J
- SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
5 x/ @7 u7 `3 k# u! A, H/ C6 ^: s -
3 }) u1 A- D% Q% r- V) r - SPI_Cmd(SPI1, ENABLE); //使能SPI外设# a+ t8 q. T) d! ]0 ~6 Y6 }1 j- d* p8 [
- SPI1_ReadWriteByte(0xFF);//启动传输
+ d: F) v2 K6 H- q& _ - }
复制代码 ) h" x( ^- w4 A* `& Z
) b- {( F8 `4 q+ ^, l1 E. `: d
三、SPI 实验----SPI 读写操作5 C" t' `: N/ \$ ^& T- o, [: H
具体程序如下:
% A# y) v* H1 ] A1 l S' q7 x) h& E- v0 n
- /* C: v. t5 K G; f
- SPI的读写操作
) ^4 n2 ^: L- v - **TxData:要写入的字节
- K) ^- l2 O/ `0 X& i$ N - **返回值:读取到的字节
, X# T9 [) G' n( L2 x3 g0 `" Y - */
3 M% }: I6 ]) [3 P - * l( }6 u* s: O1 }
- uint8_t SPI1_ReadWriteByte(uint8_t TxData)
, j, |* O( R8 P6 ]" k9 \, o0 E - { . c: a5 z6 v( I$ `
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位, V/ |( b8 O# s' P9 c3 ^
- {5 ~6 h* X, @/ T \" w! c J
- //等待发送完成: }! H3 x2 R2 g: {% c
- }
0 w& [( P5 q2 k/ X& @2 a - SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据
{( i2 P+ X" A; ^4 t/ O - while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
: x' Z! I) n6 ^) l1 J) J9 N - {
+ P/ @. ^9 q. F5 z0 m+ L% M - //等待接收完成
. h( e" b& a, n7 Z3 d - }
* ~ d7 Z( |6 M y - return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
3 @. K& m0 a; q/ P - }
复制代码
9 ]4 T, `6 q+ L
& J0 I# T- o6 M9 a9 q- r8 m6 V
/ C) o+ T, K1 {* A) C# \————————————————
% N# V) Y# o/ n" s) ]版权声明:根号五
6 n c$ b" p: J0 @& @( S6 t/ I; Y; g l; |& Q
( I5 V7 O% Z0 W* o |