`
anlx27
  • 浏览: 497563 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

搞清 stm32 SPI总线 基础和编程(转)

阅读更多

现在flash那部分还没看明白 但感觉这挺好的,所以转来~

原文地址: http://blog.sina.com.cn/s/blog_4aa25f130100ssei.html

SPI应用是相当的广了,同步串行总线,同步同步当然需要时钟信号来统一了,这样通讯双方通讯时就比较默契没那么延迟(呆呆)了。应用于中低速场合。

学起来从哪些地方入手呢?如下:

SPI概念与特点   关键的时序接受    编程时重点     STM32内部的SPI使用(介绍、功能、中断)

SPI概念与特点:不多说,串行,需要同步信号   主从结构的   CS(片选)  SCK   SDI  SDO

                             全双工  一主控多从   816位数据通信.

其它特点:8个主模式波特率预分频系数  fpcll/2

                主模式和从模式下快速通行  并支持切换

                编程MSB LSB在前

                专用发送和接受标志可促发中断

                SPI忙标志位

         支持硬件CRC校验,发送模式下crc值作为最后一个字节被发送,接受模式下最后一字节自动CRC校验

         支持错误中断标志,支持DMA功能的1字节发送和接受缓冲器:产生发送和接受请求。

SPI总线时序介绍:

看下下图应该就会了



 
使用stm32  spi需要以下的步骤

1.管脚因为复用的,故先配置好管脚、并打开spi时钟

2.设置spi的工作模式

通过 SPI1_CR1 来设置,设置SPI1主机模式,设置数据格式8位,然后通过 CPOL CPHA 位来设置 SCK时钟极性及采样方式。并设置 SPI1 的时钟频率(最大18Mhz),以及数据的格式(MSB 在前还是 LSB在前)。
3.
使能SPI.

SPI固件库函数


 
下面是初始化,必须得结构体原型

typedef struct
{
  uint16_t SPI_Direction;//
设置方向     2线全双工、2线只接受、一线发送、一线接受)

  uint16_t SPI_Mode;     //模式         (从或主设备)

  uint16_t SPI_DataSize; //宽度         816位)

  uint16_t SPI_CPOL;     //时钟极性     (低或高)

  uint16_t SPI_CPHA;     //时钟相位     (第一个或第二个跳变沿)

  uint16_t SPI_NSS;      //片选方式     (硬件或软件方式)

  uint16_t SPI_BaudRatePrescaler; //波特率预分频    (从2---256分频)  

  uint16_t SPI_FirstBit;  //最先发送的位            (最低位,还是最高位在先)        

  uint16_t SPI_CRCPolynomial; //设置crc多项式        (数字)如7

}SPI_InitTypeDef;

下面是实例,对SPI2进行的初始化

void SPI2_Init(void) 
{
 SPI_InitTypeDef  SPI_InitStructure;
 GPIO_InitTypeDef GPIO_InitStructure;
 
 //
配置SPI2管脚

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);//
???
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14| GPIO_Pin_15;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //
复用推挽输出
 GPIO_Init(GPIOB, &GPIO_InitStructure);
 
 //SPI2
配置选项
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE);
   
 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
 SPI_InitStructure.SPI_CRCPolynomial = 7;
 SPI_Init(SPI2, &SPI_InitStructure);
 //使能SPI2
 SPI_Cmd(SPI2, ENABLE);  
}

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

以上是,初始化的一些函数,发现固件库还有很多函数没用上,下面就要谈到应用了

STM32SPI串行外围总线接口,本程序,是将STM32SPI配置为全双工模式,且NSS使用的软件模式。在使用SPI前,下面的这个过程我们必须理解,即STM32作为主机发送一个字节数据时,必然能接收到一个数据,至于数据是否处理,由程序操作。

● 全双工模式(BIDIMODE=0并且RXONLY=0) 

─  当写入数据到SPI_DR寄存器(发送缓冲器)后,传输开始; 

─  在传送第一位数据的同时,数据被并行地从发送缓冲器传送到8位的移位寄存器中,

然后按顺序被串行地移位送到MOSI引脚上; 

─  与此同时,在MISO引脚上接收到的数据,按顺序被串行地移位进入8位的移位寄存器

中,然后被并行地传送到SPI_DR寄存器(接收缓冲器)中。 

注意:也就是说,在主机模式下,发送和接收是同时进行的,所以我们发送了一个数据,也就能接收到一个数据。而STM32内部硬件是这个过程的支撑!



 

读一个字节,往里面发送0,外设就返回一个数据了,发送的0外设不处理(需要先写入命令生效)

#define SPI_ReadByte(SPIx) SPI_WriteByte(SPIx,0)

写一个字节就直接发送相应的字节,外设就返回一个数据了

u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 byte);

//spi 写一个字节...................................................................
u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)
{
 while((SPIx->SR&SPI_I2S_FLAG_TXE)==RESET);  //
等待发送区空
  
 SPIx->DR=Byte;   //
发送一个
byte  
 while((SPIx->SR&SPI_I2S_FLAG_RXNE)==RESET);//
等待接收完一个
byte 
 return SPIx->DR;                //
返回收到的数据
   
}



 
void M25P16_Write_Enable(void)
{
 Select_Flash(); 
 SPI_Flash_Write(WRITE_ENABLE); 
 NotSelect_Flash();
}

void M25P16_Read_Id(u8 * id)
{
 u8 i;
 
 Select_Flash(); 
 SPI_Flash_Write(READ_ID); 

 for(i=0;i<20;i++)
 {
  id[i] = SPI_Flash_Read(); 
 }
 
 NotSelect_Flash();
}

void M25P16_Write_Status_Reg(u8 reg)
{
 Select_Flash(); 
 SPI_Flash_Write(WRITE_STAUS_REG); 
 SPI_Flash_Write(reg);
 NotSelect_Flash();
}

 

void M25P16_Read_Data(u32 addr,u32 len,u8 *buf)
{
 u32 i;
 Select_Flash(); 
 SPI_Flash_Write(READ_DATA); 
 SPI_Flash_Write((addr>>16) & 0xff);
 SPI_Flash_Write((addr>>8) & 0xff);
 SPI_Flash_Write(addr & 0xff);
 for(i=0;i<len;i++)
 {
  buf[i]=SPI_Flash_Read();
 }
 NotSelect_Flash();
}

 

//页编程函数,页编程前一定要进行页擦除!!!
void M25P16_Page_Program(u32 addr,u16 len,u8 *buf)
{
 u32 i;
 
 M25P16_Write_Enable();
 Select_Flash(); 
 SPI_Flash_Write(PAGE_PROGRAM); 
 SPI_Flash_Write((addr>>16) & 0xff);
 SPI_Flash_Write((addr>>8) & 0xff);
 SPI_Flash_Write(addr & 0xff);

 for(i=0;i<len;i++)
  SPI_Flash_Write(buf[i]);

 NotSelect_Flash();

 while(M25P16_Read_Status_Reg()&0x01); 
}

 

以上函数搞懂了,特别市红色部分标注的为重点,对于spi也就基本清楚了,这些也算是最底层的函数了,提供基本的API供以后文件系统或其它地方使用。

 

----------------------------------------------------------------------------------------------

最后补上一些文件框架的说

首先我们把最底层的SPI初始化写上,函数如下:



 
可见有芯片自带SPI模块  有给mp3芯片的,有给flash的,还有给无线网络的,还有给软件模拟spi时序供给触摸屏的控制器的,然后我们把这个.c文件配套的.h文件给下面具体的函数包含,就能正确的选取和使用了,当这些具体功能的函数写好了后,对应得.h函数就又继续给更高级别的应用层使用。

今天先就介绍下spi_flash模块了,等天补上其它3个模块的讲解,毕竟现在是基础哦。

 

  • 大小: 51.2 KB
  • 大小: 13.2 KB
  • 大小: 16.4 KB
  • 大小: 9.8 KB
  • 大小: 334 KB
分享到:
评论

相关推荐

    STM32 SPI实验

    SPI通信通常涉及主设备(Master)和从设备(Slave),在STM32中,主设备通常由STM32芯片自身扮演,而从设备可以是各种SPI兼容的外围设备。SPI总线由四条信号线构成:SCLK(时钟)、MISO(主设备输入,从设备输出)、...

    M25P64_FLASH.zip_spi stm32_stm32 m25p64_stm32 spi_stm32 spi flas

    STM32 SPI for stm32f103

    STM32F+mcp2515 SPI转CAN通讯

    10. **编程框架**:常见的STM32开发环境有Keil uVision、IAR Embedded Workbench、STM32CubeIDE等,它们都提供了完善的库函数和API,简化了STM32与MCP2515的SPI通讯实现。 综上所述,STM32F结合MCP2515实现SPI到CAN...

    STM32 SPI总线驱动代码

    STM32 SPI(Serial Peripheral Interface)总线是一种广泛应用于微控制器中的串行通信接口,...总的来说,STM32的SPI驱动代码是连接和控制外部SPI设备的关键,熟练掌握其编程方法将极大地扩展STM32应用的范围和灵活性。

    11-1_1.14寸IPS屏stm32硬件SPI_SPI驱动+DMA_1.14寸_SPI屏DMA_stm32spiDMA

    标题中的“11-1_1.14寸IPS屏stm32硬件SPI_SPI驱动+DMA_1.14寸_SPI屏DMA_stm32spiDMA”表明这是一个关于使用STM32微控制器通过硬件SPI(Serial Peripheral Interface)并结合DMA(Direct Memory Access)驱动1.14英寸...

    stm32 SPI_SD驱动

    STM32 SPI_SD驱动是基于STM32微控制器与SD卡之间进行通信的一种技术实现,主要利用了STM32的SPI(Serial Peripheral Interface)接口来与SD卡进行数据交换。在嵌入式系统中,这种驱动对于实现文件存储、数据记录等...

    Stm32Spi_spi_stm32_

    本教程针对初学者,将详细介绍如何在STM32上进行SPI通信的编程。 SPI是一种全双工、同步串行通信协议,由主机(Master)和从机(Slave)组成,通常用于连接微控制器和其他外围设备,如传感器、A/D转换器、闪存等。...

    STM32F030SPI从机程序完美,stm32spi从机的配置,C/C++

    在这个项目中,我们将重点讨论如何在STM32F030上实现SPI(Serial Peripheral Interface)从机模式的程序设计,包括基本的SPI配置、C/C++编程以及硬件交互。 首先,SPI是一种全双工、同步串行通信接口,通常用于连接...

    两个STM32的SPI通信

    两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32的SPI通信 两个STM32...

    stm32SPI代码

    在这个“stm32SPI代码”中,我们可以期待找到一个预配置好的STM32工程,它包含了实现SPI通信功能的代码,并且有详细的注释以帮助理解和学习。 首先,我们要了解STM32中的SPI工作原理。SPI是一个全双工协议,数据...

    ALIENTEK MINISTM32 实验20 SPI实验_stm32堵转_STM32+TMC5160_stm32_tmc516

    在本实验中,我们将深入探讨如何使用ALIENTEK MINISTM32开发板与TMC5160驱动芯片进行SPI通信,实现...通过分析和实践这些文件,你将能够更深入地理解STM32与TMC5160的配合使用,为后续的电机控制项目打下坚实的基础。

    STM32-SPI数模转换ad7685_STM32F103_stm32ad7685_ad7685_popular5ya_

    STM32-SPI数模转换ad7685_STM32F103_stm32ad7685_ad7685_popular5ya_ 这个压缩包文件涉及的知识点主要集中在STM32微控制器与ADI公司的AD7685数模转换器之间的SPI通信应用上。下面将详细介绍这两个核心元件以及它们...

    STM32 SPI双机通信.zip_STM32 SPI从机_stm32 spi 主从机_stm32F0 SPI_stm32双机通

    stm32f0使用spi实现主从通讯,可以实现主主机发送和从机发送

    STM32-SPI.zip_STM32控制SPI_stm32 spi_stm32f103 spi_总线控制

    总的来说,STM32F103通过SPI与外设通信涉及硬件配置、寄存器编程、中断处理等多个方面,需要对STM32的HAL库或LL库有一定的了解。在具体应用中,开发者还需要考虑通信速度、数据校验以及错误处理等因素,确保SPI通信...

    基于 STM32 的 SPI 通讯

    总结,基于STM32的SPI通信涉及硬件配置、数据传输和软件编程等多个环节。理解SPI协议的基本原理,掌握STM32的SPI接口寄存器设置,以及熟悉Keil编译环境的使用,都是实现SPI通信的关键。在实际项目中,我们需要根据...

    STM32 SPI 测试程序

    STM32 SPI(Serial Peripheral Interface)测试程序是用于验证和调试STM32微控制器上SPI接口功能的一个实用工具。SPI是一种同步串行通信协议,广泛应用于各种嵌入式系统,如传感器、显示设备、存储器等。在STM32系列...

    stm8 SPI 总线协议

    stm8 SPI 总线协议

Global site tag (gtag.js) - Google Analytics