
本帖最后由 wjandsq 于 2015-6-25 14:12 编辑 /*; ?2 \3 a+ s6 u6 }$ ~$ p * spi2.c *! p6 c1 {5 z; }! a8 L * Created on: 2015年6月22日 * Author: WJ */ 7 _0 X+ ]1 S% c6 C+ E: D /* Includes ------------------------------------------------------------------*/ #include "stm32f10x_conf.h" 3 O: I% R( q/ q9 e #define SPI_Flash_CS_Low() {GPIO_ResetBits(GPIOC, GPIO_Pin_13);} #define SPI_Flash_CS_High() {GPIO_SetBits(GPIOC, GPIO_Pin_13);}& w- d$ W6 L1 l, B3 e5 l: J uint8_t SPI2_Rx_Buf[4096];8 N* }/ F! q' x6 N! \* ? uint8_t SPI2_Tx_Buf[4096];) K: S- O- ~: v extern uint16_t Flag_DMA_Rxd_Finished; ( m4 K1 O7 G" n: e, N: z6 I extern uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte);$ |. Y- z2 [& y8 j /** * @brief Configures the SPI2 Peripheral. * @param None2 B2 j( X% E. t2 G6 x7 G8 S2 @ * @retval None! M9 z8 m* y' l */* V2 n! {- {- ~* V2 o! I void SPI2_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure;. I* S Q7 h u: C& {- X DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;7 C& C" Y. [# Z$ K, B- X) ~( {- H/ @ 1 w4 e8 K! g5 A! G, r: n* f /* Forces or releases High Speed APB (APB2) peripheral reset --------------*/8 T3 g" q9 |) i! ^4 i% ` RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE);# t9 x7 _, ^( U T" I8 k3 m 7 H1 [$ W$ E+ x RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);+ B- g- A5 C$ C RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE); ; l# Y" H" D& i$ O Y RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);( m/ g* d" [" |, Y RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE);) C4 e/ }8 K' c; \) o5 ^ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE); @ F: P& ^+ d! P, S RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);+ j9 I" V1 \8 J/ a& l- Z /* Peripheral Clock Enable -------------------------------------------------*/ /* DMA1 clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE);: P& B. Q0 V! n9 p6 c; m1 I1 H RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* Enable GPIO clocks */+ R3 u) C1 B+ y8 P+ s) V RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);. U* z; {7 I! M: r$ ^/ N RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);! r) s( d/ T; q /* SPI GPIO Configuration --------------------------------------------------*/ /* * PB13 --> SPI1 SCK Mode: GPIO_Mode_AF_PP * PB15 --> SPI1 MOSI Write Mode: GPIO_Mode_AF_PP' F' a' ~# } r# X * PB14 --> SPI1 MISO Read Mode: GPIO_Mode_IPU * PC13 --> SPI1 CS5 `( s0 W- }/ `* j9 Y* [ */ GPIO_DeInit(GPIOB); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;- V( V6 Y3 r$ h& [! | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure);0 S& ?) ?$ r" {3 j2 y GPIO_SetBits(GPIOB, GPIO_Pin_15); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;, J3 r' G8 C- t6 o# {! I- ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_14);4 I& d6 k; y$ ]$ Y3 ~5 U GPIO_DeInit(GPIOC);3 {% c0 A" d( j$ p# W% R GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;, m4 E6 _. O3 c* a7 Q% _ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure);/ {7 | Z$ k1 I) M6 v GPIO_SetBits(GPIOC, GPIO_Pin_13); : C! D$ t* _) V$ u SPI_Cmd(SPI2, DISABLE); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;( m8 O/ u# s4 }1 ]6 O SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;3 A6 y, b2 p$ B5 l6 ` SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;6 m" N# @5 p8 W4 A7 |/ o SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;: ~* v- I* @0 _9 ] SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;6 A+ t: r8 J* g1 y SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure);# ?7 w/ S; I$ \. X if(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != RESET){ SPI_I2S_ReceiveData(SPI2);2 E5 N: s+ D: h! X2 u SPI_I2S_ClearFlag(SPI2, SPI_FLAG_CRCERR);* Z- n, \( d2 R, V } P" N1 |: y. c, m /* DMA1 Channel4 Configures for SPIS Receive */" _0 z1 X: _. ~5 B8 J: Q DMA_DeInit(DMA1_Channel4);# u6 U3 Y. C. ]- G X DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Rx_Buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 0;/ \( y3 S: {! V DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;& i8 T1 f+ J, _; g8 A+ n DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;8 }$ ]7 Q: @# _' P) p DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;9 C5 X! C7 t& ~% `8 d DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;+ h, M5 s- Q/ G3 \ DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;- z8 |5 O4 ~2 S, ` DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;- E U! ]+ i2 I3 x( j( H2 ~ DMA_Init(DMA1_Channel4, &DMA_InitStructure); if(DMA_GetITStatus(DMA1_IT_TC4)!= RESET){; K7 o: g$ B9 z7 P1 |9 Y DMA_ClearITPendingBit(DMA1_IT_TC4); }/ { U- m, Y( ? DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);4 i+ u8 c$ [5 f8 N8 }; F /* Enable DMA1 Channel4 SPI2_RX */ DMA_Cmd(DMA1_Channel4, DISABLE); & _6 O' q/ i' o8 R* r) g5 C. E /* DMA1 Channel5 Configures for SPI2 Send */ DMA_DeInit(DMA1_Channel5);# K; E; h- M1 s! Z DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Tx_Buf;3 G! v% P8 |% m5 {+ ^ DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;% }& ^. N$ T6 L Q6 T DMA_InitStructure.DMA_BufferSize = 0;% M/ m. J" D" ^5 N DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;. u- C6 i& D+ B/ R8 o1 O DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;6 k; x9 y, R. e2 c: { DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;) ]3 |- e4 I2 R+ w1 j+ ^/ z DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); if(DMA_GetITStatus(DMA1_IT_TC5)!= RESET){8 T, ]0 V$ i( j$ h5 A# U DMA_ClearITPendingBit(DMA1_IT_TC5); [& o1 X4 L7 e. S } DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);2 Q5 R- a) k x9 ]1 R% y SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); ( M& ]/ C. \ S" g0 P8 I /* Enable DMA1 Channel5 SPI1_TX */ DMA_Cmd(DMA1_Channel5, DISABLE);5 ^: V" o1 O, }/ E1 ^ : m* `* `( N0 K- p2 N6 n, @" d9 O /* Enable the DMA1_Channel4、DMA1_Channel5 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;" n2 W, I8 K! u3 Q4 Q$ u* R NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;7 v* {5 p8 u6 E, T# Q/ S NVIC_Init(&NVIC_InitStructure);, o" W; @+ J# H" z , P3 t0 }; c' `; d0 n; G% `8 R NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn; NVIC_Init(&NVIC_InitStructure);! }3 n# n7 t/ s /* Enable SPI2 */# b/ m7 W6 A( ], v l4 x SPI_Cmd(SPI2, ENABLE); }( C/ t8 U; l. \* s* ]# f /**4 ^$ G' e' M" E U& T" D * @brief SPI1_DMA_Start- O& i$ z4 i7 B+ T * @param len <= 4096 * @retval None */ void SPI2_DMA_Read_Write(uint16_t len) {3 b5 E) n' P& v! e: i; v SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);" f' W# B; V, @% o+ R! f DMA1_Channel4->CMAR = (uint32_t)SPI2_Rx_Buf; DMA1_Channel5->CMAR = (uint32_t)SPI2_Tx_Buf; DMA1_Channel4->CNDTR = len; DMA1_Channel5->CNDTR = len;& V9 ?" q0 A: x( N7 W# B5 K+ V# t8 [ DMA_Cmd(DMA1_Channel4, ENABLE); DMA_Cmd(DMA1_Channel5, ENABLE);4 X; e+ q0 e) f' k) ~/ k SPI_Cmd(SPI2, ENABLE); } + g! D" c- Y/ q: y5 v2 d4 k- g /** * @brief SPI2_Set_Speed4 }8 b" N3 q: i$ W * @param SPI2 CR1 bit 9 8 7, |3 Z1 j, k( [ * SPI_BaudRatePrescaler_2 ---> 0007 R4 S' n' y" u5 ^5 s * SPI_BaudRatePrescaler_4 ---> 001 * SPI_BaudRatePrescaler_8 ---> 010 B* R$ l( n) w2 ~ * SPI_BaudRatePrescaler_16 ---> 011 s- g' q* L* s" u' Q5 Y * SPI_BaudRatePrescaler_32 ---> 100' B2 q9 B; ~& K5 G8 B5 y2 j * SPI_BaudRatePrescaler_64 ---> 101# c% ]$ g' W; w$ H8 t7 ?9 f * SPI_BaudRatePrescaler_128 ---> 1106 J% j$ X9 k' T* I, Z* F1 k2 Y * SPI_BaudRatePrescaler_256 ---> 111 * @retval None- w1 c; q& P3 {/ w9 n */) h8 R: f& W. j8 \% w * {1 ~+ n! e9 R5 {- k: ^ void SPI2_Set_Speed(uint8_t BaudRatePrescaler) { SPI2->CR1 &= 0xFFC7; /* Clear BaudRatePrescaler Value (bit 9 8 7) */3 |. U) O% {% @1 f4 K SPI2->CR1 |= BaudRatePrescaler; SPI_Cmd(SPI2,ENABLE);- P: e9 W2 X9 k$ h" \6 S, o } 9 d2 q2 y# X5 R8 T C /**0 Y4 [/ y) D9 s- o. u1 s7 [ * @brief SPI1_Byte_Read_Write& J2 j7 @8 ~+ T R ~5 n3 ?# E/ S: q * @param None1 r2 D* G+ H# f/ \6 ]- T0 h9 } * @retval None */- N# Q' F3 R% o1 K uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte) {& \# y+ a; j# O6 R1 u! k7 k$ ]1 W // 发送一字节 while((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET); SPI2->DR = SPI_Byte; // 接收一字节 while((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET);( |) w6 W9 M( ~" H return(SPI2->DR); }$ Y5 t% D$ [- B, r5 s. J& N- H " f c8 Q0 z, J /* * Function Name : DMA1_Channel4_IRQHandler# ]! e$ O7 n& s: T4 y) z7 W * Description : None * Input : None5 j+ V. `* c+ D y4 I/ z6 ~ * Output : None * Return : None */ void DMA1_Channel4_IRQHandler(void) {) v( s: V( A7 O7 _ if (DMA_GetITStatus(DMA1_IT_TC4)) {4 D4 ?' E; Q3 ]% @% p/ M SPI_Flash_CS_High(); DMA_Cmd(DMA1_Channel4, DISABLE);+ R" r V, h7 R) O& `) _0 b DMA_ClearITPendingBit(DMA1_IT_TC4); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);9 G/ M5 @9 G4 v5 ^" a$ ~/ _ SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, DISABLE);( A2 P: P( {: T& Y4 P/ `; b) T( a) f1 R, o Flag_DMA_Rxd_Finished = 1;( M& F' m4 I& x! n6 g5 I2 K } }+ x" J! _* o/ Z, b, g /* * Function Name : DMA1_Channel5_IRQHandler2 y6 u) a6 y, x0 V% i8 Q * Description : None, A9 j; T6 R: }0 J * Input : None& w+ x* P: z4 g: c( K$ s. U. s * Output : None * Return : None# y) j: p& F, g) D */ void DMA1_Channel5_IRQHandler(void) { if (DMA_GetITStatus(DMA1_IT_TC5)) {4 M4 r9 [1 k- ]' x# q! d! x DMA_Cmd(DMA1_Channel5, DISABLE); DMA_ClearITPendingBit(DMA1_IT_TC5); } }# i9 J& s! w- H- J+ y 6 m+ S% M. v) Y R" B/ A& e9 W j |
命令字节发送和接收, 可以使用SPI2_Byte_Read_Write, 也可以使用SPI2_DMA_Read_Write,4 k2 T. H3 I9 H2 ~' b+ T% V
这里使用SPI2读写SPI_Flash, SPI2_DMA_Read_Write 可以按照下面的方法使用:# o3 i F. a2 L* A
+ [9 X/ t1 k- p
SP2_Tx_Buf_load(); // 数据装入发送缓冲
SPI2_Flash_CS_Low(); // 片选使能
SPI2_DMA_Read_Write(6); // 启动发送和接收, 在DMA传输完毕中断里片选关闭" |! D% ?3 A, h! K y( O* V( C. _
while(Flag_DMA_Rxd_Finished==0) {
// 使用DMA连续收发时, 可以利用这个空闲做一些事情
// 如果是用SPI2_Byte_Read_Write, 单字节收发就没有多少空闲时间了) J. K% ]$ L. a' K' j
;; F* B% n, R" f4 y9 S" p; g! d v, l
}; V. [8 h" }6 F) |0 P
Flag_DMA_Rxd_Finished = 0; // DMA收发完毕,标志清0
2 t8 `, F9 k) K( W' f/ h. P
研究,研究