• STM32 SPI协议


    SPI是一种串行,全双工,同步通信总线

    我们先解释下这几个名词,其实在前面的IIC USART中都有出现

    串行:要发的数据排成一排,一个(位)一个(位)的发,

    并行:要发的数据排成一排(8个或者16、32),一排一起发

    单工:单方向的接收或发送,比如电视

    半双工:可以接也可以发,但是同一时间一方只能选择 接 或者 发,比如对讲机

    全双工:收发信息是独立的,互不影响。比如电话

    同步:发送方和接收方用相同频率的时钟(有时钟线 比如IIC 和本文的SPI)

    异步:时钟并不是相同的,所以在每一次发送数据的时候,需要有开始位和停止位

    根线MOSI(SDO)  MISO(SDI)  SCLK  SS(CS)     (可能还会存在地线GND)

    MOSI 主设备输出 从设备输入 最大速度复用推挽输出

    MISO 主设备输入 从设备输出 上下拉输入

    SCLK 时钟线 只能由主设备输出 最大速度复用推挽输出

    NSS 选择主从设备 每个从设备可以选择自己的NSS

    SPI有种工作方式:

    通过配置CR1中的CPHA、CPOL从而选择不同的工作方式

    CPOL = 1 空闲是高电平;CPOL = 0 空闲是低电平

    CPHA = 0 第一个跳变时采样;CPHA = 1 第二个跳变时采样

    (在本文后面的示例代码中选择第一种工作方式)

    在SPI通信中,没有读和写的说法,它使用的是主从模式,你发出数据了,那就必然会收到数据回来,你要想收到数据,那你必须要先发出数据。

    因为SPI是串行同步通信,所以需要有一根时钟线,去提供脉冲频率

    在通信当中,时钟线的作用就类似于你军训时教官喊的口令121121,由时钟线告诉你,1 和 0 应该怎么发。

    代码如下 这是cotex-M3使用的代码

    /*
    函数功能:SPI2接口初始化
    */
    void Spi2_Pin_Init(void)
    {
        //IO功能配置
        RCC->APB2ENR |=0x01<<3;
        GPIOB->CRH &=~(0xFFF<<20);
        GPIOB->CRH |=(0xB8B<<20);
            
        RCC->APB1ENR |=1<<14;  //SPI2时钟使能
        SPI2->CR1 &=~(1<<11); //8位数据帧
        SPI2->CR1 |=1<<9;  //
        SPI2->CR1 |=1<<8;  //
        SPI2->CR1 &=~(1<<7);  //先发高位
        SPI2->CR1 &=~(0x7<<3);  
        SPI2->CR1 |=0x0<<3;  //波特率
        
        //从四种工作模式中选择一种
        SPI2->CR1 |=1<<1;  //时钟空闲状态为高电平
        SPI2->CR1 |=1<<0;  //在时钟第二个电平发送数据
        
        SPI2->CR1 |=1<<2; //主SPI
        
        SPI2->CR1 |=1<<6;     //使能SPI
        Spi2_Transfer_Byte(0xff);
    }
    
    /*
    函数功能:主机发送一个字节给从机
    注意事项:MODE0/3
    */
    void Spi2_Send_Byte(u8 data)
    {
        u8 i;
        GPIOB->ODR |= 0X1 <<13;                //SCLK=1
        for(i=0;i<8;i++)
        {
            GPIOB->ODR &= ~(0X1 <<13);        //SCLK=0//准备数据
            if(data&0x80) 
            {
                GPIOB->ODR |= (0X1 <<15);    //MOSI=1;
            }
            else 
            {
                GPIOB->ODR &= ~(0X1 <<15)    //MOSI=0;
            }
            GPIOB->ODR |= 0X1 <<13;            //SCLK=1
            data<<=1;//让次高位变成最高位
        }
    }
    
    
    u8 Spi2_Transfer_Byte(u8 data)
    {
        while(!(SPI2->SR&(0x01<<1)));            //TXE transmit buffer empty
        SPI2->DR=data;                    //在数据寄存器中写入数据
        while(!(SPI2->SR&(0x01<<0)));            //PXNE receive buffer not empty
        return     SPI2->DR;
    }
  • 相关阅读:
    ABAP 动态生成内表的几种方法
    abap 动态生成alv列
    abap 二分法检索
    选择屏幕abap , pararmeters,USER-COMMAND
    摘录 abap 数学函数
    abap SY-
    解决flex布局的space-evenly兼容性问题
    es6来实现封装、继承学习
    关于vue.js禁用浏览器返回问题以及路由的一些简单使用
    vue-cli 3.x搭建项目
  • 原文地址:https://www.cnblogs.com/qifeng1024/p/11753298.html
Copyright © 2020-2023  润新知