查看: 1195|回复: 1
收起左侧

第五十一章:SPI-全双工通信,硬件控制NSS模式

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-4-29 19:11:29 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 草帽王子 于 2021-9-10 17:42 编辑

    CH32V103应用教程——
    SPI-全双工通信,硬件控制NSS模式


    本章教程主要在SPI双线全双工模式下进行主从收发实验,并采用硬件控制NSS方式。


    1、SPI简介及相关函数介绍

    关于SPI主从模式下的全双工发送和接收数据,其软件配置过程在第50章已经介绍,在此不再赘述。
    关于CH32V103 SPI具体信息,可参考CH32V103应用手册。SPI标准库函数在第十五章节已介绍,在此不再赘述。


    2、硬件设计

    本章教程主要进行SPI主从模式下的全双工发送和接收数据,需用到两个开发板,且由于采用全双工模式,因此主设备和从设备均要使用MOSI引脚和MISO引脚以及SCK引脚进行通讯。

    此处使用外设为SPI1,主设备和从设备MOSI对应引脚均为PA7引脚、MISO对应引脚均为PA6引脚,将主设备PA6、PA7引脚与从设备PA6、PA7引脚一一对应连接起来,此外还需将两个开发板SPI1对应的SCK引脚PA5连接起来,且由于采用硬件控制NSS方式,因此需要将两个开发板对应NSS引脚PA4连接起来。

    此外,由于两个开发板需要同时进行上电传输,因此将两个开发板的3.3V引脚和GND引脚进行连接。


    3、软件设计

    本章教程主要进行SPI主从模式下的全双工发送和接收数据,且采用硬件控制NSS方式,具体程序如下:

    spi.h文件
    1. #ifndef __SPI_H
    2. #define __SPI_H

    3. #include "ch32v10x_conf.h"

    4. /* SPI Mode Definition */
    5. #define HOST_MODE    0
    6. #define SLAVE_MODE   1

    7. /* SPI Communication Mode Selection */
    8. //#define SPI_MODE   HOST_MODE
    9. #define SPI_MODE   SLAVE_MODE

    10. #define  Size  18

    11. extern u16 TxData[Size];
    12. extern u16 RxData[Size];

    13. void SPI_FullDuplex_Init(void);

    14. #endif
    复制代码

    spi.c文件
    1. #include "spi.h"

    2. /* Global Variable */

    3. u16 TxData[Size] = { 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606,
    4.                      0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616,
    5.                      0x2121, 0x2222, 0x2323, 0x2424, 0x2525, 0x2626 };
    6. u16 RxData[Size];

    7. /*******************************************************************************
    8. * Function Name  : SPI_FullDuplex_Init
    9. * Description    : Configuring the SPI for full-duplex communication.
    10. * Input          : None
    11. * Return         : None
    12. *******************************************************************************/
    13. void SPI_FullDuplex_Init(void)
    14. {
    15.     GPIO_InitTypeDef GPIO_InitStructure;
    16.     SPI_InitTypeDef SPI_InitStructure;

    17.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE );

    18. #if (SPI_MODE == HOST_MODE)
    19.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    20.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    21.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    22.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    23.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    24.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    25.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    26.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    27.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    28.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    29.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    30.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    31.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    32.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    33.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    34. #elif (SPI_MODE == SLAVE_MODE)
    35.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    36.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    37.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    38.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    39.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    40.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    41.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    42.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    43.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    44.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    45.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    46.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    47.     GPIO_Init( GPIOA, &GPIO_InitStructure );

    48. #endif

    49.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

    50. #if (SPI_MODE == HOST_MODE)
    51.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

    52. #elif (SPI_MODE == SLAVE_MODE)
    53.     SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

    54. #endif

    55.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
    56.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    57.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    58.     SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
    59.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
    60.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
    61.     SPI_InitStructure.SPI_CRCPolynomial = 7;
    62.     SPI_Init( SPI1, &SPI_InitStructure );

    63.     SPI_SSOutputCmd( SPI1, ENABLE );

    64.     SPI_Cmd( SPI1, ENABLE );
    65. }
    复制代码
    spi.c文件主要包括1个函数:SPI_FullDuplex_Init函数。SPI_FullDuplex_Init函数主要进行SPI1全双工通信模式下的主机和从机配置。

    首先,由于采用全双工通信方式,且采用硬件控制NSS引脚,因此需要对主机和从机的NSS引脚、SCK引脚、MOSI引脚和MISO引脚进行GPIO初始化配置。

    此外,还需要进行主机和从机配置,此配置可根据CH32V103应用手册主模式和从模式配置步骤进行,主要对SPI通信的通信方向、主从模式、数据帧大小、时钟极性、时钟相位、NSS引脚使用方式、波特率等进行配置,可对照手册参考标准库函数ch32v10x_spi.c文件中SPI_Init函数进行配置。

    main.c文件
    1. /********************************** (C) COPYRIGHT *******************************
    2. * File Name          : main.c
    3. * Author             : WCH
    4. * Version            : V1.0.0
    5. * Date               : 2020/04/30
    6. * Description        : Main program body.
    7. *******************************************************************************/

    8. #include "debug.h"
    9. #include "spi.h"
    10. #include "string.h"

    11. /*
    12. *@Note
    13. 硬件NSS模式,Master/Slave 模式数据收发:
    14. Master:SPI1_NSS(PA4)、SPI1_SCK(PA5)、SPI1_MISO(PA6)、SPI1_MOSI(PA7)。
    15. Slave :SPI1_NSS(PA4)、SPI1_SCK(PA5)、SPI1_MISO(PA6)、SPI1_MOSI(PA7)。

    16. 本例程演示在硬件 NSS 模式下,Master 和 Slave 同时全双工收发。
    17. 注:两块板子分别下载 Master 和 Slave 程序,同时上电。
    18.        硬件连线:PA4 —— PA4
    19.             PA5 —— PA5
    20.             PA6 —— PA6
    21.             PA7 —— PA7
    22. */
    23. /*******************************************************************************
    24. * Function Name  : main
    25. * Description    : Main program.
    26. * Input          : None
    27. * Return         : None
    28. *******************************************************************************/
    29. int main(void)
    30. {
    31.     u8 i=0;
    32.     u8 j=0;
    33.     u8 value;

    34.     Delay_Init();
    35.     USART_Printf_Init(115200);
    36.     printf("SystemClk:%d\r\n",SystemCoreClock);

    37. #if (SPI_MODE == SLAVE_MODE)
    38.     printf("Slave Mode\r\n");
    39.     Delay_Ms(1000);

    40. #endif

    41.     SPI_FullDuplex_Init();

    42. #if (SPI_MODE == HOST_MODE)
    43.     printf("Host Mode\r\n");
    44.     Delay_Ms(2000);

    45. #endif

    46.     while(1)
    47.     {
    48.         while( ( i<18 ) || ( j<18 ))
    49.         {
    50.             if( i<18 )
    51.             {
    52.                 if( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) != RESET )
    53.                 {
    54.                     SPI_I2S_SendData( SPI1, TxData[i] );
    55.                     i++;
    56.                 }
    57.             }

    58.             if( j<18 )
    59.             {
    60.                 if( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) != RESET )
    61.                 {
    62.                     RxData[j] = SPI_I2S_ReceiveData( SPI1 );
    63.                     j++;
    64.                 }
    65.             }
    66.         }

    67.         for( i=0; i<18; i++ )
    68.         {
    69.          printf( "Rxdata:%04x\r\n", RxData[i] );
    70.         }

    71.         value = memcmp( TxData, RxData, Size );

    72.         if( value == 0 )
    73.         {
    74.             printf( "Same\r\n" );
    75.         }
    76.         else
    77.         {
    78.             printf( "Different\r\n" );
    79.         }

    80.         while(1);
    81.     }
    82. }

    复制代码
    main.c文件主要进行主机和从机下的数据发送和接收。并将接收数据与发送数据进行对比,当发送数据与接收数据相同,输出same,若不同,输出different。


    4、下载验证

    将编译好的程序分别在主机模式和从机模式下下载到两个开发版,并将主机的引脚与从机的引脚一一对应进行连接,开发板上电后,串口打印如下:
    主机打印:
    CH32V CH573单片机芯片-第五十一章:SPI-全双工通信,硬件控制NSS模式risc-v单片机中文社区(1)
    从机打印:
    CH32V CH573单片机芯片-第五十一章:SPI-全双工通信,硬件控制NSS模式risc-v单片机中文社区(2)

    50、SPI-全双工模式,硬件控制NSS.rar
    CH32V CH573单片机芯片-第五十一章:SPI-全双工通信,硬件控制NSS模式risc-v单片机中文社区(3) 50、SPI-全双工模式,硬件控制NSS.rar (477.45 KB, 下载次数: 10)
    链接:https://pan.baidu.com/s/1u4v7NcnP4_9iDs9VYTKp4Q
    提取码:vrqy
    复制这段内容后打开百度网盘手机App,操作更方便哦







    上一篇:第五十章:SPI-全双工通信,软件控制NSS模式
    下一篇:第五十二章:CH32V103应用教程——SPI-CRC校验
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    RISC-V隐身侠  发表于 2021-6-25 06:57:54

    facebook spy tool

    CH32V CH573单片机芯片-第五十一章:SPI-全双工通信,硬件控制NSS模式risc-v单片机中文社区(4)

    FB friends spy is a facebook windows application that offers to its user’s information about their friends they cannot find in there profiles:
    1. Online presence information (offline/online) even if you are in offline chat mode.
    2. People most interested by them.
    3. People most interacting with them(on comments not messages , spying on messages is illegal and forbidden by facebook, so it is impossible to do, thank you for your understanding).
    4. latest Facebook statuses
    5. Places visited.
    6. Events attending or already participated in
    FB friend's spy will ask you for permissions to offer you the information you want, this information will and still be used only by you, it will not be used by anyone else.
    FB friend’s spy uses Facebook SDK to connect to Facebook, so users don’t have to worry about their private or secret information.


    CH32V CH573单片机芯片-第五十一章:SPI-全双工通信,硬件控制NSS模式risc-v单片机中文社区(5)
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复 支持 反对

    使用道具

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-3-29 18:34 , Processed in 3.625976 second(s), 50 queries .

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