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

【经验分享】分析STM32G0 SPI外设不能触发RXNE接收标志的原因

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:

  1. void MX_SPI1_Init(void)
  2. {

  3.   /* USER CODE BEGIN SPI1_Init 0 */

  4.   /* USER CODE END SPI1_Init 0 */

  5.   LL_SPI_InitTypeDef SPI_InitStruct = {0};

  6.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  7.   /* Peripheral clock enable */
  8.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);

  9.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
  10.   /**SPI1 GPIO Configuration
  11.   PA5   ------> SPI1_SCK
  12.   PA6   ------> SPI1_MISO
  13.   PA7   ------> SPI1_MOSI
  14.   */
  15.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  16.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  17.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  18.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  19.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;

  20.   GPIO_InitStruct.Pin = SPI_SCK_PIN;
  21.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);

  22.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
  23.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);

  24.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;
  25.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);

  26.   /* USER CODE BEGIN SPI1_Init 1 */

  27.   /* USER CODE END SPI1_Init 1 */
  28.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  29.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  30.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
  31.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
  32.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
  33.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  34.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
  35.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  36.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  37.   SPI_InitStruct.CRCPoly = 7;
  38.   LL_SPI_Init(SPI1, &SPI_InitStruct);
  39.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
  40.   LL_SPI_DisableNSSPulseMgt(SPI1);
  41.   /* USER CODE BEGIN SPI1_Init 2 */
  42.   LL_SPI_Enable(SPI1); //用户手动使能SPI
  43.   /* USER CODE END SPI1_Init 2 */

  44. }
复制代码

程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:
2021060720475766.png


但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:

  1. /* Configure the SPI2 FIFO Threshold */
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码

通过查看STM32G0x0官方数据手册的24.6.2 SPI control register 2 (SPIx_CR2)小节,可以看到设置外设接收8位数据,RX FIFO阈值要设置为1/4,但因为Cube MX生成的代码没有设置FIFO阈值,并且LL_SPI_Init()函数也并没有直接对CR2寄存器的FRXTH位进行设置,导致了代码中虽然设置的是接收8位数据,但寄存器为默认16位的阈值,所以RXNE标志就一直不能触发,也就接收不到任何数据。

2021060721150377.png


反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。

  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
  2. {
  3.         .......
  4.          /* Configure SPIx: Data Size */
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位
  6.         /* Write to SPIx CR2 */
  7.         SPIx->CR2 = tmpreg;
  8.         ......
复制代码




收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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