板子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 |
https://www.stmcu.org.cn/module/ ... mp;highlight=lpuart
(出处: 论坛-意法半导体STM32/STM8技术社区)
评分
查看全部评分
接收方被唤醒后就等IDLE中断, 后清了SR, 等数据。
否则数据前面的部分一定会收错的
评分
查看全部评分
还有问题 。 时钟唤醒后有必要重新初始化吗? 有没有简化的路径呢?
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时钟,否则唤醒后,由于时钟重新初始化浪费时间,会导致接收数据不完整
评分
查看全部评分
如果不是老板,除非说能确保拿到调休或加班工资,万万不要这么卖命。