STM32 SPI通讯_摘自


  • 通信方式:高速全双工
    • 作用:  主机与从机之间同步交换数据 
    •   时钟:  最大18Mhz,支持DMA,可以配置SPI协议
  • 通信线
    •   MISO 主输入从输出
        MOSI 主输出从输入
        SCLK 时钟信号,主设备产生
        CS 片选信号,主设备控制

 

 

  • 协议层
    • 起始信号
      • NSS 信号由高变低
    • 终止信号
      • NSS 信号由低变高
    • 数据有效性
      • 采样:
        • MOSI 及 MISO 的数据在 SCK 的上升沿期间变化输出,在 SCK 的下降沿时被采样。
        • 即在 SCK 的下降沿时刻,MOSI 及 MISO 的数据有效,高电平时表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效,
      • 触发:
        • MOSI 及 MISO 的数据在 SCK 的上升沿期间变化输出,在 SCK 的下降沿时被采样.
    • 通讯模式
      • 共4种,区别于 SCK 的时钟状态以及数据采样时刻

 

 

 

  • SPI外设
    • 时钟:
      • SPI1 是 APB2 上的设备,最高通信速率达 36Mbtis/s,SPI2、SPI3 是 APB1 上的设备,最高通信速率为 18Mbits/s
    • 引脚
  • 通讯过程
    • (1) 控制 NSS 信号线,产生起始信号(NSS拉低,图中没有画出);
    • (2) 把要发送的数据写入到“数据寄存器 DR”中,该数据会被存储到发送缓冲区;
    • (3) 通讯开始,SCK 时钟开始运行。MOSI 把发送缓冲区中的数据一位一位地传输出去;MISO 则把数据一位一位地存储进接收缓冲区中;
    • (4) 当发送完一帧数据的时候,“状态寄存器 SR”中的“TXE 标志位”会被置 1,表示传输完一帧,发送缓冲区已空;类似地,当接收完一帧数据的时候,“RXNE标志位”会被置 1,表示传输完一帧,接收缓冲区非空;
    • (5) 等待到“TXE 标志位”为 1 时,若还要继续发送数据,则再次往“数据寄存器DR”写入数据即可;等待到“RXNE 标志位”为 1 时,通过读取“数据寄存器DR”可以获取接收缓冲区中的内容。
  • 处理收发数据
    • 中断方式
      • 使能TXE 或 RXNE 中断,TXE 或 RXNE 置 1 时会产生 SPI 中断信号,进入同一个中断服务函数,到 SPI 中断服务程序后,可通过检查寄存器位来了解是哪一个事件,再分别进行处理
    • DMA方式
      • 使用 DMA 方式来收发“数据寄存器 DR”中的数据。
  • 配置流程

    •   配置相关引脚的复用功能,使能 SPI2 时钟 ,设置 SPI2 的相关引脚为复用输出,这样才会连接到 SPI2 
    •   初始化 SPI2,设置 SPI2 工作模式 
    •   使能 SPI2 
    •   SPI 传输数据 
    •   查看 SPI 传输状态 

裸机--SPI--FLASH读写
  • 硬件连接
    • WP 引脚可控制写保护功能,当该引脚为低电平时,禁止写入数据。我们直接接电源,不使用写保护功能。
  • 指令表
    • 带括号的字节参数,方向为 FLASH 向主机传输,即命令响应,不带括号的则为主机向 FLASH 传输
    • 表中“A0~A23”指 FLASH 芯片内部存储器组织的地址;
    • “M0~M7”为厂商号(MANUFACTURER ID);
    • “ID0-ID15”为 FLASH 芯片的ID;
    • “dummy”指该处可为任意数据;
    • “D0~D7”为 FLASH 内部存储矩阵的内容。

 

  • FLASH操作
    • 一般流程
      • CS拉低
      • 发送指令
      • 操作数据
      • CS拉高
      • 等待
    • 扇区擦除
      • 只能把原来为“1”的数据位改写成“0”,而原来为“0”的数据位不能直接改写为“1”。在写入前,必须要对目标存储矩阵进行擦除操作,把矩阵中的数据位擦除为“1”,在数据写入的时候,如果要存储数据“1”,那就不修改存储矩阵 ,在要存储数据“0”时,才更改该位。
      • FLASH 芯片的最小擦除单位为扇区(Sector),而一个块(Block)包含 16 个扇区,
      • 流程:
        • 发送写使能
        • CS拉低
        • 发送擦除指令
        • 发送擦除地址
        • CS拉高
        • 等待擦除完毕
1 /**
2 * @brief 擦除 FLASH 扇区
3 * @param SectorAddr:要擦除的扇区地址
4 * @retval 无
5 */
6 void SPI_FLASH_SectorErase(u32 SectorAddr)
7 {
8     /* 发送 FLASH 写使能命令 */
9     SPI_FLASH_WriteEnable();
10     SPI_FLASH_WaitForWriteEnd();
11     /* 擦除扇区 */
12     /* 选择 FLASH: CS 低电平 */
13     SPI_FLASH_CS_LOW();
14     /* 发送扇区擦除指令*/
15     SPI_FLASH_SendByte(W25X_SectorErase);
16     /*发送擦除扇区地址的高位*/
17     SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
18     /* 发送擦除扇区地址的中位 */
19     SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
20     /* 发送擦除扇区地址的低位 */
21     SPI_FLASH_SendByte(SectorAddr & 0xFF);
22     /* 停止信号 FLASH: CS 高电平 */
23     SPI_FLASH_CS_HIGH();
24     /* 等待擦除完毕*/
25     SPI_FLASH_WaitForWriteEnd();
26 }

 

 

 

  • 页写入
    • 最多写入256字节
    • 一般以扇区单位进行读写
    • 流程
      • 发送写使能
      • CS拉低
      • 发送写指令
      • 发送写地址
      • 写入数据
      • CS拉高
      • 等待
1 /**
2     * @brief 对 FLASH 按页写入数据,调用本函数写入数据前需要先擦除扇区
3     * @param pBuffer,要写入数据的指针
4     * @param WriteAddr,写入地址
5     * @param NumByteToWrite,写入数据长度,必须小于等于页大小
6     * @retval 无
7 */
8 void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
9 {
10     /* 发送 FLASH 写使能命令 */
11     SPI_FLASH_WriteEnable();
12
13     /* 选择 FLASH: CS 低电平 */
14     SPI_FLASH_CS_LOW();
15     /* 写送写指令*/
16     SPI_FLASH_SendByte(W25X_PageProgram);
17     /*发送写地址的高位*/
18     SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
19     /*发送写地址的中位*/
20     SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
21     /*发送写地址的低位*/
22     SPI_FLASH_SendByte(WriteAddr & 0xFF);
23
24     if (NumByteToWrite > SPI_FLASH_PerWritePageSize)
25     {
26         NumByteToWrite = SPI_FLASH_PerWritePageSize;
27         FLASH_ERROR("SPI_FLASH_PageWrite too large!");
28     }
29
30     /* 写入数据*/
31     while (NumByteToWrite--)
32     {
33         /* 发送当前要写入的字节数据 */
34         SPI_FLASH_SendByte(*pBuffer);
35         /* 指向下一字节数据 */
36         pBuffer++;
37     }
38
39     /* 停止信号 FLASH: CS 高电平 */
40     SPI_FLASH_CS_HIGH();
41
42     /* 等待写入完毕*/
43     SPI_FLASH_WaitForWriteEnd();
44 }

 

 

  • 读取数据
    • 流程
      • CS拉低
      • 发送读指令
      • 发送读地址
      • 读取数据
      • CS拉高


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM