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

基于STM32F030硬件SPI经验分享

[复制链接]
攻城狮Melo 发布时间:2023-3-30 17:02
使用的是STM32F030F4P6,这是一个小封装的单片机,但是五脏俱全,很多功能,就是引脚不多。使用到SPI的时候感觉应该和以前用过的STM32F103系列是一样的,寄存器的结构几乎是完全一样的,寄存器操作的程序甚至都能兼容,但是在使用的时候就是调不通,耽误了不少时间。8 p- i% S" _4 f

/ X/ Q) q! W: ^( W' bSPI的引脚初始化和配置代码:
3 D1 K+ L  a6 B; S( ~+ F% ]% o
  1. GPIO_InitStructure.GPIO_Pin = nIRQ_PIN;// | GPIO1_PIN | GPIO2_PIN;
    . B; V& Q3 k9 b7 N1 j6 I
  2.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;5 z0 {4 [- W# F' m! J' v( E/ r7 d
  3.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    5 a+ F" z$ J0 l( K9 E6 G3 d; E- `- V
  4.         GPIO_Init(GPIOA, &GPIO_InitStructure);
    ; |' H- R1 q! s3 O- [
  5. 7 h( ~7 L" ]1 c/ N5 s
  6.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    3 O0 T' d% b4 T0 y8 C- }
  7.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;3 Z. |1 F9 Y. Y6 x
  8.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;' m5 ~' A+ O, H! E2 w/ D: N) S% E
  9.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    " N' W! L( G5 v& s% V
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 \" E4 y4 b( `( `
  11.         GPIO_Init(GPIOA, &GPIO_InitStructure);& g# s0 {( K  W  e' b, |! R

  12. , Z; c. l$ `; W& ?: n
  13.         GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_0);
    + j. Z. i9 F$ I' ?" T' H5 ~+ F( G# z
  14.         GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_0);/ [) ]  [: n* v# J  Y& V
  15.         GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_0);
    + `$ E; G6 D) t  S& k: }

  16. " K. H1 i& \- O
  17.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);- @: \6 X& o/ {0 g% B
  18.         SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    % c: x/ L2 ]0 c6 w9 ^! t% Z( w7 E
  19.         SPI_InitStruct.SPI_Mode = SPI_Mode_Master;% x0 {  `  E2 D2 S, G0 P2 H% b. k
  20.         SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;: x; _  d) Z  ~1 r- `
  21.         SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;! {* N0 f8 L5 d  F8 S
  22.         SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
    / B) F: F9 E" {# x
  23.         SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
    : [! d8 b! v  M
  24.         SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    " g; y! \3 W  R8 F- r$ t* Y
  25.         SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
    / }6 r6 p# _' _( r& ?  x
  26.         SPI_InitStruct.SPI_CRCPolynomial = 7;    //CRC 校验7 G! w8 c3 Z; t3 [. P. ?
  27.         SPI_Init(SPI1,&SPI_InitStruct);/ i5 O; w7 @  Z1 C  D, \* J; F; P( R
  28.         SPI_Cmd(SPI1,ENABLE);
复制代码
: r! w9 }# n% g# J# F( I+ t" _- I* |
上面的代码检查了1000遍了,没有问题,SPI的收发函数也是从STM32F103系列单片机上移植过来的:
/ V% }6 W8 X& i, {
  1. u8 SPI_RW(SPI_TypeDef* SPI,u8 TxData)4 T4 U1 P: _2 D
  2. {3 }) J: {$ c$ T) ~% F, z
  3.         u16 retry=0;; Q7 t1 [9 f# ^4 T
  4.         while((SPI->SR&0x0002)==0)                //等待发送区空                          ; M5 l* g# }# t0 a  c# }
  5.         {
    : q/ L; Q# w/ ^
  6.                 retry++;2 V! W: G' {& b5 {
  7.                 if(retry>=200)return 0;                        //超时退出
    " `  N2 l, _1 [& E4 K7 M, q
  8.         }
    - e7 p+ |* m/ @
  9.         SPI->DR=TxData;                                                           //发送一个byte 5 B9 U5 H. F% [7 v
  10.         retry = 0;
    9 o: l, ~8 G, _4 S
  11.         while((SPI->SR&0x0001)==0)                 //等待接收完一个byte  + c$ G# n0 h3 C0 Q9 t" j  J# B& X8 f
  12.         {) u: r: o. {8 o2 N( Y9 K8 r
  13.                 retry++;& [; |* a" ]4 H5 s) l7 O  M7 G+ q
  14.                 if(retry>=200)return 0;                        //超时退出! U+ Q) O* I6 u7 F1 t# _3 L, K
  15.         }3 T9 |* p" {+ K: q
  16.         return SPI->DR;                                  //返回收到的数据                                    % r. I( ~& J- F4 q( E% J: e9 m
  17. }
复制代码

1 [% R$ C8 ~! h% s; N4 m7 m1 D) z用上面这个函数操作芯片的时候写入的数据和读出的数据是不一样的,怎么修改SPI的配置都不行......经过了很长时间,找不到问题,用逻辑分析仪查看一下波形吧......随便抓取了一个“SI4432_WR(0x00, 0xFF);”的执行波形如下:$ |/ ]. U/ V. e- `& F$ @* ~- a

& d+ M' {9 h9 u6 }* i5 B9 h
2020030315323666.png
5 u( |. G( Z. M
* G5 B' g3 Y9 t, q6 W8 Y" X' G1 f/ F; U
上图信号分别为CS、SCK、MOSI和MISO,可以看到执行一次SI4432_WR函数SCK引脚发送了16个脉冲,按道理是8个脉冲才对,郁闷的一笔。然后是在没辙了,我把SI4432_WR函数改了一下(注释超时部分不影响),将发送部分从
! \  g0 h  @. h% \! v% ?" ~) {" Q0 e! Z  W% e8 ?: s
SPI1->DR = data;
1 O. N  Q* `7 p. A7 A4 `9 R; _5 ?9 v* D1 q& A. ?  q' S3 @
改成; D0 f6 @7 }; ?: C

, I! j0 d1 Z8 c, X *(uint8_t*)&(SPI1->DR)=data;
8 x* A' P. I9 q* v
& k5 [; d+ o: m; I+ a* D5 ?0 N意思就是访问SPI1->DR的时候以byte类型访问。6 h  j+ v" z7 w9 I
  1. u8 SPI_RW(u8 data)
    0 C5 W9 v  o7 P3 K6 ~# B% T4 k
  2. {
    0 N/ d% k$ z2 I" b/ c6 @# t% L
  3.         u16 retry=0;7 I& s5 `) f1 E3 A3 d
  4.         while((SPI1->SR&SPI_SR_TXE)==0)                //等待发送区空                          
    ! @  Q7 f4 `. ^9 Q# d2 @
  5.         {
    7 p& Q/ r* W$ V) l
  6. //                retry++;
    0 b+ w( m  p9 f! Q
  7. //                if(retry>=200)return 0;                        //超时退出5 x1 i9 I* d+ a4 z3 L6 n+ l# u1 ^# G/ [' q
  8.         }- b- U# L/ s8 o0 ]  `
  9.         *(uint8_t*)&(SPI1->DR)=data;                //发送一个byte ( ]6 w. ?' L' z3 R
  10.         retry = 0;
    , m" D8 o+ v' P8 ?6 c( I; n
  11.         while ((SPI1->SR&SPI_SR_BSY))                 //等待接收完一个byte  + }' w* Z! M% N, {* e( P- m
  12.         {
    ! k; O2 d9 i0 J9 s* U
  13. //                retry++;" I" e* g- @  O$ }) I- Y" D
  14. //                if(retry>=200)return 0;                        //超时退出
    7 K0 b% L) S7 x, ?* f# u
  15.         }
      b$ m, o  L6 g. {8 w/ L/ E
  16.         return SPI1->DR;                //返回收到的数据                                    * Z/ K% z* ^# B# ~  T
  17. }
复制代码
& y4 t" R4 x/ O' t
依然抓取了“SI4432_WR(0x00, 0xFF);”的执行波形,第一张图为SI4432_WR函数发送地址数据0x00,第二张图为SI4432_WR函数发送0xFF(随意)产生8个脉冲读取寄存器数据:2 s& \7 f0 o5 f" K+ o* n
$ }7 C3 T, _7 H1 r
20200303153725685.png
* q$ p. f% q% t  z+ Y. c& g" f, h. u( l4 N6 H* r6 p/ Q3 E
20200303154003796.png 8 G" \) ^( V) C$ L4 j2 f
2 \3 y& M' q# W3 U
按道理读出的数据应该是0x08,但是程序结果读到的数据都是0x00,也就是总线是对的了,但是还是没获得到正确的数据,在回到SI4432_WR函数,发现后面的返回过程中:
$ o% @8 f6 p3 Q9 u
* T' f! |7 \% c
return SPI1->DR;6 R0 [$ E$ X7 i6 N
8 E8 D( o- Y* d  g8 [+ L; t2 Y& h8 X
我再将它改成:
. c% n- O0 `* ?0 G3 ^
& S& M. e" r) Z4 E3 b& }, O# C2 Mreturn *(uint8_t*)&(SPI1->DR);# ~, c# j7 w" ~( R  t; ]

# |- X9 X6 A) }* w然后程序的确就没问题了。! m; C8 C) i* \6 t+ N" c
————————————————
& a& E" y) h0 ?- I% M) O* M版权声明:哐哐哐 Quan
  K7 t/ x* X5 O6 z- d- A0 b. b如有侵权请联系删除7 k8 [- _$ [2 R8 C' b5 u7 b
9 _/ ]7 Z5 j; j; k- l4 v

' O( w) J$ \6 D8 V. J
收藏 评论0 发布时间:2023-3-30 17:02

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版