• SPI 及初始化例子


    概述

    时钟相性与极性

    CPOL(Clock Polarity)控制空闲状态时SCK的值:CPOL=0,空闲时SCK=0;CPOL=1,空闲时SCK=1。

    CPHA(Clock Phase)控制何时捕获数据,CPHA=0,第一个跳变沿;CPHA=1,第二个跳变沿。详细见下图:

    从选(NSS,也就是CS)管理管脚管理

    • SSM = 1,软件管理NSS片选。两种方案:一个是把NSS设为普通IO口,使用GPIO的方法置高拉低;另一个是配置成复用口,使用SPI的寄存器CR1中的SSI位来控制NSS高低。
    • SSM = 0, 硬件管理方法,推荐使用,有两种模式(SSOE在 SPI_CR2 里):
    1. NSS 输出使能,SSM=0,SSOE=1.  适合单个master通信使用,占据NSS片选线。
    2. NSS 输出禁止,SSM=0,SSOE=0. 释放NSS片选线,从而该总线的其他master设备可以进行通信。

    举个例子:

    目的:使用硬件的方法实现,主从通信,双向收发。

    简述:master 向 slave 发生数据a 同时获取slave发送的数据b,数据a、b无误即实验成功。

    操作:连线参照Figure 238. 即所有线一一对应相连,包括NSS(即CS)。

    初始化及实验代码:

    void init_spis(void)
    {
    
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef SPI_InitStructure;
        static uint16_t tmp;
    
        /*  configure master */
    //    SPI2_NSS  PB12
    //    SPI2_SCK  PB13
    //    SPI2_MISO PB14
    //    SPI2_MOSI PB15
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTA 时钟使能
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_14;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
    
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2,  ENABLE );//SPIx时钟使能
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       // 其他设置与 slave 相同
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
        SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;   // 硬件管理
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;
        SPI_Init(SPI2, &SPI_InitStructure);
        SPI2->CR2 |= SPI_CR2_SSOE;  // 使用硬件NSS,需要把SSOE(SS Output enable)使能
    
        /*  configure slave */
    //    SPI1_NSS  PA4
    //    SPI1_SCK  PA5
    //    SPI1_MISO PA6
    //    SPI1_MOSI PA7
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTA 时钟使能
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1,  ENABLE );//SPIx时钟使能
        SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;       // 其他设置与 master 相同
        SPI_Init(SPI1, &SPI_InitStructure);
        SPI_Cmd(SPI1, ENABLE);
        SPI_I2S_SendData(SPI1, 0x52);   // slave 要发生的数据
    
        SPI_Cmd(SPI2, ENABLE); // 使能SPI外设,此时CS会自动拉低,但是没有CLK信号。
        SPI_I2S_SendData(SPI2, 0x51);   // 产生 CLK信号,启动传输
        while((SPI2->SR & SPI_SR_TXE) == 0);    // 等待发送完毕
    
        /* 结束通信 */
        SPI_Cmd(SPI2, DISABLE); // 传输结束,释放总线【注】,CLK进入IDLE状态(我设置的高)
        // 注:释放总线,即开漏的控制方式,不是强制拉高,只是相当于断开与CS(NSS)的连接。
        //     当然,slave设备的CS一般是有上拉的,所有放开后在没有其他master控制时,就是高。
    
        tmp = SPI_I2S_ReceiveData(SPI2);    // 查看 master 收到的数据
        tmp = SPI_I2S_ReceiveData(SPI1);    // 查看 slave 收到的数据
    
    }

    实验结果

  • 相关阅读:
    google code jam exercise——Your Rank Is Pure
    C/C++中的文件操作(2)
    google code jam exercise——File Fix It
    google code jam exercise——All Your Base
    C/C++中的文件操作(1)
    google code jam exercise——Center of Mass
    C/C++字符串操作split
    JavascriptDOM
    Javascript特权方法
    Report子报表
  • 原文地址:https://www.cnblogs.com/qiyuexin/p/8395496.html
Copyright © 2020-2023  润新知