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

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

[复制链接]
STMCU小助手 发布时间:2020-12-30 11:24
STM32单片机应用笔记 (三) SPI通讯
stm32f103单片机SPI通讯代码:
  1. static void bsp_GPIO_Init(void)/ c2 ?1 }7 e3 q+ _2 Y
  2. {- m$ @/ I. s. ~! H7 X
  3.   GPIO_InitTypeDef GPIO_InitStructure;' P, q: G, J: S: R. ?& A3 a9 F
  4.   EXTI_InitTypeDef EXTI_InitStructure;" {" c1 P# \! d# v% \: t" o
  5.   
    : \+ x. |; E, p+ Q1 i
  6.   RCC_APB2PeriphClockCmd(  RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);   //开外设时钟; S8 q/ \- V  S( j. s' ^
  7.   GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);                                              //关闭jtag开sw+ b: d$ H9 u/ i* I1 ?3 Q' s
  8.   2 ^. Q, h7 W- Z/ [7 T$ a
  9.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_5 | GPIO_Pin_7;                                                  // SCK  MOSI
    ) N- B$ U. v  D! T. Y+ a
  10.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
    $ V  W8 W# [" v1 {5 H0 t7 D: ?
  11.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_AF_PP;  Z0 T) Q; d# n
  12.   GPIO_Init(GPIOA, &GPIO_InitStructure);# u$ |& q; _6 D9 A1 O& A
  13.   
    " H, {1 I$ N% p" e% M* L; w
  14.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_6;                                                              //MISO  g5 w0 ]  j; h
  15.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;- Q7 A: B+ S6 J9 `
  16.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
    - J7 }" E  W1 A# p
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);  ) V2 y% A# P/ D. D
  18. }" _2 p/ b& A, U" {# M* l

  19. $ [0 b4 W1 s8 ]8 ~& {9 w% z' l
  20. static void bsp_SPI_Init(void)2 C3 \: j2 J  m
  21. {
    6 m6 K' D4 l& \& Q, z3 M; i
  22.   SPI_InitTypeDef  SPI_InitStructure;
    ) u) k( T9 j8 {+ N4 }9 P# W7 S
  23.   5 h* S8 o8 L6 w$ g
  24.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);1 ]! }7 W7 H" t; V
  25.   
    . _6 N8 ]5 q3 a2 g  @% F( R6 G
  26.   SPI_InitStructure.SPI_Direction       = SPI_Direction_2Lines_FullDuplex;            //工作模式(双线或者单线)3 [$ E0 P/ B) T
  27.   SPI_InitStructure.SPI_Mode         = SPI_Mode_Master;                          //主机模式
    - a# e& w3 y! V( e% q
  28.   SPI_InitStructure.SPI_DataSize       = SPI_DataSize_8b;                          //8为数据传输
    9 B6 E* I! u+ ^' w  {
  29.   SPI_InitStructure.SPI_CPOL         = SPI_CPOL_High;                            //时钟不工作时的状态& H$ v$ F) N7 }; V8 y7 t( ]
  30.   SPI_InitStructure.SPI_CPHA         = SPI_CPHA_1Edge;                          //有效触发的边沿
    ! Q6 N: V7 t* `9 g1 i$ ?% x9 Q
  31.   SPI_InitStructure.SPI_NSS           = SPI_NSS_Soft;                              //片选软件触发* k1 ?) J% z! {) X7 {- V1 b
  32.   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;                //spi时钟频率
    % L. t/ H% j3 m
  33.   SPI_InitStructure.SPI_FirstBit         = SPI_FirstBit_MSB;                          //高位优先# o. Z- X" P  Z8 _1 i! e. f$ b/ r
  34.   SPI_InitStructure.SPI_CRCPolynomial   = 7;                                      //CRC(默认的是7)  Y4 H9 E8 H( f" e) y
  35.   SPI_Init(SPI1, &SPI_InitStructure);4 c/ ^4 l% v4 m. H4 Q
  36. $ H9 O% J7 g5 `9 p1 j, l) [$ w
  37.   SPI_Cmd(SPI1, ENABLE);* h  v- _/ t, B
  38. }. a) b' W  H2 p4 o( J3 k* O; e6 {
  39. ) `( B% N- n; ^' [+ Z* A1 X
  40. , c5 t+ B' q; j' X: H
  41. u8 bsp_SPI_ReadWriteByte(u8 txdata)4 [6 i, b# l, o) ]9 c% p& r; N/ y
  42. {! X$ }' D8 P+ |8 I, q6 M1 h% c
  43.   u8 waitcnt = 0;
    ) K! N8 e5 N. C/ O5 C8 K* K3 f
  44.   ) M2 f$ P6 [5 ~* ]7 ~
  45.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);                      //等待发送区空 $ i/ V$ b* W3 f$ R) E+ d, Y; V
  46.   SPI_I2S_SendData(SPI1, txdata);  4 _1 O& q& v- i: D
  47.   
    4 ^' A3 N4 U5 \
  48. //  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
    0 j0 x# s. v: q' M! D1 h1 v& x( u
  49.   while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET)
    $ j( D& e& D4 B- p6 g
  50.   {% Y2 A2 G: r$ J# r0 Y
  51.     waitcnt++;" u5 O- ?" B1 t, z7 }; C3 y
  52.     if(waitcnt >= 200)
    * J, d, o, S; c. F3 T# `/ q
  53.       return 0;2 y) P2 _" G+ R) e
  54.   }- u" d7 t  B6 c6 @( p$ A
  55.   ' P% ~/ F9 n& ]3 x1 `
  56.   return SPI_I2S_ReceiveData(SPI1);% o) }$ Z3 D/ S% g& B  E( P
  57. }
复制代码

1 F! x: L1 G. W+ @- }
以上代码是使用stm32自带的SPI模块功能,数据的收发使用查询的方式,没有使用中断功能。工作中使用SPI一般是控制LED灯的驱动芯片,ADC采样芯片以及DAC芯片,都属于那种定时的读写或者有某种触发条件读写的情况,因此基本没使用过SPI的中断以及SPI的DMA功能。
下面的代码是使用IO口模拟SPI功能:
  1. /*****************************************************************
    " l$ x3 I! h% |& [3 ~1 t8 f
  2. 函数名称:SPI_GPIO_Conf  \$ i& c% N2 g6 [2 {
  3. 函数功能:spi引脚配置. X( w3 u* L0 k* O) q2 ?3 ^
  4. 输    入:无
    , q  j8 V6 i5 s# ]( x. I
  5. 返    回:无* m3 C4 d9 W4 l9 k, ~
  6. ******************************************************************/
    + [7 n) }' S. Q
  7. void SPI_GPIO_Conf(void), `1 O, \5 r. S: X/ W" b
  8. {
    ' n# L! m- e2 I- T
  9.   GPIO_InitTypeDef GPIO_InitStructure;
    7 R4 {% ?1 H) `) f
  10.   
    5 d8 S7 Q& M7 p& [7 P" o
  11.   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;" j$ C& s9 ~# U, a& v4 v
  12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    8 s: l$ Y% U9 D& Y. Y4 w6 n; ^6 [
  13.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    " r3 l+ P" K  R3 D7 H& `- w
  14.   GPIO_Init(GPIOB,&GPIO_InitStructure);
    3 f& L8 B: H- }# ]; h
  15.   # u' o" O% O4 `) m+ Q7 {" l( |
  16.   SPI_OE(0);                      //片选-使能芯片  {0 ?7 v  S) z1 o  X" ]
  17.   SPI_CLR(1);                     //清除寄存器
    8 [8 C2 c9 D/ m: m
  18. }$ O7 [# [2 W; v6 E

  19. * t2 O1 ?+ Z& X  `: U% s
  20. /*****************************************************************7 y( i2 R0 d* V4 X1 e0 A0 G/ I
  21. 函数名称:SPI_WriteData
    # b/ Q1 l1 {, o) k* z
  22. 函数功能:spi写数据
    # @! B* P& x, ]. ~8 w
  23. 输    入:data:写数据8位  {6 G+ ~1 Z; c
  24. 返    回:无! ~5 m( I& |5 F2 Q5 z8 n6 \
  25. ******************************************************************/
    1 c: h+ q/ E6 M# ^
  26. void SPI_WriteData(u8 data)% b' O3 q7 c) D0 K0 f( y0 L
  27. {  x9 D. u" ^6 q* x
  28.   u8 i = 0;$ O# e/ e  \# ^9 J* o. s
  29.   2 ?' V- z! R2 c" }" ]
  30.   SPI_CLK(0);              //上升沿锁存,置低锁存引脚
    ; L6 A3 ]' M6 e5 a. G8 F) b/ s
  31.   Delay_us(1);
    1 o& N( J- W) w; F
  32.   
    / z5 T/ V) K3 ]' h0 `
  33.   for(i = 0;i < 8;i++): r+ _! d8 t( [% m9 U. P6 x3 a
  34.   {( V1 K2 z3 y6 N+ q+ ^5 [, v
  35.     SPI_SCK(0);             //上升沿写数据,置低时钟引脚
    0 i- e) S/ S1 ]; ?8 b6 k
  36.     SPI_SDO(data & 0x80);   //写数据值
    ; H8 I5 _8 G' b# P3 \
  37.     data <<= 1;
    ) L7 S8 {& R* R+ H: Q
  38.     SPI_SCK(1);              //置高时钟引脚输出数据8 [8 j$ V# |. J' _
  39.   }2 Q& R6 c0 d% P+ i6 d; J5 q/ z( _3 {
  40.   
    * O' m8 ?, q+ Y, ~& j6 v2 B" ]7 W: u
  41.   Delay_us(1);
    + Y* K$ N# r* l! |! p8 i) R/ Y
  42.   SPI_CLK(1);                //置高锁存引脚,锁存数据
    ( R5 F" [, p. M
  43. }
复制代码
& B1 S0 s. C6 }% N: N; \
使用IO口模拟的方式实现SPI功能主要是看明白时序图,按照时序要求操作相应引脚的电平就可以了,各引脚电平变化保持有时间要求的需要通过延时实现,各电平配合不得当有可能会导致通讯失败。
以上代码只是写数据的,读数据的与之相似,工程中没有用到就没写。
注:程序中加了一些注释,工程文件中为了整洁对齐,有些注释比较靠右,开始以为不能显示,后来发现代码下面有个移动条,通过移动条可以左右滑动。
文章出处: 单片机学习点滴
/ T- `/ ?- O9 Y" W( v
赞 收藏 评论0 发布时间:2020-12-30 11:24

举报

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