
本帖最后由 wjandsq 于 2015-6-25 14:12 编辑 /* * spi2.c *, r# X9 c+ t2 Z3 k E( N2 l * Created on: 2015年6月22日8 j2 D- k2 ^ V, N7 U2 o9 v( U * Author: WJ */ 1 }2 Z( Q0 @) p2 c- T /* Includes ------------------------------------------------------------------*/ #include "stm32f10x_conf.h" 5 A9 l* ^% W' @' s #define SPI_Flash_CS_Low() {GPIO_ResetBits(GPIOC, GPIO_Pin_13);}) P' w. h" g3 w( j0 p9 K #define SPI_Flash_CS_High() {GPIO_SetBits(GPIOC, GPIO_Pin_13);}' H8 s7 |- `1 V+ Q/ K 0 t1 V) C8 [- ?2 f" g uint8_t SPI2_Rx_Buf[4096];! q9 W& o: A6 Z uint8_t SPI2_Tx_Buf[4096]; ( {8 j. v; X; _+ m0 [ extern uint16_t Flag_DMA_Rxd_Finished;0 ]. W/ M3 F l8 U- L2 ]% y extern uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte); /**! |2 |5 {% O5 o5 F% L * @brief Configures the SPI2 Peripheral.8 i8 Y1 a7 B9 V. c/ y4 {1 C# t * @param None, B& v% q, X1 u# n: s g! K+ X, D& I * @retval None */ void SPI2_Config(void){ GPIO_InitTypeDef GPIO_InitStructure;+ B0 b S! U$ m( S7 U2 t1 o SPI_InitTypeDef SPI_InitStructure; DMA_InitTypeDef DMA_InitStructure;2 r, F% N1 p2 \% X NVIC_InitTypeDef NVIC_InitStructure; /* Forces or releases High Speed APB (APB2) peripheral reset --------------*/ RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE);0 u; M( c. g- T5 x9 T# _& M' ]3 B RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE);) l; P, y# p, ^& q/ X* @ 0 c4 G* [. T- t RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);. X8 X! B0 Q v8 E/ V RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);8 y7 `4 G4 y0 w# x. ]2 |0 D5 { RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE);1 l" O0 e" X7 T1 S! Y RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);4 x' ]. f: S/ j% _8 V: o. o RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);! a/ \2 k I; V2 g0 P" z /* Peripheral Clock Enable -------------------------------------------------*/ /* DMA1 clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* Enable GPIO clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);' @: V3 @ a% y- T7 K3 w- p* B0 L2 ` RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);# e( f$ J! i6 P( H* }( W8 y /* SPI GPIO Configuration --------------------------------------------------*/1 C. a5 n7 v4 J( l7 t0 M" k* y /* * PB13 --> SPI1 SCK Mode: GPIO_Mode_AF_PP * PB15 --> SPI1 MOSI Write Mode: GPIO_Mode_AF_PP# U2 Q5 ^- u9 r* \ Q) U' x2 Y' R * PB14 --> SPI1 MISO Read Mode: GPIO_Mode_IPU2 R& I1 b& w# O: Z. H * PC13 --> SPI1 CS */; J# |( S* s- Z: e / J) J8 O4 x7 d: z+ O0 W GPIO_DeInit(GPIOB);' A. {- [* x9 _3 O. U W* } 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;; G1 ~7 I M" [ GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_15);( z6 b. T- H: p+ ?: M, Q 1 \5 [% c: D. K/ i( T) l$ f0 _& u GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_14); " ]2 `) Q ^/ l' z2 t$ G, B GPIO_DeInit(GPIOC); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;. r0 V* @& E1 D: E1 c GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_SetBits(GPIOC, GPIO_Pin_13);& J9 w) {9 ^4 ]! f& g9 ~ SPI_Cmd(SPI2, DISABLE); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master;0 z$ T* @. C1 C U1 L SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;7 F& v+ v8 Q H SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;, K1 ]: a, R: T5 N' \/ C SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;+ z: \" T, s1 k$ _6 s! s3 [8 v SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure);, p( G' x8 L+ g2 T6 V; w if(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != RESET){ SPI_I2S_ReceiveData(SPI2); SPI_I2S_ClearFlag(SPI2, SPI_FLAG_CRCERR); }8 \) ]& c6 s7 `, w ' k) N1 z3 I: v# D; ~. M7 a ~- j1 O /* DMA1 Channel4 Configures for SPIS Receive */ DMA_DeInit(DMA1_Channel4);5 N, b* Q4 D* P! I Z DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Rx_Buf;$ x3 ^" ]9 a; n, r/ ` DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 0; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;1 F4 \; R7 t V* [5 @" f% t DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;6 S. m |: a0 m; }) K6 h DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;2 M0 M7 H5 d1 a DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;) V$ L5 Z ]% F- z* D DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;/ J7 Q5 y# _# A& h$ r' Q DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;) f5 d' x3 l3 }) S DMA_Init(DMA1_Channel4, &DMA_InitStructure); if(DMA_GetITStatus(DMA1_IT_TC4)!= RESET){- {9 B U& O+ a' l DMA_ClearITPendingBit(DMA1_IT_TC4); }* l- w6 |# C# \ DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);$ f. g' t8 M" H" H4 ?; [ SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); /* Enable DMA1 Channel4 SPI2_RX */: E+ Z3 G, d) \! c3 |! W4 m/ k) L DMA_Cmd(DMA1_Channel4, DISABLE); ; z* y- p0 K7 v% Z /* DMA1 Channel5 Configures for SPI2 Send */1 I- x+ e) F8 [' u DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR);5 K N, K; \6 r2 D7 J6 l, m5 c DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Tx_Buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 0; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;6 D) b9 D) P! H2 w( s; G DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;9 U, a8 Q9 r9 d1 u6 u+ [7 t3 g DMA_Init(DMA1_Channel5, &DMA_InitStructure);3 Y( z1 f! l/ E2 w# ` if(DMA_GetITStatus(DMA1_IT_TC5)!= RESET){ DMA_ClearITPendingBit(DMA1_IT_TC5); } DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); z+ E3 g4 i4 K# n( O' r /* Enable DMA1 Channel5 SPI1_TX */ DMA_Cmd(DMA1_Channel5, DISABLE); 3 B- Y7 E+ p: |5 T' p9 P /* Enable the DMA1_Channel4、DMA1_Channel5 Interrupt */ v1 y8 k, u$ \2 y, B NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);$ X8 i* R# h6 R" H! c. k2 V NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn; NVIC_Init(&NVIC_InitStructure);( V0 ?; p5 x! |" D! i d. H$ x /* Enable SPI2 */: \* Q3 x8 R- W9 v9 \* W0 D SPI_Cmd(SPI2, ENABLE); } /** * @brief SPI1_DMA_Start+ |+ A: a$ m! v [ * @param len <= 40960 V" ^: w; u7 o x" S9 j; i$ K# h% n * @retval None I6 C+ {. q2 J3 R */, p& ]( q! _- l" ~( Z; U' c! ` void SPI2_DMA_Read_Write(uint16_t len) {! p; A$ z/ }% P Y/ g SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);9 t+ l) F$ d1 z0 T* Q+ w4 k SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); DMA1_Channel4->CMAR = (uint32_t)SPI2_Rx_Buf;- G% B9 S- V. U& d. [8 z5 p6 E DMA1_Channel5->CMAR = (uint32_t)SPI2_Tx_Buf; DMA1_Channel4->CNDTR = len;1 S) N6 Z) ]5 a* _5 H* ?$ O DMA1_Channel5->CNDTR = len; DMA_Cmd(DMA1_Channel4, ENABLE); DMA_Cmd(DMA1_Channel5, ENABLE);+ b! r5 ^; c; u5 O SPI_Cmd(SPI2, ENABLE);/ A# m9 b( t' a% \. R9 B7 Z }8 k" W* w, H$ w& z0 ^3 I, \ /**' a: z/ }0 x ~9 F * @brief SPI2_Set_Speed& [9 J, E9 L/ h1 a% V ~% w! X * @param SPI2 CR1 bit 9 8 7 * SPI_BaudRatePrescaler_2 ---> 000 * SPI_BaudRatePrescaler_4 ---> 001 * SPI_BaudRatePrescaler_8 ---> 010: P6 o7 m" r& @+ x * SPI_BaudRatePrescaler_16 ---> 011+ S r: V. l* |2 p; n, j * SPI_BaudRatePrescaler_32 ---> 1009 T2 B* T! b' p2 k: g8 W$ @$ E2 v * SPI_BaudRatePrescaler_64 ---> 101# @: f9 A! W" q8 i * SPI_BaudRatePrescaler_128 ---> 110 * SPI_BaudRatePrescaler_256 ---> 111 * @retval None3 f' R, S: ^" T i, E5 R */2 g% _! Q: V3 ~7 l 2 Z7 V% V) a) ^: d, ]- i" m void SPI2_Set_Speed(uint8_t BaudRatePrescaler) { SPI2->CR1 &= 0xFFC7; /* Clear BaudRatePrescaler Value (bit 9 8 7) */) c2 L$ {" Z2 s2 t( c- W SPI2->CR1 |= BaudRatePrescaler;& f% o( J: E, d7 r% _* Q SPI_Cmd(SPI2,ENABLE);" C, O4 h3 R V& X } /** * @brief SPI1_Byte_Read_Write * @param None) X' \( _- y: |* h& X$ p& b: | * @retval None */ uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte) { M% W: ^% D! J // 发送一字节: E- k/ H5 c/ j/ A6 \4 p5 K. S& N while((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET); SPI2->DR = SPI_Byte; // 接收一字节4 Q$ ^* \: W" @) r2 N while((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET);2 l1 r( u! V: k% D: F& N4 U) _3 t return(SPI2->DR); }3 I& r5 m4 ]% @: W3 b /*0 b" S& k8 m2 W: p2 g * Function Name : DMA1_Channel4_IRQHandler * Description : None * Input : None * Output : None* {0 |" K; I- X * Return : None */ void DMA1_Channel4_IRQHandler(void) { if (DMA_GetITStatus(DMA1_IT_TC4)) {0 @ P* K9 r" u6 i9 o SPI_Flash_CS_High(); DMA_Cmd(DMA1_Channel4, DISABLE);; ]; O& ~5 N! S) Y8 l5 [7 K DMA_ClearITPendingBit(DMA1_IT_TC4); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);; |% U* r4 Z% \7 M' a) e. Y' ?! f SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, DISABLE); Flag_DMA_Rxd_Finished = 1; } }' B4 y* I7 X, L. g3 j3 S2 d: A /*6 Q6 y$ M9 T U: i6 s+ R * Function Name : DMA1_Channel5_IRQHandler. i# e: s$ t, a* j * Description : None) p! e- j: S3 M * Input : None * Output : None% [% j$ Q1 I$ o( B1 ]( | * Return : None */ void DMA1_Channel5_IRQHandler(void) { if (DMA_GetITStatus(DMA1_IT_TC5)) {( S) U& b$ w! s# C DMA_Cmd(DMA1_Channel5, DISABLE);" b+ g% G- s; d; s5 x DMA_ClearITPendingBit(DMA1_IT_TC5); } }- E& ]8 z1 J- | $ j' M! v4 u) C3 b6 j8 v/ U : d% d7 `$ [ Y) ] |
: [; V, A- b J5 i; q* R
命令字节发送和接收, 可以使用SPI2_Byte_Read_Write, 也可以使用SPI2_DMA_Read_Write,
这里使用SPI2读写SPI_Flash, SPI2_DMA_Read_Write 可以按照下面的方法使用:
6 @. D" u# r+ B* t6 N
SP2_Tx_Buf_load(); // 数据装入发送缓冲# O( n* R' a; l* D9 R- g7 ]/ X8 ]
SPI2_Flash_CS_Low(); // 片选使能9 ?7 Z0 ~* y3 E6 G
SPI2_DMA_Read_Write(6); // 启动发送和接收, 在DMA传输完毕中断里片选关闭/ ~( T7 v* @' }, D# e
while(Flag_DMA_Rxd_Finished==0) {
// 使用DMA连续收发时, 可以利用这个空闲做一些事情# z" E- H6 l7 c# A& N$ Y
// 如果是用SPI2_Byte_Read_Write, 单字节收发就没有多少空闲时间了
;
}
Flag_DMA_Rxd_Finished = 0; // DMA收发完毕,标志清0
4 p6 V' _* k; Y& E* d: |
! Z! L! A' e; C6 ]3 j
研究,研究