603|8

4

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

程序在运行时进入HardFault_Handler中 [复制链接]

本帖最后由 r123h 于 2024-5-8 17:56 编辑

stm32f103zet6写了一个通过uart5控制梅特勒托利多的天平的程序。uart5的配置和中断函数如下

void Uart5InitFor485(void)
{
    USART_InitTypeDef USART_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
    USART_InitStructure.USART_BaudRate = 9600;	
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(UART5, &USART_InitStructure);
    USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
    USART_Cmd(UART5, ENABLE);
	  USART_ClearFlag(UART5,USART_FLAG_TC);  
}

	NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	USART5_Rx_Buffer.buffer = (u8*)malloc(USART5_RX_BUFFER_SIZE);
    memset(USART5_Rx_Buffer.buffer,0,USART5_RX_BUFFER_SIZE);
    USART5_Rx_Buffer.index = 0;
    USART5_Rx_Buffer.maxSize = USART5_RX_BUFFER_SIZE;

void UART5_IRQHandler(void)
{
    u8 res;
    if(USART_GetFlagStatus(UART5,USART_FLAG_ORE)==SET)
	{
		USART_ClearFlag(UART5,USART_FLAG_ORE);                                   //¶ÁSRÆäʵ¾ÍÊÇÇå³ý±êÖ¾
		res = USART_ReceiveData(UART5);
        if(USART5_Rx_Buffer.index < USART5_Rx_Buffer.maxSize)
        {
            USART5_Rx_Buffer.buffer[USART5_Rx_Buffer.index] = res;
            USART5_Rx_Buffer.index ++;
        }
	}	
	if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)  
	{
		res =USART_ReceiveData(UART5);	
        if(USART5_Rx_Buffer.index < USART5_Rx_Buffer.maxSize)
        {
            USART5_Rx_Buffer.buffer[USART5_Rx_Buffer.index] = res;
            USART5_Rx_Buffer.index ++;
        }
    } 
    if(USART_GetITStatus(UART5, USART_FLAG_TC) != RESET)
    {
        return ;
    }
}

其中一个对天平进行清零的程序(采用的梅特勒自己的通信协议发送“Z\r\n”,返回“Z A\r\n”为清零任务完成且成功)代码如下

bool ZeroBalancebyUart(void)
{
	u32 buffer[3] = {0};
	buffer[0]=0x5A;
	buffer[1]=0x0D;
	buffer[2]=0x0A;
		for(int i=0;i<3;i++)
	{
		while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET){};	  
		USART_SendData(UART5,buffer[i]);
	}
    while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET){};
    delay_ms(50);
		u8 bufferRec[30] = {0};
    int recLen = 0;
		getUart5RecData(bufferRec,&recLen);
		if((bufferRec[0] == 0x5A) && (bufferRec[2] == 0x41) && recLen==5)
		{
			return true;
		}
		else
    {
       return false;
    }
}

void getUart5RecData(u8 *data,int* len)
{
    *len = USART5_Rx_Buffer.index;
     memcpy(data,USART5_Rx_Buffer.buffer,USART5_Rx_Buffer.index);
     USART5_Rx_Buffer.index = 0;
	   memset(USART5_Rx_Buffer.buffer,0,sizeof(USART5_Rx_Buffer.buffer));
}

但是在清零任务的时候程序进入HardFault_Handler,调用堆栈窗口第二行只有0x00000000

寄存器那边R14(LR)=0xFFFFFFFD,所以又去找了PSP,最后定位在了getUart5RecData()函数里面的“ USART5_Rx_Buffer.index = 0;”这一行。但是其他几个串口也使用了类似的函数都没有问题,实在找不到问题出在哪里了

而且还不是每次都会出现,可能隔几个小时就会出现一次

此帖出自stm32/stm8论坛

最新回复

递归溢出了?   详情 回复 发表于 2024-5-9 13:32
点赞 关注
 

回复
举报

4

帖子

0

TA的资源

一粒金砂(中级)

来自 4楼
 

同样是对天平操作的代码,读取天平的重量和其他部分的运行,因为数量很多所以采用了递归的方法

void ProcessSamples(int samplePositions[],u16 num,int totalSamples,u32 *Weightbuffer)
{
	 if (num >= totalSamples) 
		{
        return;
    }
	 ProcessSample(samplePositions[num],Weightbuffer);
	 ProcessSamples(samplePositions, num + 1, totalSamples,Weightbuffer);

}

void ProcessSample(u16 Samplenum,u32 *Weightbuffer)
{
	  if(StartWorkFlag==false)
	  return;
		SamplefromTurnTable(Samplenum);
	  ArriveBalance();
	  delay_ms(100);
	  u32 Recordweight=Weightbuffer[Samplenum-1];
	while(readBalancebyUart(&Weightbuffer[Samplenum-1])==false)
  {
		delay_sec(2);
  }
	TaskParabuffer.CurSampleWeight=Weightbuffer[Samplenum-1];
	ReturnTurntable(Samplenum);
	u32 differnum = abs(Weightbuffer[Samplenum-1]-Recordweight);
	if(differnum<=PCSetTaskPara.Balanceerronum)
	{
		Recordweight=0;
		PCSetTaskPara.bufferTask[Samplenum-1]=0;
		Weightbuffer[Samplenum-1]=0;
	}
	else{
		Recordweight=0;
	}
}

bool readBalancebyUart(u32 *weight)
{
	float data=0;
	u8 buffer[3] = {0};
	buffer[0]=0x53;
	buffer[1]=0x0D;
	buffer[2]=0x0A;
		for(int i=0;i<3;i++)
	{
		while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET){};	  
		USART_SendData(UART5,buffer[i]);
	}
    while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET){};
    delay_ms(50);
		u8 bufferRec[30] = {0};
    int recLen = 0;
		getUart5RecData(bufferRec,&recLen);
		if((bufferRec[0] == 0x53)&&(bufferRec[2] == 0x53)&&(bufferRec[8] == 0x2E)&& recLen == 0x12)
		{
			u8 dataAddr[9]= {0};
			for(int i = 0;i<9;i++)
			{
				dataAddr[i] = bufferRec[5+i];
			}
			data = atof((char*)dataAddr);
			if(data>150)
			{
				return false;
			}
			*weight=(u32)floor(data*100000);
		}
		else
    {
        return false;
    }
    return true;
}

但是运行到ProcessSample的

while(readBalancebyUart(&Weightbuffer[Samplenum-1])==false)
  {
        delay_sec(2);
  }时程序又进入到HardFault_Handler,然后通过调用堆栈窗口发现在程序运行到   ProcessSample函数的   u32 Recordweight=Weightbuffer[Samplenum-1];之前Samplenum和Weightbuffer的数值和地址是正常的,进入到while(readBalancebyUart(&Weightbuffer[Samplenum-1])==false)
  {
        delay_sec(2);
  }后,Samplenum和Weightbuffer的地址就全不对了,原本Samplenum的值为3变为0x2036,Weightbuffer的地址从0x200043E0变为0x2000430A

此帖出自stm32/stm8论坛
 
 

回复

7196

帖子

2

TA的资源

版主

沙发
 

屏蔽部分代码然后找问题。

此帖出自stm32/stm8论坛
 
 

回复

9792

帖子

24

TA的资源

版主

板凳
 

问题一般出在定位的前一行,你把断点打在memcpy,看一下各参数是不是满足要求。


此帖出自stm32/stm8论坛
 
 
 

回复

6483

帖子

9

TA的资源

版主

5
 

硬件错误是32调试最容易出现的情况,一般都是硬件外设功能运行异常导致的,试着关闭一些外设测试一下

此帖出自stm32/stm8论坛
 
个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 

回复

6105

帖子

4

TA的资源

版主

6
 

这种很多情况都是内存溢出或者相关问题。

比如堆栈的大小是否合适。

        malloc()和free()是否成对使用。

        指针是否指向了不该指向的地方。

        等等。

调试和检查多注意上面的情况。

此帖出自stm32/stm8论坛
 
 
 

回复

9792

帖子

24

TA的资源

版主

7
 

bufferRec只有30个字节,如果串口接收长度大于30就可能溢出


此帖出自stm32/stm8论坛

点评

我将获取串口数据的程序改成了动态分配内存的目前还没有进到HardFault_Handler中,我再测一段时间试试  详情 回复 发表于 2024-5-9 13:55
 
 
 

回复

7628

帖子

18

TA的资源

五彩晶圆(高级)

8
 

递归溢出了?

此帖出自stm32/stm8论坛
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

4

帖子

0

TA的资源

一粒金砂(中级)

9
 
littleshrimp 发表于 2024-5-9 12:48 bufferRec只有30个字节,如果串口接收长度大于30就可能溢出

我将获取串口数据的程序改成了动态分配内存的目前还没有进到HardFault_Handler中,我再测一段时间试试

此帖出自stm32/stm8论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表