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

STM32L431在STOP2模式下能否将串口的RX配置成EXTI唤醒呢?为什么我的唤醒不了呢?并且空闲中断也不能用

[复制链接]
Alf·Romeo 提问时间:2024-10-31 15:52 / 未解决

STM32L431在STOP2模式下能否将串口的RX配置成EXTI唤醒呢?为什么我的唤醒不了呢?并且空闲中断也不能用,手册中说在硬件上已经将EXTI与RX引脚连到一块了,但是呢STOP2模式不能将串口唤醒,所以它的那种方式好像不能使用,只能用最原始的将RX配置成EXTI的方式了,但是也还是唤醒不了

进入STOP2模式,

void EnterStop2ModeRTC(void) // 自定义的Enter函数
{
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
  __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
  __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
  __HAL_RTC_TIMESTAMP_CLEAR_FLAG(&hrtc, RTC_FLAG_TSF);
  __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
  while (__HAL_UART_GET_FLAG(&huart3, USART_ISR_BUSY) == SET)
    ;
  while (__HAL_UART_GET_FLAG(&huart3, USART_ISR_REACK) == RESET)
    ;
  setUca3RxToExti();//配置串口3的RX为EXTI
  HAL_SuspendTick();
  //HAL_DBGMCU_EnableDBGStopMode();
  __HAL_RCC_PWR_CLK_ENABLE();
  HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); // 进入STOP2模式
}

退出STOP2

void ExitStop2ModeRTC(void)
{
  SystemClock_Config(); 
  HAL_ResumeTick();
  SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
}

主函数

while (1)
  {
    while (getExitLPM3())
    {
      saveData();
      lcdActionPro(); // lcd进程
      keyActPro();
      // if (uart[_COM3].active)
      // {
      // }
      }
    }
    EnterStop2ModeRTC();
  }

在函数getExitLPM3()中,判断了一个标志位是否被置位,如果置位了就进入里面的while

EXTI回调函数:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if ((GPIO_Pin == GPIO_PIN_5))
  {
    ExitStop2ModeRTC();
    HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
    setUca3RxToRx();
    // uart[_COM3].active = true;
  }
}

在EXTI的回调函数中退出了STOP2模式并重新将串口RX引脚配置为接收引脚

void setUca3RxToExti(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
  uart[_COM3].active = false;
}

void setUca3RxToRx(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  // // HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
  // // HAL_NVIC_EnableIRQ(USART3_IRQn);
  __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);
  // __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE | UART_IT_IDLE);
}

串口中断

void USER_USART3_IRQHandler(void)
{
  uint8_t data = 0;
  if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) != RESET)
  {
    data = (uint8_t)huart3.Instance->RDR;
    wrEleQueue(&uart[_COM3].Rx, data);
    // uart[_COM3].active = true;
    // bleAppConfig.rxAct = 1;
    // bleAppConfig.tmrResp = bleAppConfig.tmrRxHold = HAL_LPTIM_ReadCounter(&hlptim1);
    // __HAL_UART_CLEAR_FLAG(&huart3, UART_FLAG_RXNE);
  }
  // if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE))
  // {
  //   // uart[_COM3].flag = 1;
  //   uart[_COM3].active = false;
  //   __HAL_UART_CLEAR_IDLEFLAG(&huart3);
  // }
}

中间好像逻辑有点问题,但是我想不明白了哈哈,就是那个标志位被置位true后就会一直在内层的while中循环,出不来了,就进不去STOP2了,但是不知道在哪将它给置为false,本来想使用IDLE空闲中断的,但是空闲中断使用后收不到数据,现在不使用的时候第一包数据永远都是错误的,有没有大佬能帮忙看一下,谢谢大家

收藏 评论9 发布时间:2024-10-31 15:52

举报

9个回答
butterflyspring 回答时间:2024-10-31 17:20:10
可以肯定的是,外部中断是可以唤醒 STOP 模式的, 所以先调试芯片正常进入STOP 模式,然后设置外部中断唤醒。


另外手册上介绍的是LPUART 才有唤醒 STOP 模式的功能, 且需要波特率最大为9600.

如果波特率太快,即使中断唤醒,从唤醒到开始工作需要一定时间,所以一定会丢掉开始的数据的。
xmshao 回答时间:2024-10-31 17:55:02
其实,STM32L4系列里的LPUART就具有唤醒STOP2 模式下MCU的能力。


从你代码来看,使用的是UART3,你似乎想问是否可以利用UART RX脚的EXTI来唤醒MCU.


即使是UART的RX脚,也可以配置其EXTI中断能力,并可以通过该中断唤醒STOP2模式下的MCU.


假设你使用STM32cubeMx进行UART配置,创建工程后自己手动再增加基于UART RX脚的EXTI配置,


不要修改该脚的复用配置功能。


假设你使用UART3的RX脚是PC5,我们可以临时选择其它编号为5个GPIO,比方PD5,启用该脚的EXTI并
使能NVIC端的中断响应。


创建工程后,只需在 MX_GPIO_Init()函数里将PD5的 EXTI配置改为PC5的配置即可,其它不用修改。


这样就可以测试了,比起对着手册修改EXTI控制寄存器方便多了。我这样测试屡试不爽。


先一步步来,先将不影响UART功能前提下,将RX脚的EXTI功能弄出来,再来验证唤醒的事情。
Alf·Romeo 回答时间:2024-11-1 14:44:32

xmshao 发表于 2024-10-31 17:55
其实,STM32L4系列里的LPUART就具有唤醒STOP2 模式下MCU的能力。</p>
<p>

如果将RX配置成EXTI方式,串口的空闲中断好像不能用啊,有时候收到一个数据就进入空闲中断了,并且第一包还是乱码,这种怎么办呢?

xmshao 回答时间:2024-11-1 16:15:12

zhouyalong 发表于 2024-11-1 14:44
如果将RX配置成EXTI方式,串口的空闲中断好像不能用啊,有时候收到一个数据就进入空闲中断了,并且第 ...

[md]基于RX脚的EXTI中断主要用来唤醒比较合适,按理你这里用不着借助RX EXTI中断来做数据接收,

RXNE中断做接收,IDLE中断提示接收结束;

RX EXTI中断和IDLE中断是完全不搭界的两个中断,IDLE中断用于不确定数据长度的UART接收比较合适;

Alf·Romeo 回答时间:2024-11-4 08:45:21

xmshao 发表于 2024-11-1 16:15
基于RX脚的EXTI中断主要用来唤醒比较合适,按理你这里用不着借助RX EXTI中断来做数据接收,</p>
<p>RXNE中 ...

[md]我是要做低功耗的,所以才需要借助RX的EXTI中断,如果没有数据的时候不将RX配置为EXTi的话,功耗就降不下去

xmshao 回答时间:2024-11-4 09:13:56

zhouyalong 发表于 2024-11-4 08:45
我是要做低功耗的,所以才需要借助RX的EXTI中断,如果没有数据的时候不将RX配置为EXTi的话,功耗就降 ...

[md]了解你的需求。

我是说,使用RX中断和IDLE中断是两个不同的事件,你这里使用RX中断主要用作唤醒,往往发生在通信前,IDLE中断是发生在通信后,你合理安排好程序逻辑即可。

Alf·Romeo 回答时间:2024-11-4 10:29:58

xmshao 发表于 2024-11-4 09:13
了解你的需求。</p>
<p>我是说,使用RX中断和IDLE中断是两个不同的事件,你这里使用RX中断主要用作唤醒,往 ...

[md]你的意思是,接收中断个空闲中断不要同时使能吗?分先后使能?我在将RX配置为接收引脚的时候使能了接收中断,那么空闲中断我不知道放在哪里

xmshao 回答时间:2024-11-4 11:05:50

zhouyalong 发表于 2024-11-4 10:29</p>
<p>[md]你的意思是,接收中断个空闲中断不要同时使能吗?分先后使能?我在将RX配置为接收引脚的时候使能 ...

[md]基于RX电平跳变的EXTI中断,基于UART接收的RXNE中断,基于空闲事件的中断,

即使这三个中断同时使能也没有关系,各司其职。EXTI中断只负责触发唤醒,进中断服务程序

后只清零EXTI相关标志,不要涉及UART相关寄存器的访问;

RXNE中断只管数据接收;

IDLE中断负责数据处理和做后续通信准备。

具体到这里EXTI中断最好不用时刻使能,只在进低功耗前才使能为宜,唤醒后立即关闭。

Alf·Romeo 回答时间:2024-11-4 11:14:18

xmshao 发表于 2024-11-4 11:05
基于RX电平跳变的EXTI中断,基于UART接收的RXNE中断,基于空闲事件的中断,</p>
<p>即使这三个中断同时使能 ...

[md]对啊,我上面的代码就是这样写的呀

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版