折腾了半夜搞不定,求帮助~~
板子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
【实战经验】LPUART唤醒STOP MODE下的MCU
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=611266&highlight=lpuart
(出处: 论坛-意法半导体STM32/STM8技术社区) 这类需要唤醒的通信, 需要有个唤醒的头码再加个暂停, 然后才发数据。
接收方被唤醒后就等IDLE中断, 后清了SR, 等数据。
否则数据前面的部分一定会收错的 日他仙人板板, 就睡3个小时。 解决了部分问题。。 把速度降低到9600,正常了。
还有问题 。 时钟唤醒后有必要重新初始化吗? 有没有简化的路径呢? 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);
} 大神厉害了,膜拜一下 LPUART1最高只能支持9600吧。 首先
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时钟,否则唤醒后,由于时钟重新初始化浪费时间,会导致接收数据不完整 佩服 奋战凌晨2点半,请问你自己是老板吗 天臆弄人 发表于 2019-5-7 17:19
佩服 奋战凌晨2点半,请问你自己是老板吗
如果不是老板,除非说能确保拿到调休或加班工资,万万不要这么卖命。
页:
[1]
2