硬汉嵌入式论坛

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

加快SPI连续读写速度的配置方式

  [复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
发表于 2019-1-8 01:12:51 | 显示全部楼层 |阅读模式
一般都是下面这种,比较啰嗦
  1. /* 等待发送缓冲区空 */
  2.         while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  3.         /* 发送一个字节 */
  4.         SPI_I2S_SendData(SPI1, _ucByte);

  5.         /* 等待数据接收完毕 */
  6.         while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  7.         /* 读取接收到的数据 */
  8.         SPI_I2S_ReceiveData(SPI1);
复制代码

下面这种可以有效加速,特别是连续读写的时候
下面的函数SendBuf 隐藏了两个关键的知识点,看看有没有坛友能看出来的(答案已经揭晓到下面)

  1. /* SPI_SR位定义 */
  2. #define RXNE    0x01
  3. #define TXE     0x02
  4. #define BSY     0x80
  5. #define FPCLK   (__FPCLK/1000)

  6. /* 串行Flsh的片选GPIO端口  */
  7. #define SPI_SelectHard            SPI1
  8. #define SF_RCC_CS                         RCC_AHB1Periph_GPIOD
  9. #define SF_PORT_CS                        GPIOD
  10. #define SF_PIN_CS                        GPIO_Pin_13
  11. #define SF_CS_0()                        SF_PORT_CS->BSRRH = SF_PIN_CS
  12. #define SF_CS_1()                        SF_PORT_CS->BSRRL = SF_PIN_CS

  13. /*
  14. *********************************************************************************************************
  15. *        函 数 名: Send
  16. *        功能说明: 发送一个字节数据
  17. *        形    参: 无
  18. *        返 回 值: SPI接口返回值
  19. *********************************************************************************************************
  20. */
  21. static U8 Send (U8 outb)
  22. {
  23.         /* 通过SPI接口读写一个字节 */
  24.         SPI_SelectHard->DR = outb;

  25.         /* 等待数据接收完毕 */
  26.         while (!(SPI_SelectHard->SR & RXNE));
  27.         return (SPI_SelectHard->DR);
  28. }

  29. /*
  30. *********************************************************************************************************
  31. *        函 数 名: SendBuf
  32. *        功能说明: 通过SPI接口发送多个字节
  33. *        形    参: buf 数据地址
  34. *             sz  发送数据大小
  35. *        返 回 值: __TRUE
  36. *********************************************************************************************************
  37. */
  38. static BOOL SendBuf (U8 *buf, U32 sz)
  39. {
  40.         U32 i;

  41.         for (i = 0; i < sz; i++)
  42.         {
  43.                 SPI_SelectHard->DR = buf[i];
  44.                 /* 等待发送完成 */
  45.                 while (!(SPI_SelectHard->SR & TXE));
  46.                 SPI_SelectHard->DR;
  47.         }
  48.         
  49.         /* 等待接收完成 */
  50.         while (SPI_SelectHard->SR & (BSY | RXNE))
  51.         {
  52.                 SPI_SelectHard->DR;
  53.         }
  54.         return (__TRUE);
  55. }
复制代码


由于SPI是全双工通信,发送完还要等带接收完成,这里做一个巧妙的处理。

发送的时候仅判断TEX发送空中断,发送完毕后,再等待RXNE,这样就不需要每次TEX都等待RXNE。

另外就是我们要清除TEX和RXNE标志,清除方法也比较简单,仅需读取DR寄存器就可以清除了,比较方便。

回复

使用道具 举报

2

主题

569

回帖

575

积分

金牌会员

积分
575
发表于 2019-1-8 08:26:52 | 显示全部楼层
用寄存器写,加速。*((u32 *)0x12345678)=0x12345678;有些时候我会尝试把代码全部写成这种风格,在加速的同时,还起到了不可读的效果!
回复

使用道具 举报

29

主题

514

回帖

606

积分

金牌会员

积分
606
QQ
发表于 2019-1-8 08:32:26 | 显示全部楼层
我抓一个关键词 “buffer”
回复

使用道具 举报

56

主题

904

回帖

1072

积分

至尊会员

积分
1072
发表于 2019-1-8 08:55:47 | 显示全部楼层
V7年前出点干货啊。。。过年放假闲着也是闲着,抓紧时间学一下。。。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2019-1-8 09:06:05 | 显示全部楼层
leiyitan 发表于 2019-1-8 08:26
用寄存器写,加速。*((u32 *)0x12345678)=0x12345678;有些时候我会尝试把代码全部写成这种风格,在加速的 ...

没说到点上,寄存器操作不是关键^_^
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2019-1-8 09:06:12 | 显示全部楼层
廷润 发表于 2019-1-8 08:32
我抓一个关键词 “buffer”

没说到点上,BUF不是关键^_^
回复

使用道具 举报

0

主题

12

回帖

12

积分

新手上路

积分
12
发表于 2019-1-8 09:21:37 | 显示全部楼层
BUF方式,只要发送缓冲空TXE,就写入发送数据,不用等实际硬件是否完全发送完,这样数据发送是连续的。最后再检查RXNE标志判断实际硬件是否发送完成。
回复

使用道具 举报

17

主题

248

回帖

299

积分

高级会员

积分
299
发表于 2019-1-8 09:32:32 | 显示全部楼层
1、SPI读写过程是同步的,所以发送的时候只需等待TXE,不必每次都对接收完毕进行判断。
回复

使用道具 举报

36

主题

2039

回帖

2147

积分

至尊会员

积分
2147
发表于 2019-1-8 09:50:30 | 显示全部楼层
函数  SPI_SelectHard->DR;   用的巧妙
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.
回复

使用道具 举报

36

主题

2039

回帖

2147

积分

至尊会员

积分
2147
发表于 2019-1-8 10:11:04 | 显示全部楼层
可以方便的清除标志。
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.
回复

使用道具 举报

4

主题

140

回帖

152

积分

初级会员

积分
152
发表于 2019-1-8 10:40:42 | 显示全部楼层
用DMA更好吧
回复

使用道具 举报

36

主题

2039

回帖

2147

积分

至尊会员

积分
2147
发表于 2019-1-8 10:49:50 | 显示全部楼层

DMA不灵活,特别是控制一些ADC,DAC芯片的时候,不方便。
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.
回复

使用道具 举报

28

主题

274

回帖

358

积分

高级会员

积分
358
发表于 2019-1-8 13:08:16 | 显示全部楼层
没看出来……
回复

使用道具 举报

8

主题

94

回帖

118

积分

初级会员

积分
118
发表于 2019-1-8 15:55:37 | 显示全部楼层
在发送指定长度数据时,只写数据,不执行读。到写完时,判断一些读寄存器并处理。
回复

使用道具 举报

9

主题

160

回帖

187

积分

初级会员

积分
187
发表于 2019-1-8 16:09:49 | 显示全部楼层
Oenomaus 发表于 2019-1-8 15:55
在发送指定长度数据时,只写数据,不执行读。到写完时,判断一些读寄存器并处理。

执行了读的,我感觉时发送定长数据时,TXE为空就继续写入,不等待发送完成,同时读一下DR,以便清除可能的RXNE标志位而不实现检查RXNE标志位
回复

使用道具 举报

56

主题

904

回帖

1072

积分

至尊会员

积分
1072
发表于 2019-1-8 16:48:51 | 显示全部楼层
难道SPI返回的数据又放在了buf里面?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2019-1-9 00:24:22 | 显示全部楼层

楼主位已经更新答案。
回复

使用道具 举报

56

主题

904

回帖

1072

积分

至尊会员

积分
1072
发表于 2019-1-9 08:23:13 | 显示全部楼层
不知道能节约多少? 可能某些场合需要这样的优化,一般项目感觉还是用HAL,程序的健壮性,可读性和可维护性才是第一的。
回复

使用道具 举报

0

主题

21

回帖

21

积分

新手上路

积分
21
发表于 2019-1-9 09:08:46 | 显示全部楼层
eric2013 发表于 2019-1-8 09:06
没说到点上,BUF不是关键^_^

硬汉,请教一个 RTX的疑惑啊,我看到user文件夹内有一个文件 RTX_lib.c , 它不是个头文件,只放在文件夹内,我在工程里没看到你有添加它,有什么作用呢? 能否删除它啊。
回复

使用道具 举报

29

主题

514

回帖

606

积分

金牌会员

积分
606
QQ
发表于 2019-1-9 09:50:30 | 显示全部楼层
这巧妙的答案,刚好给我一个灵感。去规避量产产品,个别产品发生随机通信异常现象。
回复

使用道具 举报

56

主题

904

回帖

1072

积分

至尊会员

积分
1072
发表于 2019-1-9 11:14:03 | 显示全部楼层
廷润 发表于 2019-1-9 09:50
这巧妙的答案,刚好给我一个灵感。去规避量产产品,个别产品发生随机通信异常现象。

? 这个灵感好。晚上来我房聊聊。
回复

使用道具 举报

29

主题

514

回帖

606

积分

金牌会员

积分
606
QQ
发表于 2019-1-10 08:42:16 | 显示全部楼层
roguebear 发表于 2019-1-9 11:14
? 这个灵感好。晚上来我房聊聊。

我不是用贴中的功能。我是 “望文生义” ,激发了自己某款产品的某个 随机缺陷的优化思路。
回复

使用道具 举报

4

主题

84

回帖

96

积分

初级会员

积分
96
发表于 2019-1-10 09:45:55 | 显示全部楼层
这方法的确巧妙,虽然SPI可以全双工,但实际应用中却没能实现真正意义上的全双工,官方的方法可能是对全双工的支持。

最近我发现BSP驱动的中的SPI FLASH驱动的sf_AutoWritePage()函数可以有优化的地方,就是在判别FLASH中的数据没有变化之前,
只做一次读FLASH操作,后续不用再做一次读FLASH操作。因为我看到sf_AutoWritePage()函数是在某个特定扇区内操作,如果写数据
的长度小于FLASH扇区的长度就要做两次读FLASH操作(前提是新数据与FLASH中的数据不一样);既然是在某个特定扇区内操作,何不首先
读出整个扇区数据,根据地址偏移对新数据与FLASH中的数据进行比较和判断需要擦除扇区。这样无论写数据的长度小于或等于FLASH扇区
的长度都只做一次读FLASH操作,还请大神鉴别。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2019-1-10 12:19:11 | 显示全部楼层
huohua1991 发表于 2019-1-10 09:45
这方法的确巧妙,虽然SPI可以全双工,但实际应用中却没能实现真正意义上的全双工,官方的方法可能是对全双 ...

谢谢,后面研究下。
回复

使用道具 举报

6

主题

53

回帖

71

积分

初级会员

积分
71
发表于 2019-1-12 10:22:10 | 显示全部楼层
确实比起之前为了接收一个数据,还要发送一个dummy数据快!
回复

使用道具 举报

56

主题

904

回帖

1072

积分

至尊会员

积分
1072
发表于 2019-1-12 22:36:02 | 显示全部楼层
Tresordie 发表于 2019-1-12 10:22
确实比起之前为了接收一个数据,还要发送一个dummy数据快!

大概快多少?
回复

使用道具 举报

4

主题

52

回帖

64

积分

初级会员

积分
64
发表于 2019-6-18 09:03:13 | 显示全部楼层
串口也可以用类似的方法,原理就是等地啊发送完成标志,只有发送完成,就可以往DR寄存器写数据。不需要等待发送完成后,再执行其他操作。也即是说,硬件在传输数据的时候,单片机不需要死等,而是可以做其他的事情,比如运算之类的。但是我发现F0系列的TXE表示的并不是发送完成,而是发送缓冲区是否为空,发送缓冲区为空不代表数据发送完成了,只是可以再次往发送缓冲区里写入新的数据。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2019-6-18 10:51:09 | 显示全部楼层
cortex 发表于 2019-6-18 09:03
串口也可以用类似的方法,原理就是等地啊发送完成标志,只有发送完成,就可以往DR寄存器写数据。不需要等待 ...

正常来说,所有STM32系列,TXE都是表示发送空,而发送完成是TC。
F1,F4和H7都是这样的。
回复

使用道具 举报

4

主题

52

回帖

64

积分

初级会员

积分
64
发表于 2019-6-18 11:15:06 | 显示全部楼层
eric2013 发表于 2019-6-18 10:51
正常来说,所有STM32系列,TXE都是表示发送空,而发送完成是TC。
F1,F4和H7都是这样的。

好像是哦,如果只是检测TXE,然后控制SPI的CS可能会导致数据还没发送完,就把CS拉高了。现在我的做法是等所有的SPI的数据发送完成后,最后检测检测一次Busy位。官方手册不建议检测Busy位,我估计是不建议在发完一个字节后检测Busy位。我是发送所有的字节后,检测Busy位,然后控制CS片选。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2019-6-18 11:25:25 | 显示全部楼层
cortex 发表于 2019-6-18 11:15
好像是哦,如果只是检测TXE,然后控制SPI的CS可能会导致数据还没发送完,就把CS拉高了。现在我的做法是等 ...

SPI这里有个特殊的地方,发送结束务必是要检测RXNE的。
回复

使用道具 举报

4

主题

52

回帖

64

积分

初级会员

积分
64
发表于 2019-6-18 11:36:08 | 显示全部楼层
eric2013 发表于 2019-6-18 11:25
SPI这里有个特殊的地方,发送结束务必是要检测RXNE的。

意思是不是这样的,还没发送完成,接收缓冲区也是为空的,只有等到发送完成了,接收缓冲区才不是为空,也就是传输完成了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2019-6-19 00:17:15 | 显示全部楼层
cortex 发表于 2019-6-18 11:36
意思是不是这样的,还没发送完成,接收缓冲区也是为空的,只有等到发送完成了,接收缓冲区才不是为空,也 ...

由于SPI是全双工,发送时,必须要保证收到RXNE信号才是整个传输完成了。
QQ截图20190619001554.jpg
回复

使用道具 举报

19

主题

150

回帖

207

积分

高级会员

积分
207
发表于 2020-7-10 09:29:26 | 显示全部楼层
SPI发送技巧。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2021-5-16 00:05:33 | 显示全部楼层
标记下这个帖子,每次回复问题,都要查找一番这个帖子。
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2021-6-16 16:41:08 | 显示全部楼层
使用后发现卡在了 while (!(SPI_SelectHard->SR & RXNE));这个里面
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2021-6-16 16:59:07 | 显示全部楼层
qlslxf 发表于 2021-6-16 16:41
使用后发现卡在了 while (!(SPI_SelectHard->SR & RXNE));这个里面

说明没有正常工作。
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2021-6-16 17:18:14 | 显示全部楼层
eric2013 发表于 2021-6-16 16:59
说明没有正常工作。

大佬想问一下,这个spi加速改写如何替换HAL_SPI_Receive,试了一天了 感觉总是卡住了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2021-8-30 17:15:05 | 显示全部楼层
  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) *********************************/
复制代码


回复

使用道具 举报

4

主题

166

回帖

178

积分

初级会员

积分
178
发表于 2021-9-2 19:52:04 | 显示全部楼层
硬汉哥,全双工如果只有一个主不接从,发送会显示失败吗,就是例程里这个        while (w_2TransferState == TRANSFER_WAIT),因为有上拉,我觉得就算不接从机,就相当于一直接收高电平,不应该提示错误啊,但是我这反馈是错误
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
 楼主| 发表于 2021-9-3 09:22:52 | 显示全部楼层
yuanzhongda 发表于 2021-9-2 19:52
硬汉哥,全双工如果只有一个主不接从,发送会显示失败吗,就是例程里这个        while (w_2TransferState == TRAN ...

1、你貌似搞错了,这个例子里面没有while (w_2TransferState == TRANSFER_WAIT),这个是我们给bsp_spi_bus.c的HAL库驱动整理的。

2、可以参考我们论坛置顶帖V7网盘的DAC8563的DMA方式例子,就是仅发送。
SPI_DIRECTION_2LINES_TXONLY
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-3 00:22 , Processed in 0.400182 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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