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

STM32单片机应用笔记 (三) SPI通讯

[复制链接]
STMCU小助手 发布时间:2020-12-30 11:24
STM32单片机应用笔记 (三) SPI通讯
stm32f103单片机SPI通讯代码:
  1. static void bsp_GPIO_Init(void)& t1 G! |7 k0 T
  2. {- v4 B( `  \  k
  3.   GPIO_InitTypeDef GPIO_InitStructure;/ C# m1 F2 ^3 B
  4.   EXTI_InitTypeDef EXTI_InitStructure;# @, g( ^& w! z) N) M1 t
  5.   
    8 r/ W1 }3 x6 j3 w7 v, ]: q
  6.   RCC_APB2PeriphClockCmd(  RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);   //开外设时钟
    - S3 T- {+ ]+ v$ r1 J1 I
  7.   GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);                                              //关闭jtag开sw
    * C+ I: \5 J8 l) s
  8.   
    # O  M5 v  N/ ]; `8 p- i% d
  9.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_5 | GPIO_Pin_7;                                                  // SCK  MOSI8 z' @( K4 Y$ n
  10.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;" O, ?# J" n6 v, K! A& Q* U
  11.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_AF_PP;
    2 \3 L: T# G8 }) L& s& J- C+ O
  12.   GPIO_Init(GPIOA, &GPIO_InitStructure);" y8 Q! q# o+ Q% T! b
  13.   7 P( _: R. `/ w# I! ~' x- u
  14.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_6;                                                              //MISO
    / y+ c2 o% [3 q& U$ l2 a
  15.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;/ f5 C  a5 [7 Y& d
  16.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
    " F/ L  a: ~2 N# D6 a, g
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);  # R: B- W- B1 d: w, k! _
  18. }1 s0 z# d2 @( S7 z3 ^* b- h
  19. 7 z- T+ i6 V0 u! z% F+ j4 r
  20. static void bsp_SPI_Init(void)! ]- C7 j$ X; ?0 f6 `8 r. A
  21. {0 Q( |/ S$ i! b  n
  22.   SPI_InitTypeDef  SPI_InitStructure;- D, |( c# ^$ @: a. W
  23.   ; j, I, U7 [% J  P+ g
  24.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);* K8 V1 v2 s0 U6 G/ D
  25.   0 R% W1 K6 T% Y2 \  P1 _8 Q
  26.   SPI_InitStructure.SPI_Direction       = SPI_Direction_2Lines_FullDuplex;            //工作模式(双线或者单线)  k* k3 V: [: @( i
  27.   SPI_InitStructure.SPI_Mode         = SPI_Mode_Master;                          //主机模式+ d# o! `- y; @; a, z4 q; t
  28.   SPI_InitStructure.SPI_DataSize       = SPI_DataSize_8b;                          //8为数据传输
    7 `+ E; [/ i# b6 w
  29.   SPI_InitStructure.SPI_CPOL         = SPI_CPOL_High;                            //时钟不工作时的状态
    3 K6 p" I* D9 y* l* ?! v% B
  30.   SPI_InitStructure.SPI_CPHA         = SPI_CPHA_1Edge;                          //有效触发的边沿( H( j% Y+ |5 K1 O' q
  31.   SPI_InitStructure.SPI_NSS           = SPI_NSS_Soft;                              //片选软件触发$ D/ }- e2 P  w' w% z% m! R2 t# s
  32.   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;                //spi时钟频率
    ! ?% ]3 g2 U1 a* Y3 H
  33.   SPI_InitStructure.SPI_FirstBit         = SPI_FirstBit_MSB;                          //高位优先9 ~/ S0 L5 ~& Y  y0 ?3 j
  34.   SPI_InitStructure.SPI_CRCPolynomial   = 7;                                      //CRC(默认的是7)! Z* ~/ A& Y8 Z
  35.   SPI_Init(SPI1, &SPI_InitStructure);( `5 H" R8 l9 e6 m5 P

  36. 9 c5 K1 k5 I9 x/ V$ G/ a& q
  37.   SPI_Cmd(SPI1, ENABLE);# o) R+ U7 X& v$ D5 \' F. @
  38. }2 n9 k" I3 l9 I' U4 |
  39.   I! G# c; M2 `) a& t% t
  40. , J# f+ E9 o3 k
  41. u8 bsp_SPI_ReadWriteByte(u8 txdata)
    % z; c# v: [7 u9 l9 I
  42. {: a$ L  c# J: ]1 \
  43.   u8 waitcnt = 0;
    2 D) Y4 o' ^9 m3 m6 H, L0 L3 K
  44.   
    $ K0 V! ?8 y0 R4 Y# f
  45.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);                      //等待发送区空
    0 r$ v, ]5 f: K+ U9 E
  46.   SPI_I2S_SendData(SPI1, txdata);  & m7 F9 T* r# y! ~
  47.   
    * |2 k0 J$ B& _' L8 Q4 K
  48. //  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
    ' N; P& B6 h4 W5 Q0 x
  49.   while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET)* p/ {* s: H) V" T* e4 M
  50.   {
    6 _* c& B$ X, S. S: M. S8 d
  51.     waitcnt++;5 T& c( M" H$ S6 X7 {  ^2 t* z* s0 u( O
  52.     if(waitcnt >= 200)3 F) s+ e4 E6 v2 x% E
  53.       return 0;
    5 y: q2 @. J9 x* [  w1 {0 W
  54.   }
    7 }$ Y  d! n- L
  55.   ! a3 {# l" T1 I1 S4 G" p
  56.   return SPI_I2S_ReceiveData(SPI1);
    ( e2 U; `/ k7 o$ q
  57. }
复制代码
# m+ \- V# b6 P
以上代码是使用stm32自带的SPI模块功能,数据的收发使用查询的方式,没有使用中断功能。工作中使用SPI一般是控制LED灯的驱动芯片,ADC采样芯片以及DAC芯片,都属于那种定时的读写或者有某种触发条件读写的情况,因此基本没使用过SPI的中断以及SPI的DMA功能。
下面的代码是使用IO口模拟SPI功能:
  1. /*****************************************************************
      c2 p* R! L: C6 t! l+ V& D1 k
  2. 函数名称:SPI_GPIO_Conf5 P8 w# r4 a* {
  3. 函数功能:spi引脚配置6 V8 r+ w9 h, G, e% ?( E2 u
  4. 输    入:无+ a( j1 C, J  `
  5. 返    回:无' G" U- _# ^, o' O' `
  6. ******************************************************************/
    8 A/ n8 d( d) G6 v( D* r, b
  7. void SPI_GPIO_Conf(void)
    . l9 H/ l# s! m3 S+ ^7 Y2 S7 F0 c( b
  8. {- m2 B6 Y0 A( J) P( }  Z2 _  O, r6 f
  9.   GPIO_InitTypeDef GPIO_InitStructure;
    $ ?5 B. ^: g! C& Z' Y4 E
  10.   
    ) H' b/ o3 R+ M2 ?4 J) C3 P
  11.   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;1 w: `) F1 x2 N5 K! q. j
  12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    5 w+ X1 r- I0 o, d  r. ~
  13.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    9 {9 v9 e# G( k& {2 T4 ?- |
  14.   GPIO_Init(GPIOB,&GPIO_InitStructure);, {! m9 e' W$ r
  15.   - j( D: w: _# y) U" X
  16.   SPI_OE(0);                      //片选-使能芯片
    / c' t1 T% Y6 f3 W( Y
  17.   SPI_CLR(1);                     //清除寄存器
    ) H$ _. y! b! R! \/ h$ W
  18. }
    0 o8 k4 n6 q6 r2 _& F' M

  19. * u. X" W& u4 ^1 J* Z
  20. /*****************************************************************
    " O6 c4 i% K; J1 r4 Y4 y# w$ Z
  21. 函数名称:SPI_WriteData
    4 Y7 d, z8 |  I6 g
  22. 函数功能:spi写数据& }1 V0 K7 l9 B. Q
  23. 输    入:data:写数据8位
    4 G) a& _: k* `4 p+ D; x  F
  24. 返    回:无9 f2 D' u% T" P5 \' X
  25. ******************************************************************/
    9 J( ]3 h; B6 B. M/ W0 }) Y- S
  26. void SPI_WriteData(u8 data)
    " L! D, m" [2 `6 ?/ N4 z% R( X% g
  27. {
    ( q' g# {2 @- x. U* X  z
  28.   u8 i = 0;+ W3 B4 ^* v5 Z, v( E4 [/ q& S. A# j
  29.   / P  }1 I( N  E2 J' ]. `( P" I
  30.   SPI_CLK(0);              //上升沿锁存,置低锁存引脚8 w! u8 M' O1 K5 w! R6 p. I
  31.   Delay_us(1);0 `8 |. ^" B) Q9 X  o# |# ^
  32.   ; V  k$ }! }8 `+ p5 J) P2 v: x
  33.   for(i = 0;i < 8;i++)
    / n( y4 F4 o# h4 {
  34.   {
      t9 g3 H2 _0 q2 B1 s  F
  35.     SPI_SCK(0);             //上升沿写数据,置低时钟引脚( \& D  N/ K0 D2 S6 U2 E  Q
  36.     SPI_SDO(data & 0x80);   //写数据值4 }% ^# t' M# b
  37.     data <<= 1;1 E3 F$ U% }$ ^. m4 ?: f9 K
  38.     SPI_SCK(1);              //置高时钟引脚输出数据
    $ a/ u2 _. [7 Z0 p  v. k- B
  39.   }' d0 i) x* i* H& j" p  [3 |9 k0 [- F
  40.   
    : `( H# q; R- x  z. b/ Q2 b
  41.   Delay_us(1);
    . X) |$ K; B  `4 I. C2 i! m( @" `
  42.   SPI_CLK(1);                //置高锁存引脚,锁存数据" b% |. [+ {- h9 D3 ]
  43. }
复制代码

- O( }" E# |' r; g/ ]* V' t
使用IO口模拟的方式实现SPI功能主要是看明白时序图,按照时序要求操作相应引脚的电平就可以了,各引脚电平变化保持有时间要求的需要通过延时实现,各电平配合不得当有可能会导致通讯失败。
以上代码只是写数据的,读数据的与之相似,工程中没有用到就没写。
注:程序中加了一些注释,工程文件中为了整洁对齐,有些注释比较靠右,开始以为不能显示,后来发现代码下面有个移动条,通过移动条可以左右滑动。
文章出处: 单片机学习点滴
+ x$ s% v% F, P  i
收藏 评论0 发布时间:2020-12-30 11:24

举报

0个回答

所属标签

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