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

分享一个软件模拟SPI代码

[复制链接]
ctang 发布时间:2017-9-28 16:12
STM32电机培训online,大佬带你玩电机
+ l  D1 L' K* g1 C% T
5 `6 v* J* C5 t8 i
& z$ T7 D' B  e$ m3 T4 x- U* O因为硬件上连接到了普通的GPIO脚,不得不写软件模拟SPI,代码经过验证。如下:
  1. #ifndef __SPI_H
    # x. t/ c0 w" m5 z9 b, u
  2. #define __SPI_H9 K( \8 [: d% [$ {3 \
  3. & A* V$ X$ g! q5 i& C8 r+ O
  4. /* Includes ------------------------------------------------------------------*/  g5 M  [' I+ C1 l
  5. #include "stm32l0xx_hal.h"$ z% A0 ~8 ^% I9 A2 D
  6. ! X5 U. Z, c3 z, M3 Z; ?3 |
  7. #define SPI_SCK_PIN                     GPIO_PIN_4( T7 [$ ]& O: d7 J" x. m3 \3 S6 }
  8. #define SPI_SCK_GPIO_PORT               GPIOC
      N& @! K7 ]) x& _' I% R% z
  9. #define SPI_MOSI_PIN                    GPIO_PIN_7
    : S( [( ^( l9 T5 ?. j3 N
  10. #define SPI_MOSI_GPIO_PORT              GPIOC0 t# K( _  ?3 Q7 e
  11. #define SPI_MISO_PIN                    GPIO_PIN_8
    $ S. q4 y8 D( ?& v8 {0 K
  12. #define SPI_MISO_GPIO_PORT              GPIOC( b: k  |% ^, I% [: V6 n, z
  13. #define SPI_NSS_PIN                     GPIO_PIN_6* ~6 H% K( Z7 x5 O0 m4 S1 @2 ~
  14. #define SPI_NSS_GPIO_PORT               GPIOC1 s: }; |4 Y* e3 K
  15. #define SPI_RESET_PIN                   GPIO_PIN_5: j$ \% D9 x. E! u( {
  16. #define SPI_RESET_GPIO_PORT             GPIOC. n; D3 D6 J2 A( A' \
  17. " |. J& y9 H- h- J( ]
  18. #define SPI_SCK_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOC_CLK_ENABLE()
    , k: r# T4 _* _) p6 @$ T$ O
  19. #define SPI_MISO_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()
    5 C# v# o6 i0 N
  20. #define SPI_MOSI_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()% f6 D" f. E: N9 I  [2 h1 O$ R% E, O& H
  21. #define SPI_NSS_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOC_CLK_ENABLE()- U1 B/ i- |2 Q9 N: {
  22. #define SPI_RESET_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()# y5 @! @! h3 P0 }3 j

  23. 5 I! h' X- D* e6 L  q* p
  24. #define MOSI_H  HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET)  
    ! B$ B: S5 f; Z9 {$ V' y+ l) n/ ]
  25. #define MOSI_L  HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_RESET)  
    0 q; \% i# v+ P) k7 l. I. O( R. M
  26. #define SCK_H   HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET)  + i9 Q3 W: Z! e2 s% }  W
  27. #define SCK_L   HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_RESET)  
    * R2 J4 A1 e1 Z, r. ]
  28. #define MISO    HAL_GPIO_ReadPin(SPI_MISO_GPIO_PORT, SPI_MISO_PIN)
      u$ N; t$ Z" }
  29. #define NSS_H   HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET)  
    / ~3 F: k0 Z) T! W0 Y0 q$ W
  30. #define NSS_L   HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_RESET) 4 a" ?, L- S1 ]
  31. 0 @* c+ N# z  k
  32. 1 I, Y( q( f% b7 M% {
  33. #define EEPROM_DAC_START_ADDR   DATA_EEPROM_BASE+6             /* Start @ of user EEPROM area */
    6 p& P' A' c8 ?. c0 O  j5 k
  34. #define EEPROM_DAC_END_ADDR     (EEPROM_BIAS_START_ADDR + 16)   /* End @ of user EEPROM area */1 m2 u' t5 Z. _) o) Y
  35. #define IS_DAC_DATA_ADDRESS(__ADDRESS__)          (((__ADDRESS__) >= EEPROM_DAC_START_ADDR) && ((__ADDRESS__) <= EEPROM_DAC_END_ADDR))' c3 B. @. C# W0 p+ O9 J* x; y; R2 ?
  36. #define IS_DAC_CH_ADDRESS(__ADDRESS__)          (((__ADDRESS__) >= 1) && ((__ADDRESS__) <= 4))# y# r# r9 D% x/ S$ {

  37. 8 X$ z4 X% G- @2 z; h% ]
  38. void SPI_Init(void);' d  O# t  J+ @! [& @
  39. uint16_t SPI_ReadWrite_Byte(uint8_t cmd_addr, uint16_t data);
    9 I6 e" C/ d% \; w4 a; X2 P
  40. #endif
复制代码
; T+ q# o  I* }; v

. K7 C" R& }" \! T; L* h# Z; e7 A  H& }, {) |8 L2 j: q) V" E
  1. #include "spi.h"
    & N. t: H- U0 V6 [
  2. #include "main.h"
    4 {; B4 C* L" E1 [* e
  3. #include "stm32l0xx_hal.h"
    $ ]8 a6 [' C% P7 C) w/ B

  4. & P  k2 s4 E- F- @' h
  5. void SPI_Init(void)
    % o4 T2 v. r# @, x$ x0 p7 f+ z# W  X
  6. {  
    - W9 z- [0 k8 S9 C
  7.   /*##-1- Enable peripherals and GPIO Clocks #################################*/
      v- v; e5 }1 P: A
  8.   /* Enable GPIO TX/RX clock */
    * `* G! k/ `9 o* q
  9.   SPI_SCK_GPIO_CLK_ENABLE();: L/ d4 V0 I, l
  10.   SPI_MISO_GPIO_CLK_ENABLE();
    $ x& d$ e' D& W( W8 G' r, ?3 |) W0 O
  11.   SPI_MOSI_GPIO_CLK_ENABLE();; E" b4 `2 r! y. C
  12.   SPI_NSS_GPIO_CLK_ENABLE();
      ^6 P( O/ \. M0 @6 v
  13.   SPI_RESET_GPIO_CLK_ENABLE();8 |' o0 q2 b- U/ \4 b( q# L' `
  14. & _9 e$ ]2 t8 r6 ]5 Y8 Y( j
  15.   /*##-2- Configure peripheral GPIO ##########################################*/$ D+ Y( i' U. k4 ]8 B. L
  16.   /* SPI SCK GPIO pin configuration  */4 g% T+ e$ r( z1 a
  17.   GPIO_InitTypeDef GPIO_InitStruct;* r+ `" Z6 j! }" E
  18.   - {3 c& N* ~9 P8 q! t
  19.   GPIO_InitStruct.Pin       = SPI_SCK_PIN;0 h  g5 }2 P  r
  20.   GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;: J* R) i9 n+ \; O
  21.   //GPIO_InitStruct.Pull      = GPIO_PULLDOWN;
    : Z- E; [0 N; x5 J2 ]9 |
  22.   GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;* x: M& v% ]* L) k: G/ d  G
  23.   HAL_GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStruct);
    9 l8 y* B+ u% U$ [( \
  24.   HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET);- m0 ^3 e$ g/ y6 w1 P) z

  25. , W! S# T& p* X; j+ i' g
  26.   /* SPI MISO GPIO pin configuration  */
    " |# U( W& b8 l( d( J" u) O' w' G4 D
  27.   GPIO_InitStruct.Pin = SPI_MISO_PIN;. T, |3 h0 J4 ^7 ]! c) Q3 t
  28.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    # J8 C$ f0 t$ b1 n# @
  29.   HAL_GPIO_Init(SPI_MISO_GPIO_PORT, &GPIO_InitStruct);
    / _5 T5 j& D. ]" C3 f0 Y; h
  30. 4 O5 K2 h2 ]% A* B
  31.   /* SPI MOSI GPIO pin configuration  */
    ) X1 [$ ^& n6 {( f9 ?( k" u
  32.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;
    5 `# v% n3 }$ ^
  33.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;2 _# ]# p/ Q; I( `/ c) {: _) d
  34.   HAL_GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);
    7 x# @/ h6 @* l
  35.   HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET);
    3 g' p4 a: ~  T8 O$ ?/ P; k$ s
  36.   0 V7 k1 M; Q& b5 _# r4 t! k) k" E
  37.   GPIO_InitStruct.Pin = SPI_NSS_PIN;
    3 u* P' ?$ b, V5 H  K' |6 J7 ?
  38.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    + M' H* v$ r" m7 h) [9 Z* k4 o
  39.   HAL_GPIO_Init(SPI_NSS_GPIO_PORT, &GPIO_InitStruct);! C* C. O4 F- W8 M
  40.   HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET);. M6 w' o/ f3 S
  41.   
    / Q# ~! j2 r1 X, C' i5 g1 k) ]
  42.   GPIO_InitStruct.Pin = SPI_RESET_PIN;1 I7 t9 ?- @2 q/ B7 z
  43.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;1 _! l, q, n  u6 ]3 m; l5 Y, y. W4 R  _
  44.   HAL_GPIO_Init(SPI_RESET_GPIO_PORT, &GPIO_InitStruct);9 X7 T, x9 N7 [6 x: R* b) x6 r( Z
  45.   HAL_GPIO_WritePin(SPI_RESET_GPIO_PORT, SPI_RESET_PIN, GPIO_PIN_SET);- `0 b; d' ^5 o, i+ j$ s* j
  46. }
    5 e! Q4 J; Q' l* M5 L7 @( I
  47. 3 Y1 t2 ^: Y6 S, {/ B5 w' P+ e
  48. uint16_t SPI_ReadWrite_Byte(uint8_t cmd_addr, uint16_t data)
    4 [: l* L6 {/ K( ~+ ~0 k# l: v
  49. {  1 W8 T4 R' y) r: g1 T9 F  r
  50.   uint16_t temp=0;5 J; X/ A- m" d9 P! h6 n
  51.   SPI_Init();, Q/ r$ N3 j8 l. L$ i
  52.   NSS_L;  ' @3 o' Z2 [2 V, E, A; s% H% M
  53.   SCK_H;    * l- s% @/ g# p- A0 p
  54.   __NOP();             /*读取第一bit数据 等待数据稳定 根据实际时钟调整*/' v" o# I$ x6 P8 c3 |
  55.   for(uint8_t i=0;i<8;i++)+ R* W# O  t& H" g/ r
  56.   {   
    1 A; n& w% O/ s# D# ~8 X5 F
  57.     if(cmd_addr&0x80)
    % d' Q3 \& f3 |( v0 ?  S
  58.     {8 H3 n7 O$ v9 J/ d1 c. Y* N
  59.       MOSI_H;          /*若最高位为高,则输出高*/
    , k3 j9 q2 T8 E
  60.     }8 F, t6 V# d* t- `1 ~. Y& e' n9 r
  61.     else
    7 H) L: K% g5 Y* U) E) V/ K
  62.     {
    ; i/ ^4 D& X; X* t, c% k$ s$ K
  63.       MOSI_L;          /*若最高位为低,则输出低*/   
    $ D+ L8 B2 K. R0 R
  64.     }    . {# p0 w3 @/ y# l" |& w1 I2 \
  65.     __NOP();
    0 C4 Q7 W9 O! ~+ s2 C7 ?
  66.     cmd_addr <<= 1;2 b+ f- L1 P; P: [
  67.     SCK_L;
    ; O+ Y$ I0 H* G$ \( B
  68.     temp <<= 1;        /*数据左移*/
    4 l4 M* l- d0 g; `
  69.     if(MISO)8 I' |! y8 e6 [. K
  70.     {
    7 m+ e7 b, |8 D2 I# A/ j# L
  71.       temp++;          /*若从从机接收到高电平,数据自加一*/
    1 @0 P6 _( P8 F
  72.     }
    " @3 L# V: f, O- Y8 Y
  73.     SCK_H;
    6 }- c. |* h" ]
  74.   }
    & [2 ]1 T4 r/ U
  75.    
    3 z0 p2 N" C- q4 `8 J7 m6 y, u
  76.   data <<= 6;
    ; }( Z; t# u& G2 B$ k3 M
  77.   # I# f$ E$ |% q* E1 Q7 b' x
  78.   for(uint8_t i=0;i<16;i++)
    - u) _8 Z* k6 z8 S/ j
  79.   {   
    0 v) C+ L5 {* ~
  80.     if(data&0x8000) : _) P6 N( r' M, g8 n
  81.     {
    & [8 h& r' k: ]3 p3 b- u
  82.       MOSI_H;          /*若最高位为高,则输出高*/, e8 ?4 k" q  I" i
  83.     }
    : w9 z8 f8 z. ^1 E1 f
  84.     else
    3 |6 F3 E# X; S& w2 O# J1 v2 d
  85.     {
      m+ A2 Y8 X# J: Z
  86.       MOSI_L;          /*若最高位为低,则输出低*/   
    4 ^" q& ?. r% c3 g5 q% u
  87.     }    5 f  Y: {0 s9 I5 X5 i  {7 {
  88.     __NOP();
    " ?  I+ T% C0 \1 b* N4 A* \
  89.     data <<= 1;
    $ w; H, O$ @4 u6 |* J( v6 y% [
  90.     SCK_L;
    0 E  F8 u6 n4 M/ U! o
  91.     temp <<= 1;        /*数据左移*/% m) @" I8 X# \2 F2 C
  92.     if(MISO)4 }3 ^. ^# ~1 h/ D. H. N
  93.     {5 z) T! w0 `) \; x
  94.       temp++;          /*若从从机接收到高电平,数据自加一*/* }+ W9 |8 y. J& z2 n  @( ^( h- @
  95.     }
    ) N2 }0 {* H0 H8 z$ U
  96.     SCK_H;
      g! ?2 _6 ?; L
  97.   }
    . f; B; \+ ?  D0 I9 u
  98.   NSS_H;* L; T8 M8 n/ z! y! o8 X2 r
  99.   MOSI_H;
    2 k, z. H6 M1 c" _9 D9 I  K
  100.   return temp;! \0 [9 `; V" W: W! {1 ^5 j: m
  101. }
复制代码

! j" R6 P$ _  R& S# @2 F
1 ?' w( T! c' \7 o- e
赞 收藏 7 评论10 发布时间:2017-9-28 16:12

举报

10个回答
Inc_brza 回答时间:2017-9-28 16:25:16
谢谢分享
斜阳 回答时间:2017-9-28 16:38:23
谢谢分享
七哥 回答时间:2017-9-28 17:39:58
有个有用,谢谢分享
左岸右岸 回答时间:2017-9-28 18:57:27
谢谢分享
Paderboy 回答时间:2017-9-28 19:41:23
多谢分享。。。
epochal 回答时间:2017-9-28 21:47:23
谢谢分享!
五哥1 回答时间:2017-10-1 08:35:54
先谢谢楼主分享,楼主这个在神马芯片上测试成功过,可以移植到L系列吗?
ctang 回答时间:2017-10-9 09:21:22
本帖最后由 ctang 于 2017-10-9 09:25 编辑
4 S6 z' F9 l8 k
五哥1 发表于 2017-10-1 08:35
1 H6 j; }$ H# Z' p3 s/ X, l先谢谢楼主分享,楼主这个在神马芯片上测试成功过,可以移植到L系列吗?

! B8 H/ p2 u3 J; R! h- o: j在MCU STM32L073RZ上。移植的话,需要简单修改下SPI_ReadWrite_Byte函数,例子里面是按32bit为一个数据包发送的。
1 K) j( l/ ^7 Z  F% n: Q- W6 {4 {+ N
oceane 回答时间:2018-3-17 10:52:17
谢谢分享
  y' Z  `4 h1 V. w- L$ G& `
jianzhirao 回答时间:2018-3-17 13:38:52
谢谢分享

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版