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

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

[复制链接]
STMCU小助手 发布时间:2020-12-30 11:24
STM32单片机应用笔记 (三) SPI通讯
stm32f103单片机SPI通讯代码:
  1. static void bsp_GPIO_Init(void)
  2. {
  3.   GPIO_InitTypeDef GPIO_InitStructure;
  4.   EXTI_InitTypeDef EXTI_InitStructure;
  5.   
  6.   RCC_APB2PeriphClockCmd(  RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);   //开外设时钟
  7.   GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);                                              //关闭jtag开sw
  8.   
  9.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_5 | GPIO_Pin_7;                                                  // SCK  MOSI
  10.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
  11.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_AF_PP;
  12.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  13.   
  14.   GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_6;                                                              //MISO
  15.   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
  16.   GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
  18. }

  19. static void bsp_SPI_Init(void)
  20. {
  21.   SPI_InitTypeDef  SPI_InitStructure;
  22.   
  23.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
  24.   
  25.   SPI_InitStructure.SPI_Direction       = SPI_Direction_2Lines_FullDuplex;            //工作模式(双线或者单线)
  26.   SPI_InitStructure.SPI_Mode         = SPI_Mode_Master;                          //主机模式
  27.   SPI_InitStructure.SPI_DataSize       = SPI_DataSize_8b;                          //8为数据传输
  28.   SPI_InitStructure.SPI_CPOL         = SPI_CPOL_High;                            //时钟不工作时的状态
  29.   SPI_InitStructure.SPI_CPHA         = SPI_CPHA_1Edge;                          //有效触发的边沿
  30.   SPI_InitStructure.SPI_NSS           = SPI_NSS_Soft;                              //片选软件触发
  31.   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;                //spi时钟频率
  32.   SPI_InitStructure.SPI_FirstBit         = SPI_FirstBit_MSB;                          //高位优先
  33.   SPI_InitStructure.SPI_CRCPolynomial   = 7;                                      //CRC(默认的是7)
  34.   SPI_Init(SPI1, &SPI_InitStructure);

  35.   SPI_Cmd(SPI1, ENABLE);
  36. }


  37. u8 bsp_SPI_ReadWriteByte(u8 txdata)
  38. {
  39.   u8 waitcnt = 0;
  40.   
  41.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);                      //等待发送区空
  42.   SPI_I2S_SendData(SPI1, txdata);  
  43.   
  44. //  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
  45.   while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET)
  46.   {
  47.     waitcnt++;
  48.     if(waitcnt >= 200)
  49.       return 0;
  50.   }
  51.   
  52.   return SPI_I2S_ReceiveData(SPI1);
  53. }
复制代码

以上代码是使用stm32自带的SPI模块功能,数据的收发使用查询的方式,没有使用中断功能。工作中使用SPI一般是控制LED灯的驱动芯片,ADC采样芯片以及DAC芯片,都属于那种定时的读写或者有某种触发条件读写的情况,因此基本没使用过SPI的中断以及SPI的DMA功能。
下面的代码是使用IO口模拟SPI功能:
  1. /*****************************************************************
  2. 函数名称:SPI_GPIO_Conf
  3. 函数功能:spi引脚配置
  4. 输    入:无
  5. 返    回:无
  6. ******************************************************************/
  7. void SPI_GPIO_Conf(void)
  8. {
  9.   GPIO_InitTypeDef GPIO_InitStructure;
  10.   
  11.   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  14.   GPIO_Init(GPIOB,&GPIO_InitStructure);
  15.   
  16.   SPI_OE(0);                      //片选-使能芯片
  17.   SPI_CLR(1);                     //清除寄存器
  18. }

  19. /*****************************************************************
  20. 函数名称:SPI_WriteData
  21. 函数功能:spi写数据
  22. 输    入:data:写数据8位
  23. 返    回:无
  24. ******************************************************************/
  25. void SPI_WriteData(u8 data)
  26. {
  27.   u8 i = 0;
  28.   
  29.   SPI_CLK(0);              //上升沿锁存,置低锁存引脚
  30.   Delay_us(1);
  31.   
  32.   for(i = 0;i < 8;i++)
  33.   {
  34.     SPI_SCK(0);             //上升沿写数据,置低时钟引脚
  35.     SPI_SDO(data & 0x80);   //写数据值
  36.     data <<= 1;
  37.     SPI_SCK(1);              //置高时钟引脚输出数据
  38.   }
  39.   
  40.   Delay_us(1);
  41.   SPI_CLK(1);                //置高锁存引脚,锁存数据
  42. }
复制代码

使用IO口模拟的方式实现SPI功能主要是看明白时序图,按照时序要求操作相应引脚的电平就可以了,各引脚电平变化保持有时间要求的需要通过延时实现,各电平配合不得当有可能会导致通讯失败。
以上代码只是写数据的,读数据的与之相似,工程中没有用到就没写。
注:程序中加了一些注释,工程文件中为了整洁对齐,有些注释比较靠右,开始以为不能显示,后来发现代码下面有个移动条,通过移动条可以左右滑动。
文章出处: 单片机学习点滴

收藏 评论0 发布时间:2020-12-30 11:24

举报

0个回答

所属标签

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