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

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

[复制链接]
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 回答时间: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点半,请问你自己是老板吗

如果不是老板,除非说能确保拿到调休或加班工资,万万不要这么卖命。
luscu 回答时间:2019-5-16 10:28:41
我看到这个问题的本身不是关键,关键还是要注意身体,除非自己是老板。

所属标签

相似问题

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