
本帖最后由 wjandsq 于 2015-6-25 14:12 编辑 /* * spi2.c% F5 s8 Y: M2 H+ y3 h *8 ~/ u# Y4 U0 P' H5 n% I8 C0 O * Created on: 2015年6月22日9 p8 k1 P* \3 p2 _' O4 E * Author: WJ2 D, y1 Q0 S* a: X, N$ l; Z */) b9 z7 [3 A; r3 U/ c7 C /* Includes ------------------------------------------------------------------*/ #include "stm32f10x_conf.h"& s* K/ Q1 \8 {) w& d #define SPI_Flash_CS_Low() {GPIO_ResetBits(GPIOC, GPIO_Pin_13);} #define SPI_Flash_CS_High() {GPIO_SetBits(GPIOC, GPIO_Pin_13);}, A: q0 l7 X( ?: f# M2 z( j uint8_t SPI2_Rx_Buf[4096]; uint8_t SPI2_Tx_Buf[4096]; & \4 w0 P z$ W5 W0 U2 q4 O! J extern uint16_t Flag_DMA_Rxd_Finished; 7 T1 h& K/ _! A extern uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte);1 @# v& ~9 I1 s8 R9 D /**. @. C r# q3 @7 S * @brief Configures the SPI2 Peripheral. * @param None * @retval None; q! e) X6 E9 b! r */ void SPI2_Config(void){ GPIO_InitTypeDef GPIO_InitStructure;4 S& k- L) d8 F6 A3 _; ? SPI_InitTypeDef SPI_InitStructure;! m |4 I1 s9 f- z3 b) { DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* Forces or releases High Speed APB (APB2) peripheral reset --------------*/ RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE);7 H' z1 Q1 ^7 C" I RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE); % h" Y: l5 A, J: l, E$ ~: d/ { RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);! O5 h s5 g0 I z. [; Z RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);: Z( ]/ B: m3 f' D* ^" W; a RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);# N/ V' |: O7 L" j7 t# a RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);; V; h- z& B' P2 X; M RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE);# U& B8 }6 z9 }. ? RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE); ( o4 I6 c( Q+ L RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);" e; P0 R9 j, t5 F/ v6 R4 D /* Peripheral Clock Enable -------------------------------------------------*/ /* DMA1 clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE);; r3 ~- ~% o, D- G5 d3 c; n6 a& \ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* Enable GPIO clocks */7 u- I' m& G/ b: i, q RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);" ?5 R! k! @( l6 m: N7 \1 i RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);/ N2 V/ N6 n( f Z( r7 { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); b! S( J6 H7 M! a 0 x- l) k2 h% s/ U3 x, z, ^ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); /* SPI GPIO Configuration --------------------------------------------------*/3 T4 ^! V/ k$ [3 k% O/ Y /*. v$ w _' l1 n" n" ] * PB13 --> SPI1 SCK Mode: GPIO_Mode_AF_PP* m, P! ], Q6 `( G2 d- L# j * PB15 --> SPI1 MOSI Write Mode: GPIO_Mode_AF_PP' }( ?. V) q9 o0 ` `3 t4 f * PB14 --> SPI1 MISO Read Mode: GPIO_Mode_IPU * PC13 --> SPI1 CS */ & n* i/ b/ a1 ^1 C4 U GPIO_DeInit(GPIOB); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;2 @4 i D. y8 V: o! a, w- C: @ GPIO_Init(GPIOB, &GPIO_InitStructure);- R: y) W1 C! } u) Q* |7 | GPIO_SetBits(GPIOB, GPIO_Pin_15);! I- }0 J8 ]6 W! e% ^+ a+ x GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;# E! n F: o# O1 x z0 h& b! k GPIO_Init(GPIOB, &GPIO_InitStructure);* O0 Z2 b+ g. o GPIO_SetBits(GPIOB, GPIO_Pin_14); ( L9 c" L& [9 u. p5 i# d GPIO_DeInit(GPIOC); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_SetBits(GPIOC, GPIO_Pin_13); SPI_Cmd(SPI2, DISABLE); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master;. T0 X3 t( h$ R( S' i SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;3 r5 }7 v5 e/ E' V: ?4 |# Y SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;) A% j( y8 t; E W2 a- D& s& p1 @ SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;% O3 ~6 m+ V: z SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); if(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != RESET){3 q6 C: ? {7 Y5 x. n SPI_I2S_ReceiveData(SPI2);& t, H* A, h8 V$ J/ \* `" y SPI_I2S_ClearFlag(SPI2, SPI_FLAG_CRCERR); }+ H, M, x+ a( k' D/ v' ~' Z /* DMA1 Channel4 Configures for SPIS Receive */ DMA_DeInit(DMA1_Channel4);: _8 i+ Z0 {$ e6 L- q& e2 w DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR);3 Q' q+ d% {4 Z8 [ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Rx_Buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;) W+ O& B3 w# V; o DMA_InitStructure.DMA_BufferSize = 0;2 b9 I3 c% E5 d! X% O: A8 [ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;1 O: N p9 m5 U$ S DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;5 x4 r# t0 x) @' K4 |# _5 v DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;4 g7 a @, U9 S+ t! f- D0 r& T DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;! F6 r! {* }+ w- ?$ ] DMA_Init(DMA1_Channel4, &DMA_InitStructure); . Z, u' N2 |/ s" ^ A. ] if(DMA_GetITStatus(DMA1_IT_TC4)!= RESET){/ r2 e' f8 q- M& H( r DMA_ClearITPendingBit(DMA1_IT_TC4);% _9 O/ L* {4 X- R, X } DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);* \6 _' x" O, Q6 O SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);. G& z5 r0 i+ w. R$ Y* D) _4 X# ? 2 o. B9 I! o% e& z: O2 o" h /* Enable DMA1 Channel4 SPI2_RX */ DMA_Cmd(DMA1_Channel4, DISABLE);! M/ {$ V- d& [7 H" m& {9 q. h1 D 4 b$ A9 Q# s, y3 r* l/ `/ ~ /* DMA1 Channel5 Configures for SPI2 Send */ DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR);0 h" u2 P6 n, ` DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Tx_Buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 0;/ ~) ~$ `- m: P1 q5 N z. K* M DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;* x1 k3 O, O0 T. x0 ]3 W DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;. s. } P6 R( s. I# r9 d DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;1 P4 Z9 Y. N! q$ b DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;' I0 V) w$ N% W G DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); 3 i; M, ?" K9 N/ H* @% G if(DMA_GetITStatus(DMA1_IT_TC5)!= RESET){ DMA_ClearITPendingBit(DMA1_IT_TC5);: {! F t; T3 i* ], u' V; y } DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);4 j) N5 Y- C/ z/ n" f3 R SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); /* Enable DMA1 Channel5 SPI1_TX */+ t, `1 X, G4 p8 Z DMA_Cmd(DMA1_Channel5, DISABLE); # E8 E$ w& [9 ]$ v* g9 i& D* Y' |2 m /* Enable the DMA1_Channel4、DMA1_Channel5 Interrupt */- i' j$ p4 }! T2 w; l) u NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;6 x! U) c+ V3 k1 q! r NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);+ `5 b! z) J. U4 L: M NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn; NVIC_Init(&NVIC_InitStructure); 9 M$ G+ o, r+ b1 A6 I /* Enable SPI2 */0 S- z! V% B' I1 H SPI_Cmd(SPI2, ENABLE); } /** * @brief SPI1_DMA_Start * @param len <= 4096 * @retval None */5 \% k8 \7 F" o' w5 o' X! u ) |6 @2 F- r2 w6 E& ^% T3 i/ F void SPI2_DMA_Read_Write(uint16_t len) {5 P: B4 Z7 b) x" f SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);+ w* \3 R$ I6 J p8 u$ z0 \% l# J DMA1_Channel4->CMAR = (uint32_t)SPI2_Rx_Buf;5 k8 z( y6 V# p- |) g0 G9 { DMA1_Channel5->CMAR = (uint32_t)SPI2_Tx_Buf; DMA1_Channel4->CNDTR = len; DMA1_Channel5->CNDTR = len;3 A- t2 m; ^7 a DMA_Cmd(DMA1_Channel4, ENABLE); DMA_Cmd(DMA1_Channel5, ENABLE); SPI_Cmd(SPI2, ENABLE);8 `1 l" U' g/ k+ t9 G8 T3 A } 0 l( l: a8 Z8 ]& B7 l# I5 c /** d# ^, o1 N: z" O. r* ^ * @brief SPI2_Set_Speed * @param SPI2 CR1 bit 9 8 7 * SPI_BaudRatePrescaler_2 ---> 000/ p( C3 M7 t, A8 E8 E2 k * SPI_BaudRatePrescaler_4 ---> 0018 z0 n( v' {' V' x7 }* f& k * SPI_BaudRatePrescaler_8 ---> 010 * SPI_BaudRatePrescaler_16 ---> 0118 ?! H% M+ a- x- t, P * SPI_BaudRatePrescaler_32 ---> 100 * SPI_BaudRatePrescaler_64 ---> 101 * SPI_BaudRatePrescaler_128 ---> 110# ]0 S2 Z2 n x& X' ?, g" Q# V1 L * SPI_BaudRatePrescaler_256 ---> 111 * @retval None */* s% t" W6 q' G+ u 5 E6 c( x8 Z* N( W! O void SPI2_Set_Speed(uint8_t BaudRatePrescaler) {( c* j6 f1 X4 U! p: y. Z) ? SPI2->CR1 &= 0xFFC7; /* Clear BaudRatePrescaler Value (bit 9 8 7) */ SPI2->CR1 |= BaudRatePrescaler; SPI_Cmd(SPI2,ENABLE); } /**2 Z F1 T" {2 _ * @brief SPI1_Byte_Read_Write3 X. v0 r3 |( D4 b/ s& t * @param None * @retval None */ uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte) { // 发送一字节% a5 a+ Q: p+ T( V2 M1 { while((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET); SPI2->DR = SPI_Byte;! h3 E% p. L s // 接收一字节2 p& y, q# d4 H, m- N, v' q while((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET);( z" \% R% }4 N0 o return(SPI2->DR);$ X4 i& G& i' s7 o G9 K } + ^ B5 {8 T0 X /*: j6 b t0 |. h# i' u, } * Function Name : DMA1_Channel4_IRQHandler$ Y& s$ z* l+ w * Description : None * Input : None * Output : None * Return : None' c7 v2 N( E; ?8 p5 w/ f; _2 ^ */ void DMA1_Channel4_IRQHandler(void) { if (DMA_GetITStatus(DMA1_IT_TC4)) { SPI_Flash_CS_High(); DMA_Cmd(DMA1_Channel4, DISABLE); DMA_ClearITPendingBit(DMA1_IT_TC4);2 [. {- I0 V: _' a5 a SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);4 j% v7 r" j( W6 q9 H SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, DISABLE); D0 N' i1 x, a! D Flag_DMA_Rxd_Finished = 1; }, _7 D% q8 x7 E2 G9 J2 T5 N s } /*' f, i+ m6 |5 H8 K * Function Name : DMA1_Channel5_IRQHandler" ?1 Z6 d/ O% k5 j t4 y+ m/ s* t * Description : None- m* x; f( X. `0 S * Input : None& e! m' s t( W. I* } * Output : None2 i% I( V, A' A) x * Return : None. j1 e) ?4 Q! M */ void DMA1_Channel5_IRQHandler(void) {5 B- C7 a! b6 n( q2 ?7 }6 B% ^8 {) x if (DMA_GetITStatus(DMA1_IT_TC5)) {; v, P! z+ P2 e S0 g DMA_Cmd(DMA1_Channel5, DISABLE); DMA_ClearITPendingBit(DMA1_IT_TC5);- z( R9 T2 U0 S$ R6 b- X } }: x) y% D+ p: p: h0 x( q $ d2 S! p1 j2 _0 o) { |
4 T6 X; |5 @/ j/ ^: C
命令字节发送和接收, 可以使用SPI2_Byte_Read_Write, 也可以使用SPI2_DMA_Read_Write,8 G* X3 S2 K7 C2 r5 r5 P9 N
这里使用SPI2读写SPI_Flash, SPI2_DMA_Read_Write 可以按照下面的方法使用:
SP2_Tx_Buf_load(); // 数据装入发送缓冲
SPI2_Flash_CS_Low(); // 片选使能1 J4 S9 t' }; z
SPI2_DMA_Read_Write(6); // 启动发送和接收, 在DMA传输完毕中断里片选关闭
while(Flag_DMA_Rxd_Finished==0) {2 b* C0 u& K7 k9 s& t, l0 m! z
// 使用DMA连续收发时, 可以利用这个空闲做一些事情8 H" G- t4 g( n- F" z
// 如果是用SPI2_Byte_Read_Write, 单字节收发就没有多少空闲时间了
;& m& p+ u7 k+ G- w- Y- h2 ~
}
Flag_DMA_Rxd_Finished = 0; // DMA收发完毕,标志清0$ m9 T1 }3 N3 g A, N
* z' f/ D# ?- G1 c. Y$ Q, ?+ b! \
* i1 }& n* g7 D$ [& D1 J
6 e0 |7 s; z" x6 N' x6 B
研究,研究