首页 > 其他分享 >STM32 ---SPI通讯

STM32 ---SPI通讯

时间:2024-02-20 10:44:05浏览次数:34  
标签:--- SPI1 I2S STM32 SPI InitStructure Mode GPIO

I2C能够通过软件模拟,同样的,SPI通讯也可以通过软件模拟,具体需要掌握SPI的收发时序。但在本节,我们着重讲解STM32的硬件SPI外设。

 

我们知道SPI有以下几个特点

1、时钟频率:Fpclk /2,4,8,16,32,64,128,256 (Fpclk是时钟分频 ,APH2的Fpclk是72MHZ ,APB1的Fpclk是36MHZ)
2、支持多主机模型、主或从操作
3、可精简为半双工/单工通信
4、支持DMA
5、兼容I2S协议 (I2S是一种数字音频信号传输协议)

 

在STM32F103C8T6中,分别有 SPI1 、SPI2 硬件外设
SPI1挂载载APB2总线上,pclk是72MHZ(高速总线)
SPI2挂载载APB1总线上,pclk是36MHZ(低速总线)

 

相对于UART(串口),SPI和I2C是高位先行
比如要发送一个0x34
在SPI和I2C的波形上是 0011 0100 →
但在UART中, 波形是 0010 1100 ←

在SPI通讯中,不像I2C,需要发送和接收数据。在SPI中,数据是通过“交换”来实现通讯的。

通过MOSI(主出从入)和MISO(主入从出)两条数据线来传输数据的,如图。

 


在SPI通信中,TXE位和RXNE位是非常重要的两个标志位,TXE是数据传送完毕标志位,RXNE是数据接收完毕标志位。后面我们使用硬件SPI通讯时,需要通过这两个位来确定通讯进度。

 

先说说怎么准备去使用SPI通讯吧

/*-------------------------------------启动硬件SPI---------------------------------------*/
在硬件SPI中,完成代码只需要以下几个步骤
第一步:
开启时钟,开启GPIO和SPI的时钟
第二步:
初始化GPIO口,
SCK ,MOSI配置成复用推挽输出(硬件外设的输出信号,跟I2C一样要配置成复用推挽输出)
MISO配置成上拉输入(输入设备可能有多个)
SS,实验中是软件控制的输出信号,配置为通用推挽输出
第三步:
配置SPI外设,使用结构体配置即可
第四步:
开关控制,SPI_CMD使能

 

以下是常用的库函数,待会我们写代码需要用到这些

/*-------------------------------------SPI库函数---------------------------------------*/
//库函数主要使用到这些

SPI_I2S_DeInit();//恢复出厂配置
SPI_Init();//SPI初始化
I2S_Init();//I2S初始化
SPI_StructInit();//SPI结构体变量初始化
I2S_StructInit();//I2S结构体变量初始化
SPI_CMD();//SPI外设使能
SPI_I2S_ITConfig();//中断使能
SPI_I2S_CMD();//DMA使能
SPI_I2S_SendData();//写 DR数据寄存器
SPI_I2S_ReceiveData();//读 DR数据寄存器

SPI_I2S_GetFlagStatus();//获取标志位 ---主要用于获取TXE 和RXNE 标志位
SPI_I2S_ClearFalg();//清除标志位
SPI_I2S_GetITStatus();//获取中断标志位
SPI_I2S_ClearITPendingBit();//清除中断标志位

 

/*-------------------------------------硬件SPI代码---------------------------------------*/


void SPI_GPIO_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI1 ,ENABLE);//开启SPI1外设的时钟
RCC_APB2PeriphClockCmd(RCC_APB1Periph_GPIOA ,ENABLE);//开启GPIOA外设的时钟

GPIO_TypeDef GPIO_InitStructure ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽模式
GPIO_InitStructure.GPIO_Pin =GPIO_PIN_5|GPIO_PIN_7;//pin5和pin7作为SPI通讯的SCK 和MOSI引脚
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHZ;//50MHZ
GPIO(GPIO_A ,&GPIO_InitStructure);

GPIO_TypeDef GPIO_InitStructure ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;//推挽输出
GPIO_InitStructure.GPIO_Pin =GPIO_PIN_4;//pin4用于模拟SS引脚
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHZ;//50MHZ
GPIO(GPIO_A ,&GPIO_InitStructure);


GPIO_TypeDef GPIO_InitStructure ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//Input Pull UP上拉输出模式
GPIO_InitStructure.GPIO_Pin =GPIO_PIN_6;//pin6作为SPI通讯的MISO引脚
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHZ;//50MHZ
GPIO(GPIO_A ,&GPIO_InitStructure);
SPI_TypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主机还是从机, Master是主机 , Slave则是从机
SPI_InitStructure.SPI_Direction =SPI_Direction_2Lines_FullDuplex ;//SPI工作模式 :标准模式 -双线全双工
SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b ;//数字帧长度: 8Bit ,16Bit
SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_MSB ;//高位先行
SPI_InitStructure.SPI_BaudRatePrescalar = SPI_BaudRatePrescalar_128;//SPI波特率预分频器:2,4,8,16,.....256
SPI_InitStructure.SPI_CPOL =SPI_CPOL_LOW ;//时钟极性:High就是1 ,Low是0
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//时钟相位:1Edge第一个边沿(下降沿)触发 ,2Edge第二个边沿(上升沿)触发
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//NSS引脚设置:Hard硬件NSS模式,Soft软件NSS模式
SPI_InitStructure.SPI_CRCPolynomialS =7 ;//CRC校验的多项式:默认值7

SPI_Init(SPI1 , &SPI_InitStructure);

SPI_Cmd(SPI1,ENABLE);//SPI开关控制

MySPI_W_SS(1);//默认给SS输出高电平,默认不选择从机

}

uint8_t SPI_SwapByte (uint8_t ByteSend)//交换字节函数
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FALG_TXE) !=SET);//检测TXE
//在写入DR数据寄存器的时候,TXE标志位会自动清零
SPI_I2S_SendData(SPI1 ,ByteSend );//发送一个字节数据

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FALG_RXNE) !=SET);//检测RXNE

return SPI_I2S_ReceiveData(SPI1);//接受数据

}

 

 以上是STM32-SPI通讯的代码,欢迎纠错指正。

 

标签:---,SPI1,I2S,STM32,SPI,InitStructure,Mode,GPIO
From: https://www.cnblogs.com/xuegaogao/p/17790216.html

相关文章

  • because it set 'X-Frame-Options' to 'sameorigin'
    报错becauseitset'X-Frame-Options'to'sameorigin'.Refusedtodisplay'https://xxx.xxx.cn/'inaframebecauseitset'X-Frame-Options'to'sameorigin'.解决方法:修改页面,增加meta配置<head><!--CSP......
  • opengauss-流容灾两地三中心部署
    架构:两套cm,AZ1和AZ2为一套构建主备关系:按照标准部署步骤分别gs_preinstall,gs_install安装完成之后两套数据库后,执行以下部署:主集群gs_install执行完成,建复制用户:openGauss=#createuserhadr_userwithreplicationpassword'XXX';构建复制关系:[omm@omm1script]$g......
  • GitHub 热搜项目--电视直播软件:my-tv
    1.GitHub热搜项目1.1开箱即用的电视直播软件:my-tv主语言:C,Star:10k,周增长:6.9k这是一款开源、免费、无广告、不用注册的电视直播软件,适用于Android5及以上的手机和电视盒子。它安装即用、启动快,没有花里胡哨的UI和弹框,内置中央台、地方台等优质直播源,画质高清、播放流畅,......
  • c-jwt-cracker Jwt 密钥爆破工具的安装使用
    c-jwt-cracker  项目地址:https://github.com/brendan-rius/c-jwt-cracker BuildaDockerImagedockerbuild.-tjwtcrack RunonDocker  docker版使用方法dockerrun-it--rmjwtcrackeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODk......
  • 大年学习linux(第三节---用户管理)
    三、用户管理用户和用户组操作命令ldFingerPwck检查/etc/passwd配置文件内的信息与实际主文件夹是否存在,还可比较/etc/passwd和/etc/shadow的信息是否一致,另外如果/etc/passwd中的数据字段错误也会提示。Grpck和pwck功能相近,这个是检查用户组的。Groupsnewgrpuseraddus......
  • 大年学习linux(第四节---文件权限)
    四、文件权限文件类型Linux文件类型和linux文件的文件名所代表的意义是两个不同的概念。我们通过一般应用程序而创建的比如file.txt、file.tar.gz,这些文件虽然要用不同的程序打开,但放在linux文件类型中衡量的话,大多是常规文件。Linux文件系统类型:普通文件-rw-r-r--第一个......
  • 2024年,提升Windows开发和使用体验的实践经验 - RIME输入法
    前言上一篇文章介绍了Windows下的包管理器,本文继续介绍输入法。事实上Windows的输入法生态比Linux/Mac丰富很多,不过很多国产输入法存在窃取隐私、植入广告、乱安装流氓软件等问题,现在有开源的RIME输入法可以选择,何必受这气呢......
  • Programming Abstractions in C阅读笔记:p283-p292
    《ProgrammingAbstractionsinC》学习第72天,p283-p292总结,总计10页。一、技术总结1、anylasisofalgorithms算法分析——即判断程序的效率(efficiency)。2、mathematicalinduction(数学归纳法)3、Big-Onotation(大O标记法)4、constanttime(常量时间)5、lineartime(......
  • CF-928(已更新:B C E)
    CF-928排名四千多,目前为止排名最高的一场~E题我赛时基本上是猜的结论(但是也推了快一小时才想到有这个可能性),因此目前只能放个码在这(⊙﹏⊙)D的话问了学长思路,正在补了0-^-0……但是上一场牛客打得特别烂(⊙﹏⊙),还是等我补了牛客的再更新吧-^-B分析观察它的性质,答案为正方......
  • ARC172 - sol
    AtCoderRegularContest172A-ChocolateMs.AtCoderhasdecidedtodistributechocolatesto\(N\)friendsonValentine'sDay.Forthe\(i\)-thfriend\((1\leqi\leqN)\),shewantstogiveasquarechocolatebarofsize\(2^{A_i}\time......