你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32之IO口模拟SPI

[复制链接]
STMCU小助手 发布时间:2022-2-1 18:00
本文介绍如何使用STM32标准外设库的GPIO端口模拟SPI,本例程使用PA5、PA6和PA7模拟一路SPI。SPI有4种工作模式,模拟SPI使用模式0,即空闲时SCK为低电平,在奇数边沿采样。
本文适合对单片机及C语言有一定基础的开发人员阅读,MCU使用STM32F103VE系列。
' T7 k7 t* @8 B, y" U% U
1.   简介
SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在要求通讯速率较高的场合。SPI用于多设备之间通讯,分为主机Master和从机Slave,主机只有一个,从机可以有多个,通过片选信号对从机进行选择,一次只能选择一个从机。通讯只能由主机发起,支持的操作分为读取和写入,即主机读取从机的数据,以及向从机写入数据。
SPI一般有4根线,分别是片选线SS、时钟线SCK、主设备输出\从设备输入MOSI、主设备输入\从设备输出MISO,其中除MISO对于主机为输入引脚外,其他引脚对于主机均为输出引脚。因为有独立的输入和输出引脚,因此SPI支持全双工工作模式,即可以同时接收和发送。
2.    总线传输信号
  • 空闲状态:片选信号SS低电平有效,那么空闲状态片选信号SS为高。
  • 开始信号及结束信号:开始信号需要将片选信号SS拉低,结束信号需要将片选信号SS拉高。
  • 通讯模式:SPI有4种通讯模式,分别为0、1、2、3,根据时钟极性和时钟相位确定,时钟极性分别为空闲低电平和空闲高电平,时钟相位分别为SCK奇数边沿采样和偶数边沿采样。常用的模式为模式0和模式3。# F! W+ _8 b  s" Z3 j
SPI模式
时钟极性(空闲时SCK时钟)
时钟相位(采样时刻)
0
低电平
奇数边沿
1
低电平
偶数边沿
2
高电平
奇数边沿
3
高电平
偶数边沿
8 F. s* z" e* m% j$ i8 U

  [' v  J$ X- S7 H: |, ~3.    时序说明
以模式0举例说明:
  • 空闲状态:片选信号SS为高,SCK输出低电平。
  • 开始信号:片选信号SS变低,SCK输出低电平。
  • 结束信号:片选信号SS变高,SCK输出低电平。
  • 读取:SCK由低变高之后,读取MISO引脚信号。
  • 写入:SCK输出低电平,MOSI引脚输出相应的电平,然后SCK输出高电平。
  • 一个时钟周期同时读取和写入:SCK输出低电平,主设备控制MOSI输出相应电平,从设备控制MISO输出相应电平,然后SCK输出高电平,从设备读取MOSI引脚电平,主设备读取MISO引脚电平。即无论主设备还是从设备,均在SCK为低电平时输出信号,在SCK为高电平时读取信号。" O$ ^% V; z* I8 K. G% O
4.    初始化
初始化跟普通GPIO类似,SCK和MOSI设置为推挽输出,而MISO设置为浮空输入。
GPIO初始化完成之后,SCK置为低电平,进入空闲状态。
5.    模拟信号
由于SPI支持一个周期内同时读取和写入,因此读取和写入操作可以用一个函数实现,而单独的读取函数和写入函数可以通过调用该读写函数实现。
# J+ A: c* \4 y. {4 L7 j" y
完整代码(仅自己编写的部分)  v$ q6 e: q. `, u
  1. #define SPI_SCK_1    GPIO_SetBits(GPIOA, GPIO_Pin_5)            /* SCK = 1 */
      G- u% `; W6 r' }7 L% a/ l
  2. #define SPI_SCK_0    GPIO_ResetBits(GPIOA, GPIO_Pin_5)        /* SCK = 0 */
    # B& J) M7 F, Z( R6 w* J; W

  3. 9 k* v  H: C9 I% n8 Y# F+ i
  4. #define SPI_MOSI_1    GPIO_SetBits(GPIOA, GPIO_Pin_7)            /* MOSI = 1 */
    0 z7 ?0 N* s. |
  5. #define SPI_MOSI_0    GPIO_ResetBits(GPIOA, GPIO_Pin_7)        /* MOSI = 0 */
    : f7 b+ z- t4 L

  6. 2 S$ @; j4 ]+ x. Y
  7. #define SPI_READ_MISO    GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)    /* 读MISO口线状态 */
    0 p" e9 g: \' t' S) T
  8. # v. n8 q, _) t* a& V- D4 D2 K
  9. #define Dummy_Byte    0xFF    //读取时MISO发送的数据,可以为任意数据& U" [3 y- ^' B2 X8 \
  10. % X5 K2 \8 Z: C& f# P! w8 R' r
  11. 6 O3 \7 O7 {& x3 `/ f
  12. //初始化SPI
    " M' h2 M, F  g: C& A' o
  13. void SPI_IoInit(void)& i( u. {. h* `9 |
  14. {3 a4 B# Q+ {7 X( }3 F! `
  15.     GPIO_InitTypeDef GPIO_InitStructure;
    ( s5 Q8 t3 S  Y3 o* Q" D! l# q( [+ d
  16. % ~# [% Z& N" k/ ~6 J1 |0 |7 P
  17.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);$ v+ D& l0 D  r- M
  18. 7 w8 L2 y/ G9 c- K9 h! a, l
  19.     //CS引脚初始化& Y* L( N0 M2 m) ^# ?; S! h9 L
  20.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    $ k+ T- S* g$ L' A* e  g
  21.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;           //推挽输出  K$ j4 e+ `. p$ e
  22.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    0 A) V2 M7 W5 A+ P
  23.     GPIO_Init(GPIOC, &GPIO_InitStructure);* N4 d5 C6 `: ]; f

  24. ! a5 B8 O# N/ d9 A4 h* f  `
  25.     //SCK和MOSI引脚初始化
    ( |/ f5 n& O1 W" ~5 C
  26.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
    5 _) n- J& c% m$ l3 V. ?
  27.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;           //推挽输出
    $ h1 n  P3 Y9 u3 C
  28.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    6 [- I2 Q6 x5 ^3 E6 J7 |
  29.     GPIO_Init(GPIOA, &GPIO_InitStructure);
    & i. {' l/ `3 s- q6 \; R

  30.   x$ A" B" O( h' w2 r/ T
  31.     //MISO引脚初始化: F3 K- ~; d* i: d1 M
  32.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;0 X+ e4 [- T  Q- X4 L1 F
  33.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;               //浮空输入' k" b) R6 \* f$ A1 L
  34.     GPIO_Init(GPIOA, &GPIO_InitStructure);/ K- S/ T, ~5 t! f7 k
  35. 7 y* P1 ^2 H8 j+ H
  36.     SPI_CS_1;- o: L9 Z9 H' }  Q) X
  37.     SPI_SCK_1;7 N) P3 Z0 j) U
  38. }2 m1 P2 ~* r) ~' T) g8 l8 L
  39. ( m6 V+ r' [, f3 F
  40. //SPI可以同时读取和写入数据,因此一个函数即可满足要求$ I7 D6 V( X0 Q( f( X0 b) q
  41. uint8_t SPI_ReadWriteByte(uint8_t txData). y) |- z# [  E9 m7 n: r
  42. {
    : U9 A2 m  [* I9 h
  43.     uint8_t i;6 x6 j1 n) j* E4 f4 G
  44.     uint8_t rxData = 0;
    $ F5 i* Z$ ?; w# c! f' P/ [

  45. 1 E' I7 J0 t) V+ y
  46.     for(i = 0; i < 8; i++)
    1 @2 n% M8 C+ L2 f4 m9 F7 {# ~
  47.     {
    ' j, E$ \: x8 s
  48.         SPI_SCK_0;6 o9 X" `% Y3 w/ p( J; \! }
  49.         delay_us(1);
    * s6 R* L. q$ W
  50.         //数据发送
    ' ^; f" X4 ^8 r/ @
  51.         if(txData & 0x80){4 o4 C! b+ i# o# }: X9 g8 Q
  52.             SPI_MOSI_1;
    # v! o# o$ H* V8 Q* x
  53.         }else{* Q  {! P* H$ Z! u
  54.             SPI_MOSI_0;7 n; ^: ?) `& A8 C
  55.         }
    $ h+ }! G- l; h) r: u; u
  56.         txData <<= 1;
    6 M. L( W: @& a
  57.         delay_us(1);/ \" L2 u/ G0 a" t" O9 E
  58. 0 d$ L* S6 ^4 U
  59.         SPI_SCK_1;
    % u0 t/ D7 }4 H, |% g
  60.         delay_us(1);
    % N3 h6 c% i7 B6 b+ ^4 `
  61.         //数据接收/ |, [' f0 C) Z; `
  62.         rxData <<= 1;
    & e. S* w3 _. Z4 ~3 X: _6 L
  63.         if(SPI_READ_MISO){
    ! P: R' H0 M6 O
  64.             rxData |= 0x01;
    ' W3 r& s: {: O2 Y4 q2 a+ A
  65.         }2 G3 ~6 F: q; [3 A
  66.         delay_us(1);
    6 t! p% k6 I& W# i# O
  67.     }# V/ S3 O  p2 F$ c0 e6 |. ?% t
  68.     SPI_SCK_0;# ?" x# b/ |8 q" S# t2 S
  69. + W- i4 j  w( ~0 h
  70.     return rxData;
    % z% i) v, R* Y" n' c& b% H! ?6 D& f5 F
  71. }
    # @7 {; m: r+ \" M$ D. e

  72.   K3 O- k  x3 \1 |% n. H
  73. uint8_t SPI_ReadByte(void)
    ; \1 M0 d7 ]! F# h. }
  74. {
    ' C. o3 Z1 D6 S: w7 D& f
  75.     return SPI_ReadWriteByte(Dummy_Byte);; B+ z" C3 K* y* P! K
  76. }0 P0 M9 y" d7 v% q. Y
  77. 5 b' ~2 a2 {  k
  78. void SPI_WriteByte(uint8_t txData)) v4 K3 g0 k& V! E+ i# s
  79. {# J8 ~: s. y4 r3 G
  80.     (void)SPI_ReadWriteByte(txData);: s5 @% m. ~. N0 A
  81. }
复制代码
% ~4 j9 w1 h' k* }# }9 `8 h
" T' s2 V9 y2 ]; Q( c
收藏 评论0 发布时间:2022-2-1 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版