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

折腾了半夜搞不定,求帮助~~

[复制链接]
lvfeng123 提问时间:2019-5-6 02:13 /
板子STM32L496
目标:1.只接收8字节长的数据, 多或者少都不理会。
          2.没数据的时候休眠, 有数据的时候醒来处理。
现在情况:(1)已经解决。  (2)可以正常休眠,可以正常有输入就醒来(LPUART1输入唤醒)。  
问题: 接收到的数据是乱码!!!, 醒来之后能正常接收。 就是最重要的唤醒那段数据收到是错的。
具体结果如下:  (是乱码!!),醒来后倒是能正常

I'm going to sleep...

L?&S撚?1234567812345678

I'm going to sleep...

代码如下:

中断处理部分:

void LPUART1_IRQHandler(void){
  //如果是刚醒来,是唤醒信号, a)把当前字节接收下来(顺便清空了NE中断能够继续接收下一个字节),b)清空睡眠各种状态! c)重新配置时钟
  if(LL_LPUART_IsActiveFlag_WKUP(LPUART1) && LL_LPUART_IsEnabledIT_WKUP(LPUART1)){
                        LL_LPUART_DisableIT_WKUP(LPUART1);
                        LL_LPUART_ClearFlag_WKUP(LPUART1);
                  rxBuffer[rxCounts++] = LL_LPUART_ReceiveData8(LPUART1);
                SystemClock_Config();
        }
//持续接收完当前帧;保存计数, 超过8字节按照错误随便处理。
        if(RESET != __HAL_UART_GET_FLAG(&hlpuart,UART_FLAG_RXNE)){

                isRec = 1;
                if(rxCounts < 8) {
                        rxBuffer[rxCounts++] = LPUART1->RDR;                       
                }else{
                        rxBuffer[0] = LPUART1->RDR;
                        rxCounts = 255;
                }
        }
//帧中断处理,符合长度是8 就处理,不然不理会。
  if(RESET != __HAL_UART_GET_FLAG(&hlpuart,UART_FLAG_IDLE)){
                if(rxCounts == 8)
                        HAL_UART_Transmit(&hlpuart,rxBuffer,DLen,0xFFFF);
               
                __HAL_UART_CLEAR_IDLEFLAG(&hlpuart);
                isRec = 0;
                rxCounts =0;
                //if(isRec==0) SYS_Sleep(&Lpuart1);
        }
//这句我不知道干嘛的,我看别人代码里都加上,我也加上。
        HAL_UART_IRQHandler(&hlpuart);
}


睡眠函数:(参考了疯子的一篇文章)

__STATIC_INLINE void SYS_Sleep(void){
//配置醒来后使用的时钟,enable 电源时钟。
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
        LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
  printf("\n\rI'm going to sleep...\n\r");

//以下是等待cpu各种状态空闲, 为休眠做准备!
  /* Clear OVERRUN flag */
  LL_LPUART_ClearFlag_ORE(LPUART1);

  /* Make sure that no LPUART transfer is on-going */
  while(LL_LPUART_IsActiveFlag_BUSY(LPUART1) == 1)
  /* Make sure that LPUART is ready to receive */   
  while(LL_LPUART_IsActiveFlag_REACK(LPUART1) == 0)

  /* Configure LPUART1 transfer interrupts : */
  /* Clear WUF flag and enable the UART Wake Up from stop mode Interrupt */
  LL_LPUART_ClearFlag_WKUP(LPUART1);
  LL_LPUART_EnableIT_WKUP(LPUART1);

//进入休眠模式。LPUART1有输入就会醒来
  /* Enable Wake Up From Stop */
  LL_LPUART_EnableInStopMode(LPUART1);
        HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
}


主要的一些配置情况:

void LPUART1_Init(void){
  hlpuart.Instance            = LPUART1;
  hlpuart.Init.BaudRate       = 115200U;
  hlpuart.Init.WordLength     = UART_WORDLENGTH_8B;
  hlpuart.Init.StopBits       = UART_STOPBITS_1;
  hlpuart.Init.Parity         = UART_PARITY_NONE;
  hlpuart.Init.HwFlowCtl      = UART_HWCONTROL_NONE;
  hlpuart.Init.Mode           = UART_MODE_TX_RX;
  hlpuart.Init.OverSampling   = UART_OVERSAMPLING_16;
  hlpuart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  hlpuart.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  //lpuart->gState = HAL_UART_STATE_RESET;
        if(HAL_UART_Init(&hlpuart) == HAL_OK)
                HAL_UART_Transmit(&hlpuart,(uint8_t *)&"\r\nInit ok!\r\n",16,0xffff);
}

void HAL_UART_MspInit(UART_HandleTypeDef* huart){
  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==LPUART1){
    __LPUART1_CLK_ENABLE();
                __GPIOG_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

    /* Peripheral interrupt init*/
    HAL_NVIC_SetPriority(LPUART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(LPUART1_IRQn);
       
                LL_LPUART_SetWKUPType(LPUART1, LL_LPUART_WAKEUP_ON_RXNE);
                LL_LPUART_EnableIT_RXNE(LPUART1);
                LL_LPUART_EnableIT_IDLE(LPUART1);
                //LL_LPUART_EnableIT_WKUP(LPUART1);
  }
}


时钟:LPUART1 一直是使用的HSI
<
收藏 评论10 发布时间:2019-5-6 02:13

举报

10个回答
creep 回答时间:2019-5-6 09:19:28
【实战经验】LPUART唤醒STOP MODE下的MCU
https://www.stmcu.org.cn/module/ ... mp;highlight=lpuart
(出处: 论坛-意法半导体STM32/STM8技术社区)

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

edmundlee 回答时间:2019-5-6 06:51:08
这类需要唤醒的通信, 需要有个唤醒的头码再加个暂停, 然后才发数据。
接收方被唤醒后就等IDLE中断, 后清了SR, 等数据。
否则数据前面的部分一定会收错的

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

lvfeng123 回答时间:2019-5-6 09:02:38
日他仙人板板, 就睡3个小时。 解决了部分问题。。 把速度降低到9600,正常了。

还有问题 。 时钟唤醒后有必要重新初始化吗? 有没有简化的路径呢?
lvfeng123 回答时间:2019-5-6 09:03:50
  1. void LPUART1_IRQHandler(void){

  2.         if(RESET != __HAL_UART_GET_FLAG(&hlpuart,UART_FLAG_RXNE)){
  3.   if(LL_LPUART_IsActiveFlag_WKUP(LPUART1) && LL_LPUART_IsEnabledIT_WKUP(LPUART1)){
  4.                         LL_LPUART_DisableIT_WKUP(LPUART1);
  5.                         LL_LPUART_ClearFlag_WKUP(LPUART1);
  6.                   //rxBuffer[rxCounts++] = LL_LPUART_ReceiveData8(LPUART1);
  7.                 SystemClock_Config();
  8.         }
  9.                 isRec = 1;
  10.                 if(rxCounts < 204) {
  11.                         rxBuffer[rxCounts++] = LPUART1->RDR;                       
  12.                 }else{
  13.                         rxBuffer[0] = LPUART1->RDR;
  14.                         rxCounts = 255;
  15.                 }
  16.         }
  17.   if(RESET != __HAL_UART_GET_FLAG(&hlpuart,UART_FLAG_IDLE)){
  18.                 if(rxCounts == 204){
  19.                         HAL_UART_Transmit(&hlpuart,rxBuffer,204,0xFFFF);
  20.                         vr();
  21.                 }
  22.                 //HAL_UART_Transmit(&hlpuart,(uint8_t*)&"OK!",3,0xFFFF);
  23.                 __HAL_UART_CLEAR_IDLEFLAG(&hlpuart);
  24.                 isRec = 0;
  25.                 rxCounts = 0;
  26.                 //if(isRec==0) SYS_Sleep(&Lpuart1);
  27.         }
  28.         HAL_UART_IRQHandler(&hlpuart);
  29. }
复制代码
3111272 回答时间:2019-5-6 09:05:35
大神厉害了,膜拜一下
q44044 回答时间:2019-5-6 09:12:36
LPUART1最高只能支持9600吧。
waiman-156411 回答时间:2019-5-6 11:16:25
首先
        LPUART 有3种触发唤醒事件,        包括:
                UART_WAKEUP_ON_ADDRESS            地址匹配        
                UART_WAKEUP_ON_STARTBIT           开始位事件
                UART_WAKEUP_ON_READDATA_NONEMPTY  接收非空事件

建议选用起始位,这样可以加快唤醒时序

LPUART 可以运行在 PCLK1,LSE,HSI,SYSCLK 4个时钟源,但在需要在STOP模式唤醒,则
只能使用LSE,HSI, 而LSE时钟源下,最大波特率只有9600。

必须指定唤醒后使用HSI时钟,否则唤醒后,由于时钟重新初始化浪费时间,会导致接收数据不完整

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

天臆弄人 回答时间:2019-5-7 17:19:55
佩服 奋战凌晨2点半,请问你自己是老板吗
maxtch 回答时间:2019-5-7 19:33:55
天臆弄人 发表于 2019-5-7 17:19
佩服 奋战凌晨2点半,请问你自己是老板吗

如果不是老板,除非说能确保拿到调休或加班工资,万万不要这么卖命。
12下一页

所属标签

相似问题

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