SPI-SPI单线半双工数据收发应用笔记

Posted wchmcu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPI-SPI单线半双工数据收发应用笔记相关的知识,希望对你有一定的参考价值。

SPI单线半双工数据收发应用笔记

SPI 接口可以工作在单线半双工模式,即主设备使用 MOSI 引脚,从设备使用 MISO 引脚进行通讯。CH32V203C8T6 芯片内置两路 SPI,使用 SPI1 作为主机,SPI2 作为从机,配合 DMA 完成 SPI 接口的单线半双工通信测试。

查阅应用手册 SPI 章节的寄存器描述,不难发现其关键在于通信过程中正确切换控制寄存器1中 BIDIOE 位。当 BIDIOE 置位时,主机处于发送状态,此时通过 DMA 将所需发送的数据搬运到数据寄存器中,即可完成发送过程。当 BIDIOE 复位时,主机处于接收状态,此时,主机仅通过时钟线持续输出既定频率的时钟信号。

 

1. SPI_InitTypeDef SPI_InitStructure = 0;

2.  

3. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

5.  

6. // SPI1 HOST

7. SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; // 单线半双工发送状态

8. SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主机

9. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

10. SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

11. SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;

12. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 软件片选

13. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

14. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;

15. SPI_InitStructure.SPI_CRCPolynomial = 7;

16. SPI_Init(SPI1, &SPI_InitStructure);

17.  

18. // SPI2 SLAVE

19. SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Rx; // 单线半双工接收状态

20. SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; // 从机

21. SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; // 硬件片选

22. SPI_Init(SPI2, &SPI_InitStructure);

23.  

24. SPI_Cmd(SPI1, ENABLE);

25. SPI_Cmd(SPI2, ENABLE);

 

为了能够实现数据正常的接收,在初始化时,先将 SPI1 主机配置为单线发送状态,将 SPI2 从机配置为单线接收状态。

SPI 作为从机时,处于完全被动状态,在片选状态下,只要主机向外输出时钟信号,从机将持续的把数据寄存器中的数据向外移出。这种情况下需要特殊的处理,以保证 SPI 不会开始一次新的传输。为了简化这一操作,SPI2 配置时使用了硬件片选进行控制。

在初始化 DMA 时,应注意不使能 SPI1&2 的发送通道,避免 SPI 从机在未切换完成前进行发送操作。实际测试 DMA 接收通道,并发现存在接收异常的问题。

 

1. printf("SPI1 Tx...\\r\\n");

2. GPIO_ResetBits(GPIOA, GPIO_Pin_4);

3. DMA_Cmd(DMA1_Channel3, ENABLE); // 主机(SPI1)数据发送

4. while(DMA_GetFlagStatus(DMA1_FLAG_TC3) == 0); // 等待主机DMA(SPI1)操作完成

5. while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == 0); // 等待从机DMA(SPI2)操作完成

6. GPIO_SetBits(GPIOA, GPIO_Pin_4); // 主机释放片选信号

7.  

8. printf("SPI2 Tx...\\r\\n");

9. SPI2->CTLR1 |= 1<<14; // 从机(SPI2)切换为发送状态

10. /* 先准备好第一个需要发送的数据,等待片选及时钟信号

11. * 避免出现在SPI时钟较高时,数据寄存器未完成更新的问题

12. * */

13. DMA_Cmd(DMA1_Channel5, ENABLE); // 从机(SPI2)数据发送

14. GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 片选

15. SPI1->CTLR1 &= ~(1<<14); // 主机(SPI1)切换为接收状态

16.  

17. while(DMA_GetFlagStatus(DMA1_FLAG_TC5) == 0); // 等待从机DMA(SPI2)操作完成

18. // 等待SPI2发送完成

19. __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

20. __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

21. __NOP();__NOP();__NOP();__NOP();

22. GPIO_SetBits(GPIOA, GPIO_Pin_4);

23. while(DMA_GetFlagStatus(DMA1_FLAG_TC2) == 0); // 等待主机DMA(SPI1)操作完成

24. SPI1->CTLR1 |= 1<<14; // 主机(SPI1)切换为发送状态

25. SPI2->CTLR1 &= ~(1<<14); // 从机(SPI2)切换为接收状态

 

测试过程中,还需要注意 SPI2 作为从机发送数据的过程。应首先将 SPI 从机切换至发送状态,以留出充足的时间,给 DMA 将所需发送的数据搬运到数据寄存器中。

在测试时还使用了 NOP 函数,用于解决从机发送完成最后一包数据后,依然有数据输出的问题,通过在从机 DMA 将数据搬运完成后,添加一段延时,等待 SPI 从机将数据发送完成,此时主机主动释放片选信号,停止从机数据的发送。延时所需的时间与系统主频和 SPI 时钟频率有关,需在开发过程中根据实际情况进行调整。

STM32 uart 单线半双工模式(cube版本)

STM32 uart 单线半双工模式(cube版本)

1.引言

在某些场合下需要进行三线制串口通信(信号线只有一根),这就要求进行单线半双工的模式进行通信。在这种情况进行数据协议传输的过程中,信号端需要来回切换输入输出模式。或者可以将控制端口的发送和接口进行短接。那针对这种情况,STM32提供了half-duplex功能,只要在软件里面开启这项功能,芯片硬件层内部就会将发送和接收端口进行短接。具体的芯片如何寄存器操作这边不做赘述,可以自己手册usart篇进行查阅。我们下面来看看如何利用cubeMx进行配置。

2.配置关键步骤

本文使用的STM32F0芯片,打开cubeMx在Pinout标签也下的USART1的mode 使能Sigle Wire(Half-Duplex)。如下图所示。
技术分享图片

其他配置跟普通的usart配置一样没有区别。注意这个时候硬件连线的时候需要接在TX端口。

3.软件编写

配置完成生产代码之后,在main函数中利用添加代码进行测试。

每次发送需要使能相应的功能
HAL_HalfDuplex_EnableTransmitter

同理,接收数据前也要使能相应的功能
HAL_HalfDuplex_EnableReceiver(&huart1);


 while (1)
  {
    
  /* USER CODE END WHILE */
    
  /* USER CODE BEGIN 3 */
    static uint8_t test = 6;
    //使能发送功能,每次发送前需要调用此函数
    HAL_HalfDuplex_EnableTransmitter(&huart1);
    HAL_UART_Transmit(&huart1, &test, 1, 2000);
    //使能接收功能。每次接收前需要调用此函数
    HAL_HalfDuplex_EnableReceiver(&huart1);
    HAL_UART_Receive(&huart1, &res, 1, 2000);

    if (res==6)
    {
      test++;
    }
  }

-----------------本文作者“智御电子”,期待与电子爱好者交流学习。----------------




以上是关于SPI-SPI单线半双工数据收发应用笔记的主要内容,如果未能解决你的问题,请参考以下文章

STM32F103X datasheet学习笔记---USART

stm32怎么配置成半双工异步通信

求ax-12舵机的驱动程序,stm32的,尤其是那个单线半双工串口怎么配置啊

N32G45之串口+DMA数据收发

数据通信基础(物理层)学习笔记

stm32 usart的几种通信模式