硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2745|回复: 2
收起左侧

[有问必答] STM32F103三个硬件SPI同时用有什么要注意的吗?

[复制链接]

33

主题

203

回帖

302

积分

高级会员

积分
302
发表于 2020-2-16 10:29:14 | 显示全部楼层 |阅读模式
本帖最后由 diiiiiii 于 2020-2-16 10:35 编辑
  1. void stm32_enable_periph_clock(void)

  2. {

  3.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

  4.    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | \

  5.                             RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);

  6. }
复制代码
  1. static void stm32_spi2_init(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStructure;
  4.         SPI_InitTypeDef SPI_InitStructure;

  5.         // NSS
  6.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  7.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                       
  8.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  9.         GPIO_Init(GPIOC, &GPIO_InitStructure);
  10.         GPIO_SetBits(GPIOC,GPIO_Pin_6);       
  11.         // SPI
  12.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 |GPIO_Pin_15;
  13.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                        
  14.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  16.        

  17.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  18.         RCC_PCLK1Config(RCC_HCLK_Div2);
  19.        
  20.         SPI_I2S_DeInit(SPI2);
  21.         SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  22.         SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  23.         SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  24.         SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  25.         SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  26.         SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  27.         SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
  28.         SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  29.         SPI_InitStructure.SPI_CRCPolynomial = 7;
  30.         SPI_Init(SPI2,&SPI_InitStructure);
  31.        
  32.         SPI_Cmd(SPI2, ENABLE);

  33. }
复制代码
  1. void stm32_spi1_init(void)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     SPI_InitTypeDef  SPI_InitStructure;
  5.         // NSS
  6.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  7.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                       
  8.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  9.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  10.         GPIO_SetBits(GPIOB,GPIO_Pin_11);       
  11.    
  12.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  13.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  14.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  16.     GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
  17.         RCC_APB2PeriphClockCmd(        RCC_APB2Periph_SPI1, ENABLE );
  18.    
  19.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  20.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  21.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  22.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  23.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  24.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  25.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  26.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  27.     SPI_InitStructure.SPI_CRCPolynomial = 7;
  28.     SPI_Init(SPI1, &SPI_InitStructure);

  29.     SPI_Cmd(SPI1, ENABLE);
  30. }  
  31. /*******************************************************************************/
  32. void stm32_spi3_init(void)
  33. {
  34.         GPIO_InitTypeDef GPIO_InitStructure;
  35.         SPI_InitTypeDef SPI_InitStructure;
  36.    
  37.         // NSS
  38.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  39.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                       
  40.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  41.         GPIO_Init(GPIOD, &GPIO_InitStructure);
  42.         GPIO_SetBits(GPIOD,GPIO_Pin_2);       
  43.         // SPI
  44.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 |GPIO_Pin_5;
  45.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                        
  46.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  47.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  48.        
  49.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);

  50.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
  51.         RCC_PCLK1Config(RCC_HCLK_Div2);
  52.        
  53.         SPI_I2S_DeInit(SPI3);
  54.         SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  55.         SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  56.         SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  57.         SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  58.         SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  59.         SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  60.         SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  61.         SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  62.         SPI_InitStructure.SPI_CRCPolynomial = 7;
  63.         SPI_Init(SPI3,&SPI_InitStructure);
  64.        
  65.         SPI_Cmd(SPI3, ENABLE);

  66. }
复制代码

SPI1和SPI3带RFID芯片,SPI2带W25Q64,功能是刷卡时从W25Q64读取数据,发现读取数据速度特慢。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107431
QQ
发表于 2020-2-16 10:48:55 | 显示全部楼层
试试我的,RL-FlashFS的SPI驱动:

  1. /*
  2. *********************************************************************************************************
  3. *
  4. *        模块名称 : SPI驱动模块
  5. *        文件名称 : SPI_STM32F103.c
  6. *        版    本 : V1.0
  7. *        说    明 : 本驱动是基于bsp_spi_bus.c文件实现。
  8. *              (1)使用FlashFS的SPI FLASH文件系统前务必先调用初始化函数bsp_InitSPIBus(在函数bsp.c中初始化)。
  9. *              (2)本文件使用的是官方模板,用户只需添加函数功能即可,故不对变量定义和函数名做重新规范。
  10. *              
  11. *        修改记录 :
  12. *                版本号  日期        作者     说明
  13. *                V1.0    2015-09-09 Eric2013  正式发布
  14. *
  15. *        Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
  16. *
  17. *********************************************************************************************************
  18. */
  19. #include <File_Config.h>
  20. #include "bsp.h"


  21. /*
  22. **********************************************************************************************************
  23.                                                                                         宏定义
  24. **********************************************************************************************************
  25. */
  26. /*
  27.    SPI 驱动定义
  28.    spi0_drv: 第一个SPI设备驱动
  29.    spi1_drv: 第二个SPI设备驱动
  30. */

  31. #define __DRV_ID  spi0_drv
  32. #define __FPCLK   72000000

  33. /* SPI_SR位定义 */
  34. #define RXNE    0x01
  35. #define TXE     0x02
  36. #define BSY     0x80
  37. #define FPCLK   (__FPCLK/1000)

  38. /* 串行Flsh的片选GPIO端口  */
  39. #define SPI_SelectHard            SPI1
  40. #define SF_RCC_CS                         RCC_APB2Periph_GPIOF
  41. #define SF_PORT_CS                        GPIOF
  42. #define SF_PIN_CS                        GPIO_Pin_11
  43. #define SF_CS_0()                        SF_PORT_CS->BRR = SF_PIN_CS
  44. #define SF_CS_1()                        SF_PORT_CS->BSRR = SF_PIN_CS

  45. /*
  46. **********************************************************************************************************
  47.                                                                                         宏定义
  48. **********************************************************************************************************
  49. */

  50. /* SPI驱动接口函数 */
  51. static BOOL Init (void);
  52. static BOOL UnInit (void);
  53. static U8   Send (U8 outb);
  54. static BOOL SendBuf (U8 *buf, U32 sz);
  55. static BOOL RecBuf (U8 *buf, U32 sz);
  56. static BOOL BusSpeed (U32 kbaud);
  57. static BOOL SetSS (U32 ss);

  58. /* SPI 设备驱动控制块 */
  59. SPI_DRV __DRV_ID = {
  60.   Init,
  61.   UnInit,
  62.   Send,
  63.   SendBuf,
  64.   RecBuf,
  65.   BusSpeed,
  66.   SetSS,
  67.   NULL
  68. };


  69. /*
  70. *********************************************************************************************************
  71. *        函 数 名: Init
  72. *        功能说明: 初始化SPI设备,这里仅初始化了SPI Flash的片选,SPI初始化调用函数bsp_InitSPIBus()实现
  73. *        形    参: 无
  74. *        返 回 值: __TRUE
  75. *********************************************************************************************************
  76. */
  77. static BOOL Init (void)
  78. {
  79.         /*
  80.           安富莱STM32-V4 开发板口线分配:  串行Flash型号为 W25Q128 (104MHz)
  81.           片选 PF8/SF_CS
  82.         */
  83.         GPIO_InitTypeDef GPIO_InitStructure;

  84.         /* 使能GPIO 时钟 */
  85.         RCC_APB2PeriphClockCmd(SF_RCC_CS, ENABLE);

  86.         /* 配置片选口线为推挽输出模式 */
  87.         SF_CS_1();                /* 片选置高,不选中 */
  88.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  89.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  90.         GPIO_InitStructure.GPIO_Pin = SF_PIN_CS;
  91.         GPIO_Init(SF_PORT_CS, &GPIO_InitStructure);
  92.         return (__TRUE);
  93. }

  94. /*
  95. *********************************************************************************************************
  96. *        函 数 名: UnInit
  97. *        功能说明: 卸载SPI设备,正常情况下此函数实现卸载需要将SPI接口设置为初始化状态,即未开启状态。
  98. *             由于多个设备使用SPI接口,这里仅是将片选至高。
  99. *        形    参: 无
  100. *        返 回 值: __TRUE
  101. *********************************************************************************************************
  102. */
  103. static BOOL UnInit (void)
  104. {
  105.   SF_CS_1();

  106.   return (__TRUE);
  107. }

  108. /*
  109. *********************************************************************************************************
  110. *        函 数 名: Send
  111. *        功能说明: 发送一个字节数据
  112. *        形    参: 无
  113. *        返 回 值: SPI接口返回值
  114. *********************************************************************************************************
  115. */
  116. static U8 Send (U8 outb)
  117. {
  118.         /* 通过SPI接口读写一个字节 */
  119.         SPI_SelectHard->DR = outb;

  120.         /* 等待数据接收完毕 */
  121.         while (!(SPI_SelectHard->SR & RXNE));
  122.         return (SPI_SelectHard->DR);
  123. }

  124. /*
  125. *********************************************************************************************************
  126. *        函 数 名: SendBuf
  127. *        功能说明: 通过SPI接口发送多个字节
  128. *        形    参: buf 数据地址
  129. *             sz  发送数据大小
  130. *        返 回 值: __TRUE
  131. *********************************************************************************************************
  132. */
  133. static BOOL SendBuf (U8 *buf, U32 sz)
  134. {
  135.         U32 i;

  136.         for (i = 0; i < sz; i++)
  137.         {
  138.                 SPI_SelectHard->DR = buf[i];
  139.                 /* 等待发送完成 */
  140.                 while (!(SPI_SelectHard->SR & TXE));
  141.                 SPI_SelectHard->DR;
  142.         }
  143.        
  144.         /* 等待接收完成 */
  145.         while (SPI_SelectHard->SR & (BSY | RXNE))
  146.         {
  147.                 SPI_SelectHard->DR;
  148.         }
  149.         return (__TRUE);
  150. }

  151. /*
  152. *********************************************************************************************************
  153. *        函 数 名: RecBuf
  154. *        功能说明: 通过SPI接口接收多个字节
  155. *        形    参: buf 数据地址
  156. *             sz  接收数据大小
  157. *        返 回 值: __TRUE
  158. *********************************************************************************************************
  159. */
  160. static BOOL RecBuf (U8 *buf, U32 sz)
  161. {
  162.         U32 i;

  163.         for (i = 0; i < sz; i++)
  164.         {
  165.                 SPI_SelectHard->DR = 0xFF;
  166.                 /* 等待接收完成 */
  167.                 while (!(SPI_SelectHard->SR & RXNE));
  168.                 buf[i] = SPI_SelectHard->DR;
  169.         }
  170.         return (__TRUE);
  171. }

  172. /*
  173. *********************************************************************************************************
  174. *        函 数 名: BusSpeed
  175. *        功能说明: 设置SPI速度,驱动SPI Flash使用的是18MHz
  176. *        形    参: buf 数据地址
  177. *             sz  接收数据大小
  178. *        返 回 值: __TRUE
  179. *********************************************************************************************************
  180. */
  181. static BOOL BusSpeed (U32 kbaud)
  182. {
  183.         U8 br;

  184.         if      (kbaud >= FPCLK / 2)   br = 0;                       /* FPCLK/2    */
  185.         else if (kbaud >= FPCLK / 4)   br = 1;                       /* FPCLK/4    */
  186.         else if (kbaud >= FPCLK / 8)   br = 2;                       /* FPCLK/8    */
  187.         else if (kbaud >= FPCLK / 16)  br = 3;                       /* FPCLK/16   */
  188.         else if (kbaud >= FPCLK / 32)  br = 4;                       /* FPCLK/32   */
  189.         else if (kbaud >= FPCLK / 64)  br = 5;                       /* FPCLK/64   */
  190.         else if (kbaud >= FPCLK / 128) br = 6;                       /* FPCLK/128  */
  191.         else                           br = 7;                       /* FPCLK/256  */

  192.         SPI_SelectHard->CR1 = (SPI_SelectHard->CR1 & ~(7 << 3)) | (br << 3);
  193.         return (__TRUE);
  194. }

  195. /*
  196. *********************************************************************************************************
  197. *        函 数 名: BusSpeed
  198. *        功能说明: 设置SPI速度,驱动SPI Flash使用的是18MHz
  199. *        形    参: ss
  200. *             0 表示选中设备
  201. *             1 表示取消选中
  202. *        返 回 值: __TRUE
  203. *********************************************************************************************************
  204. */
  205. static BOOL SetSS (U32 ss) {
  206.         if(ss == 0)
  207.         {
  208.                 bsp_SpiBusEnter();        /* 占用SPI总线, 用于总线共享 */
  209.                
  210.                 bsp_SPI_Init(SPI_Direction_2Lines_FullDuplex | SPI_Mode_Master | SPI_DataSize_8b
  211.                         | SPI_CPOL_High | SPI_CPHA_2Edge | SPI_NSS_Soft | SPI_BaudRatePrescaler_4 | SPI_FirstBit_MSB);
  212.                 SF_CS_0();
  213.                
  214.         }
  215.         else
  216.         {
  217.                 SF_CS_1();
  218.                 bsp_SpiBusExit();        /* 释放SPI总线, 用于总线共享 */
  219.         }
  220.        
  221.   return (__TRUE);
  222. }

  223. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码


回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2020-2-16 12:02:35 | 显示全部楼层
如果你的W25Q64需要一次读的数据较多,建议SPI2和DMA配合使用来读写,因为DMA要求指定的大小,可以牺牲一本分W25Q64的字节,来满足DMA
感觉利用while循环的方式读写十分慢。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-31 09:18 , Processed in 0.212569 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表