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

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

[复制链接]
STMCU小助手 发布时间:2020-12-30 11:24
STM32单片机应用笔记 (三) SPI通讯
stm32f103单片机SPI通讯代码:
  1. static void bsp_GPIO_Init(void)
    & i/ p* g* v( {# a* J; r! v' U
  2. {8 {' k1 T# @3 V& [/ ^% a
  3.   GPIO_InitTypeDef GPIO_InitStructure;
    & g- {8 X! C9 \7 s2 ?
  4.   EXTI_InitTypeDef EXTI_InitStructure;: }: v: W% s% q4 g# A/ W
  5.   
    6 T7 D1 W2 S( m3 A$ q: Q0 e
  6.   RCC_APB2PeriphClockCmd(  RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);   //开外设时钟5 n" b' a+ b2 w1 D0 b: v7 |
  7.   GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);                                              //关闭jtag开sw
    : S% S, `0 i$ g: o9 g
  8.   ) w. X4 _8 |- U* B/ R. B- W& M6 s
  9.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_5 | GPIO_Pin_7;                                                  // SCK  MOSI# X. o: h, a6 h; n: f
  10.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
    ) ^" r' z8 }; m8 Q* V
  11.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_AF_PP;
    4 g' z0 a' O" i; A/ z1 o4 j
  12.   GPIO_Init(GPIOA, &GPIO_InitStructure);
    . J* `1 I) ^+ `- t0 V4 p. J
  13.   + `) W8 B: S- u/ c- c2 C
  14.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_6;                                                              //MISO" ]6 k8 H8 G+ H% n
  15.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;$ W5 I* w# D% o2 h! B- P/ M. x
  16.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
    % n# z. ~: s; ?; T! c
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);  + a' s6 H8 S. q; W& i- T; J
  18. }; ?# L/ A, E  R+ J; {! r

  19. ! z. {7 g& B+ k( R* E% E8 J, Z; j5 [: ]
  20. static void bsp_SPI_Init(void)& K, `8 Z7 R/ h! o
  21. {% V+ m' e5 G* ?; x4 v
  22.   SPI_InitTypeDef  SPI_InitStructure;
    ! C7 _% Z6 c1 X# I* ~4 R
  23.   
    9 X/ e% m! H, {
  24.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
    ) ]- f5 g0 i) d6 Z7 c0 A
  25.   8 l4 l! z& q; [4 M  c
  26.   SPI_InitStructure.SPI_Direction       = SPI_Direction_2Lines_FullDuplex;            //工作模式(双线或者单线)
    ; B  K2 Z" H; A4 w4 _
  27.   SPI_InitStructure.SPI_Mode         = SPI_Mode_Master;                          //主机模式2 P9 {. M, b- v5 p$ N, J
  28.   SPI_InitStructure.SPI_DataSize       = SPI_DataSize_8b;                          //8为数据传输9 W& v# e+ N7 Z" p
  29.   SPI_InitStructure.SPI_CPOL         = SPI_CPOL_High;                            //时钟不工作时的状态* E/ H6 @5 w1 E
  30.   SPI_InitStructure.SPI_CPHA         = SPI_CPHA_1Edge;                          //有效触发的边沿
    + C1 R! d7 D0 a( j8 t. f9 L
  31.   SPI_InitStructure.SPI_NSS           = SPI_NSS_Soft;                              //片选软件触发
    7 c0 j8 ^5 Y# q* V
  32.   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;                //spi时钟频率$ _) o1 F) C! G2 l8 F* f! ~6 u  y* H
  33.   SPI_InitStructure.SPI_FirstBit         = SPI_FirstBit_MSB;                          //高位优先' b1 X4 |  t' Z
  34.   SPI_InitStructure.SPI_CRCPolynomial   = 7;                                      //CRC(默认的是7)
    * O: ~$ f; U  g+ y# x$ e; f
  35.   SPI_Init(SPI1, &SPI_InitStructure);: `8 Q0 R# e: ~8 i4 K
  36. + b: i5 ]0 M% b  ^$ `0 V( g% ~
  37.   SPI_Cmd(SPI1, ENABLE);
    ; \- `! ]2 I0 K
  38. }% @3 |7 t# s, S- y# }2 F
  39. # `. C1 X( ^6 a$ P8 z2 D6 O: A

  40. + |; D7 V  n, r! {0 B; x( ]
  41. u8 bsp_SPI_ReadWriteByte(u8 txdata)
    % {: s9 f$ F3 K" ^. f0 T8 h5 ~
  42. {; p  X7 J/ {* K5 Y( D
  43.   u8 waitcnt = 0;3 l8 a+ F( W6 X4 ]4 b! r' D
  44.   7 J, u- [, r0 e' @4 {8 |. l
  45.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);                      //等待发送区空
    $ P) I) ~0 l( `5 r/ _& y( M
  46.   SPI_I2S_SendData(SPI1, txdata);  % B7 }# ~6 H3 I- q1 |0 M
  47.   . p9 a" J4 j, K, ~# W/ l) y
  48. //  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
    . n6 n" X7 n% Y
  49.   while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET)
    3 h* M( g+ V5 ?) Y/ B
  50.   {+ X. y2 Z1 N$ g2 q4 |3 R# g- y
  51.     waitcnt++;; A% D/ |6 {5 m3 G
  52.     if(waitcnt >= 200)
    ; E4 _6 s/ O3 o$ Q
  53.       return 0;5 B6 {2 y, v$ d/ D( V# a
  54.   }
    5 W, x3 J2 p5 u. @" A* j
  55.   
    5 l; _" S. s% _% S( k: ^
  56.   return SPI_I2S_ReceiveData(SPI1);
    ; r7 @7 M6 ^7 J
  57. }
复制代码
* x6 k# F0 s3 x0 v) t! ^; ^
以上代码是使用stm32自带的SPI模块功能,数据的收发使用查询的方式,没有使用中断功能。工作中使用SPI一般是控制LED灯的驱动芯片,ADC采样芯片以及DAC芯片,都属于那种定时的读写或者有某种触发条件读写的情况,因此基本没使用过SPI的中断以及SPI的DMA功能。
下面的代码是使用IO口模拟SPI功能:
  1. /*****************************************************************
    3 E7 {& T- \% _* D. g
  2. 函数名称:SPI_GPIO_Conf
    ! C% N; ~& T  T' w! Y# @0 y, v
  3. 函数功能:spi引脚配置* W, G: V' U; P- k) K: g) n0 P& P/ ~
  4. 输    入:无5 W" G9 V3 ]5 u2 a7 C, Y$ Z+ Q
  5. 返    回:无
    0 C0 r, \4 O7 N0 X! p9 X
  6. ******************************************************************/) |6 x, ?# t/ k# _9 I
  7. void SPI_GPIO_Conf(void)
    # m6 i  @. Y5 s
  8. {% n; R6 [7 M0 R6 N4 v2 f# y: _; N
  9.   GPIO_InitTypeDef GPIO_InitStructure;
    / c3 z6 }# w+ I; {! y
  10.   + C- q+ i5 V3 M6 ~
  11.   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;' {. @' ?; s# s. |6 D
  12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    : W& J9 [7 V$ W' K7 |) p' J
  13.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    8 e0 I8 I0 f1 x0 N$ w
  14.   GPIO_Init(GPIOB,&GPIO_InitStructure);5 s- |) b/ F, b' |) G( l
  15.   
    * X1 |( }7 S: a4 c! R& Q% P) {0 H# E
  16.   SPI_OE(0);                      //片选-使能芯片
    4 d0 c9 U& ]. k3 w4 t
  17.   SPI_CLR(1);                     //清除寄存器
    3 G8 ]' u3 P( ~( n; U! K4 ]2 w
  18. }( _- l/ P: k8 @- t# N5 q. x+ ]

  19. & X4 W8 d2 F/ b8 d! X5 T
  20. /*****************************************************************
    . W( |, K- F' e( i( O" U, _
  21. 函数名称:SPI_WriteData$ C' l$ `1 a' H3 ^
  22. 函数功能:spi写数据6 r; k! ^+ M7 @+ U
  23. 输    入:data:写数据8位# B: J$ C* l+ U  _- \: j* B
  24. 返    回:无
    9 Z$ r9 r8 b4 x
  25. ******************************************************************/
    3 S% {1 q: W  ?3 s. g8 w! w# f
  26. void SPI_WriteData(u8 data)6 `& B$ [( k6 o
  27. {# P6 F9 d- I; n8 v! @4 S" N
  28.   u8 i = 0;7 f$ q6 \) }3 E& w6 c" O" ^$ e- r
  29.   / S# P5 V* r* ~& [; f- w
  30.   SPI_CLK(0);              //上升沿锁存,置低锁存引脚
    9 }! @1 T5 J' E$ e: F( c) S
  31.   Delay_us(1);5 F! G9 o( ~5 _* |
  32.   
    " A6 h% {* p8 m( O3 B
  33.   for(i = 0;i < 8;i++)
    - r$ K  o; W$ R
  34.   {& ]' {5 J/ F% [; ~$ x' f$ o% }5 ^
  35.     SPI_SCK(0);             //上升沿写数据,置低时钟引脚% l/ ^8 M2 V" w
  36.     SPI_SDO(data & 0x80);   //写数据值( p! F9 ^1 q- V- [2 W
  37.     data <<= 1;/ Z' \1 X$ z. m0 K) L- D# Q8 b2 c
  38.     SPI_SCK(1);              //置高时钟引脚输出数据* g7 b# r  B" q* {$ A% p! h
  39.   }! ~9 M2 |5 S) l" v5 N
  40.   
    $ E7 X* z: O# }0 Z* i  E
  41.   Delay_us(1);' j- c* s1 q6 O2 G# B4 ?" `" B
  42.   SPI_CLK(1);                //置高锁存引脚,锁存数据" D! h( e! w/ R
  43. }
复制代码

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

举报

0个回答

所属标签

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