关于STM32F1 的SPI 操作讲解已经很普遍了,这里分享一下STM32F1 系列 SPI3 使用DMA 发送和接收,关于SPI3 DMA发送和 接收大多数所都是在中断中 执行的,其实原理一样都需要死循环,等待数据发送完毕后在执行下一步操作。
A+ s/ g) J% u4 `$ O6 a0 Y0 I( F. A& B _
5 v# Q: H0 m9 F$ p% o. o. e& W) `9 u- // 初始化SPI3
( r* s: t d2 K4 b+ n+ c& s0 q - void SPI3_Init(void)* [" R& p! N+ K) W" |
- {1 w7 f4 |' {% Q$ E: }
- GPIO_InitTypeDef GPIO_InitStructure;6 ]& v; i4 V+ e+ F
- SPI_InitTypeDef SPI_InitStructure;9 q: ?, {, L) R1 k' f; g
- DMA_InitTypeDef DMA_InitStructure;
7 [+ d$ v: N1 }( q. N& F3 |, `* e - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
! b' a; ]) d8 d$ r - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); V1 ~2 V i9 x. `
- GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE); //禁止JTAG功能(保留SWD下载口)
0 b/ p! B( S) L& m - RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
. i- F+ \: B2 t8 t -
% F. \$ Z G. N2 v7 f' j - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;. G) C9 o% I% ]& _
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 5 \9 f9 b/ L6 Y$ }0 R" V! \
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
! L! T/ y9 B0 R0 a) S* a* j" h2 | - GPIO_Init(GPIOB, &GPIO_InitStructure);
+ I- f7 N& K2 n8 G' P -
1 p; F8 s9 l4 L% E+ D* y2 s5 E - GPIO_InitStructure.GPIO_Pin =GPIO_Pin_15; //PA15 =16 c$ W) \7 A+ d7 }$ |
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
; u( n- O4 x, _1 T+ C - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;7 z5 u3 Z$ i! t: W7 `* x) {
- GPIO_Init(GPIOA, &GPIO_InitStructure);. c9 W' z6 E( w6 m
- PAout(15)=1;
5 |8 C6 T- ^) Y* r3 |- w" [% L* d - SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;8 J5 K0 I7 V- H+ _, E
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
- t* s( l: I% T1 C. O2 `( Z* f# k, E - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
+ ?7 I" r. F( U6 y6 [7 E - SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; 3 K: J/ F( B+ M; x
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;4 _$ n# B5 |0 h8 c1 l
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;& d; P% H( n; ~
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;5 K3 V' d( G0 c: {& T6 a6 M; \5 a
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;7 }& E% G9 P O; m% K0 ?- i" F% H2 [
- SPI_InitStructure.SPI_CRCPolynomial = 7;
" h8 C2 c1 [5 i/ f0 m! ~. ] - SPI_Init(SPI3, &SPI_InitStructure);
8 W" n/ g6 X! Q% { - //使能DMA发送
8 T& a9 B+ a2 y# T8 j - DMA_DeInit(DMA2_Channel2);
4 u: F$ p: g% G: [ - DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI3->DR; 5 J7 T+ \* ]6 q4 g
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
" c/ v8 S+ p: q- E6 h, J+ d! t2 \# w - DMA_InitStructure.DMA_BufferSize = 1024;
# M3 p! d7 n; J. Y, D' |5 n - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;1 r) C* g" t5 s' d2 r% z7 r, M
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
3 @6 d1 T& S. k0 R3 N9 V3 Y - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
& a7 Q- ?9 E1 x - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
: P4 p' j4 e5 m - DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
. _8 l- x1 z/ j; q% U! U Z3 g - DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
7 k$ y1 f" `4 p6 Y - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- m0 }$ |. \+ n, a. ~' q9 X0 f - DMA_Init(DMA2_Channel2, &DMA_InitStructure); . K+ }) U! Z2 q9 B/ J
- //使能DMA接收
( {& p0 z' M0 N* L$ [; Q - DMA_DeInit(DMA2_Channel1);9 r B$ }( o% f4 Z& W9 w+ B
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI3->DR;
2 ~, Q( Q- H, F( I! \- w$ q - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;. }7 y3 [; T4 y
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;8 d# y) H6 Z; r! F
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
! |, G& E$ Y) I! w8 o) U - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;6 w6 u( Z1 x6 u h p3 O
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;* R5 e' Q1 x, t# r9 L
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;$ f2 i6 i1 j$ U: h; [
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
5 T; ^: `% G8 D - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
! f0 l8 E6 ?0 P. j0 D; G9 x - DMA_Init(DMA2_Channel1, &DMA_InitStructure);3 J/ ~6 i5 |# y0 B' l
- SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx, ENABLE);
; {! U" t3 Z Q- h; M/ g9 F$ t! f - SPI_I2S_DMACmd(SPI3,SPI_I2S_DMAReq_Tx,ENABLE);
+ r& _( T: H- V" |; \) t1 G - SPI_Cmd(SPI3, ENABLE);
3 K9 E, G5 {. A8 t9 j8 ^) Y - }
, L7 {% h6 n4 [4 `( f: J2 P - // 速度设置! W; [; }& X. C6 J/ j
- void SPI3_SetSpeed(u8 SpeedSet)
. ?+ D; g2 B( V1 I7 Y6 q& n - {! T; z. d, T, z# M4 ?7 `2 ]; M
- SPI3->CR1&=0XFFC7;
% y: N* z$ n8 [+ G" } - SPI3->CR1|=SpeedSet;) g( ?4 w! y. t% P3 b
- SPI_Cmd(SPI3,ENABLE);
* b) v0 r4 `. p+ q$ @ - } p& N& W2 ?0 w3 a4 O
- // CPU发送9 H7 F g6 b# e. |
- uint8_t SPI3_ReadWriteByte(u8 TxData)
9 b0 O* Y, c5 A6 e$ m( g( T - { ! V u" m$ e( \0 t2 F4 i
- while((SPI3->SR&1<<1)==0){; }
7 ?& \. i* h4 a: @9 c/ L2 I* y0 H* \ - SPI3->DR=TxData;
; P1 e* Y: B& L% h J2 r% t3 I5 z9 u - while((SPI3->SR&1<<0)==0){; } : C7 r/ z" o [4 g+ M4 N9 P
- while(SPI3->SR&(1<<7)){;}
6 t. X. _0 n2 s3 |- b" G1 A - return SPI3->DR;
$ H7 B, P; a! r6 M+ N6 `( x2 ? - }
1 r& h/ l* S6 J6 |- v; e0 R - // SPI3 DMA发送1 ~6 A2 v3 K# H5 ~) c( c
- void DMA_SPI3_TX(uint8_t *buffer,uint16_t len)
) T w3 x, O) _0 u - {$ a7 F/ A. @' Z2 t5 G1 }! P
- DMA2->IFCR |=(0xf<<4);
/ S1 n0 N5 ~: h" S: o V7 \# Q* z1 h - DMA2_Channel2->CNDTR=len; //设置要传输的数据长度
- }3 k w; _) k0 u' m - DMA2_Channel2->CMAR=(u32)buffer; //设置RAM缓冲区地址. P7 v6 }* _1 l5 |$ v" y
- DMA2_Channel2->CCR|=0x1;% z* n, c+ _+ Y. a1 [
- while(!(DMA2->ISR&(1<<5))){;}3 m% i! j( @9 M9 {
- while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET){;}
, X9 y: \+ v+ D. u( u - DMA2_Channel2->CCR &=(uint32_t)~0x1;
! D- E Q$ ]1 ^" m. a2 p; p - }
; T5 @+ u0 _2 Q# F+ e% P - // SPI3 DMA 接收
% l ^8 d, C8 H. b2 F6 } - void DMA_SPI3_RX(uint8_t *buffer,uint16_t len)
% A* }$ W c0 o& C. T" L! D: d9 G - {6 S- w3 v9 ~9 \/ Q9 _* C: B7 c
- SPI3->CR1|=SPI_Direction_2Lines_RxOnly;1 t" ~2 a; l+ v/ C) T
- buffer[0] = SPI3->DR;// 读取一次数据' X% ~% N$ F/ J3 u4 N$ U M
- DMA2->IFCR |=(0xf<<0);% \! Z- C4 W, C) {. a9 Z
- DMA2_Channel1->CNDTR=len; //设置要传输的数据长度
6 j& a& g! R B/ B. v1 ` K8 v- ~5 j5 g - DMA2_Channel1->CMAR=(u32)buffer; //设置RAM缓冲区地址
6 @: T, [* q" c/ u, W( T( p - DMA2_Channel1->CCR|=0x1;( R O# j) P4 x2 O
- while(!(DMA2->ISR&(1<<1))){;}
* X+ |1 K0 Y. x, V: X$ K N - DMA2_Channel1->CCR &=(uint32_t)~0x1;
' n/ D- n' q1 n - SPI3->CR1&=~SPI_Direction_2Lines_RxOnly;! f: c' w2 O; `
- }
复制代码 ; {3 h# p. \3 j0 ^' n
转载自:kensey A/ I6 f O. \; l
如有侵权请联系删除
6 x: t3 G3 e, ?6 z8 y- A2 e, |, j1 z3 K
1 E H, V/ N8 C6 Q# {1 {1 l) |$ e: V) h
0 x9 l8 y# r! F1 D; o
|