lvfeng123 发表于 2019-5-6 02:13:25

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

板子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 = LL_LPUART_ReceiveData8(LPUART1);
                SystemClock_Config();
        }
//持续接收完当前帧;保存计数, 超过8字节按照错误随便处理。
        if(RESET != __HAL_UART_GET_FLAG(&hlpuart,UART_FLAG_RXNE)){

                isRec = 1;
                if(rxCounts < 8) {
                        rxBuffer = LPUART1->RDR;                       
                }else{
                        rxBuffer = 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

creep 发表于 2019-5-6 09:19:28

【实战经验】LPUART唤醒STOP MODE下的MCU
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=611266&highlight=lpuart
(出处: 论坛-意法半导体STM32/STM8技术社区)

edmundlee 发表于 2019-5-6 06:51:08

这类需要唤醒的通信, 需要有个唤醒的头码再加个暂停, 然后才发数据。
接收方被唤醒后就等IDLE中断, 后清了SR, 等数据。
否则数据前面的部分一定会收错的

lvfeng123 发表于 2019-5-6 09:02:38

日他仙人板板, 就睡3个小时。 解决了部分问题。。 把速度降低到9600,正常了。

还有问题 。 时钟唤醒后有必要重新初始化吗? 有没有简化的路径呢?

lvfeng123 发表于 2019-5-6 09:03:50

void LPUART1_IRQHandler(void){

        if(RESET != __HAL_UART_GET_FLAG(&hlpuart,UART_FLAG_RXNE)){
if(LL_LPUART_IsActiveFlag_WKUP(LPUART1) && LL_LPUART_IsEnabledIT_WKUP(LPUART1)){
                        LL_LPUART_DisableIT_WKUP(LPUART1);
                        LL_LPUART_ClearFlag_WKUP(LPUART1);
                  //rxBuffer = LL_LPUART_ReceiveData8(LPUART1);
                SystemClock_Config();
        }
                isRec = 1;
                if(rxCounts < 204) {
                        rxBuffer = LPUART1->RDR;                       
                }else{
                        rxBuffer = LPUART1->RDR;
                        rxCounts = 255;
                }
        }
if(RESET != __HAL_UART_GET_FLAG(&hlpuart,UART_FLAG_IDLE)){
                if(rxCounts == 204){
                        HAL_UART_Transmit(&hlpuart,rxBuffer,204,0xFFFF);
                        vr();
                }
                //HAL_UART_Transmit(&hlpuart,(uint8_t*)&"OK!",3,0xFFFF);
                __HAL_UART_CLEAR_IDLEFLAG(&hlpuart);
                isRec = 0;
                rxCounts = 0;
                //if(isRec==0) SYS_Sleep(&Lpuart1);
        }
        HAL_UART_IRQHandler(&hlpuart);
}

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时钟,否则唤醒后,由于时钟重新初始化浪费时间,会导致接收数据不完整

天臆弄人 发表于 2019-5-7 17:19:55

佩服 奋战凌晨2点半,请问你自己是老板吗

maxtch 发表于 2019-5-7 19:33:55

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

如果不是老板,除非说能确保拿到调休或加班工资,万万不要这么卖命。
页: [1] 2
查看完整版本: 折腾了半夜搞不定,求帮助~~