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

STM32L051串口(LPUART)通讯错误?

[复制链接]
abc5504@139.com 提问时间:2021-9-14 22:44 /
硬件基本情况:STM32L051,HSE=4M,LSE=32.768k程序基本流程及问题见下图(虽然工作正常了,但实在想不明白原因.....)

程序基本流程

程序基本流程



收藏 评论9 发布时间:2021-9-14 22:44

举报

9个回答
butterflyspring 回答时间:2021-9-15 11:26:39
建议楼主先屏蔽掉传感器等相关任务,试试看是不是LPUART本身工作的问题,还是软件逻辑造成的问题。目前找问题的线索不多。
abc5504@139.com 回答时间:2021-9-15 22:33:45
butterflyspring 发表于 2021-9-15 11:26
建议楼主先屏蔽掉传感器等相关任务,试试看是不是LPUART本身工作的问题,还是软件逻辑造成的问题。目前找问 ...

找原因的过程中确实试过先关闭一些调用,发现屏蔽掉传感器启动代码问题就消失,但是传感器启动代码仅仅是调用HAL的I2C库,执行一个写操作,实在是太简单了,所以不认为是它的原因。
传感器启动代码如下:
if(xxx_Err) xxx_Config();                      //发生错误,尝试重新配置传感器
xxx_Ctl(xxx_Mode_Continuous);              //启动传感器

/* 函数xxx_Ctl定义如下*/
HAL_StatusTypeDef xxx_Ctl(xxx_WorkMode Mode)
{
        uint8_t u8Cmd[2];
        u8Cmd[0]=(uint8_t)Mode;
        return HAL_I2C_Mem_Write(&hIIC2,SP16_Adr,0x8,I2C_MEMADD_SIZE_8BIT,u8Cmd,1,10);
}

------------------------------------------------



芯片唤醒后有一个时钟恢复函数,用来启动HSE。执行完时钟恢复就转到主循环开始处,添加的延时操作,实际就是在主循环开始处多”耗“了一些时间。会不会时钟恢复有什么不妥?代码如下
/*停机唤醒后恢复时钟*/
void SystemClock_Stop(void)
{
       RCC_OscInitTypeDef RCC_OscInitStruct = {0}                                                                                                                                                                                               
       RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
       
        __HAL_RCC_PWR_CLK_ENABLE();
        __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
        HAL_RCC_GetOscConfig(&RCC_OscInitStruct);
       
        //开启HSE(等待HSE就绪)
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
        RCC_OscInitStruct.HSEState = RCC_HSE_ON;
        if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
       {
          Error_Handler();
        }
               
        //配置总线时钟
        //RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
        //                            |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
        RCC_ClkInitStruct.ClockType=RCC_CLOCKTYPE_SYSCLK;
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
       //RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
       //RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
       //RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
       if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
       {
          Error_Handler();
        }
}

butterflyspring 回答时间:2021-9-16 17:46:20
从函数上看,启动传感器像是写存贮器,是哪个存贮器,通常写EEPROM 或者 FLASH会有等待时间,所以耗时比较长一点。 另外可以试试时钟恢复函数里不启动HSE,就用默认的内部时钟,看看串口的数据有没有影响。
abc5504@139.com 回答时间:2021-9-17 08:43:21
butterflyspring 发表于 2021-9-16 17:46
从函数上看,启动传感器像是写存贮器,是哪个存贮器,通常写EEPROM 或者 FLASH会有等待时间,所以耗时比较 ...

昨天又试试----只要在时钟恢复函数后面增加延时就能解决问题,但是原因怎么也想不明白。启动传感器是个写寄存器过程,调用的是写存储器方法。
我最不能理解的是通讯错误的具体现象,通讯过程实际是主机发一条Modbus指令,指令内容是01 04 03 E8 00 08 71 BC 。
当通讯错误发生时,MCU实际收到的串口数据是01 04 03 E8 80 08 71 BC ,仅仅是第5字节错误(最高位错误),其它字节完全正确,字节数也正确。而且每次出错情况都相同。
butterflyspring 回答时间:2021-9-17 11:09:08
abc5504@139.com 发表于 2021-9-17 08:43
昨天又试试----只要在时钟恢复函数后面增加延时就能解决问题,但是原因怎么也想不明白。启动传感器是个写 ...

从程序架构上看,时钟恢复函数刚好后面就是传感器启动中的I2C写函数啊。 那个写I2C函数建议仔细看看或测试一下,如上次所说,如果是写外部存贮器时需要等待时间,是不是影响到串口的处理程序?另外,你的串口接收是否是中断方式,如果是的话,可以考虑在中断中触发信号(IO),看看这个时刻是不是恰好在I2C写的某段程序处。(反之没有这段写代码,串口数据也就正常了)
abc5504@139.com 回答时间:2021-9-17 11:20:17
butterflyspring 发表于 2021-9-17 11:09
从程序架构上看,时钟恢复函数刚好后面就是传感器启动中的I2C写函数啊。 那个写I2C函数建议仔细看看或测 ...

感谢关注和回复!
abc5504@139.com 回答时间:2021-9-17 11:21:38

写I2C是非中断方式,我简单看了一下HAL库的I2C写函数,没有发现关中断的地方,回头再仔细看看。
abc5504@139.com 回答时间:2021-9-17 11:32:15
butterflyspring 发表于 2021-9-17 11:09
从程序架构上看,时钟恢复函数刚好后面就是传感器启动中的I2C写函数啊。 那个写I2C函数建议仔细看看或测 ...

串口通讯是中断方式,每接收一个字节就会中断一次,然后放入缓存区,接着启动定时器做超时检测,当超时发生时即认为接收完成,接着调用消息处理过程。因为I2C操作是非中断方式,任何时候串口接收(中断)都会优先于I2C操作,按理只会串口通讯影响I2C操作,反过来却不会。
自己感觉方向不对,回头再试试吧。
butterflyspring 回答时间:2021-9-17 15:04:38
串口是中断方式,可以考虑增加几行行代码并打上断点。这几行代码判断是错误数据(0x80),这时候就可以看看前后代码运行到什么地方,是否有些线索。另外启动传感器的I2C里面去写什么设备?
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版