当前位置:   article > 正文

关于STM32与OpenMv通讯踩过的那些坑(2)

关于STM32与OpenMv通讯踩过的那些坑(2)

不好意思!因为这几天要准备项目答辩,比较忙,所以没能及时更新。

OenMv方面的问题可以查看上一篇文章哦!
stm32串口接收数据其实大部分朋友都经常使用,应该都没什么问题的,可能我比较笨、总是遇到一些小问题,在这里我和大家分享一下。
后面有串口接收数据详细解析。

我遇到的主要问题是在串口中断服务函数那里出的错。我写代码程序一般都比较喜欢用LED作为调试使用。因为这样可以很明确知道程序运行到哪一行哪一步。在许多的程序中,这中方法都百试百灵,但这次却成为一个致命的错误,害我找了很久很久,总的来说还是不清楚串口中断的一些细节。

不过,虽然这种led调试方法让串口中断产生了异常,但它确实帮助我查出了OpenMv方面的错误!
接下来我将先和大家分享我利用led调试,检查出OpenMv方面错误的步骤。
下面展示一些 内联代码片

//使用正点原子串口实验源代码
void USART1_IRQHandler(void)                	//串口1中断服务函数
{
		
	uint8_t Res;

	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接受中断(接受到的数据必须是0x0D 0x0A结尾)
		{
				
			Res =USART_ReceiveData(USART1);	//读取接受到的数据(每次是一位八位的数据)
			
			//在这里加入红色led亮起代码,如果红色led亮起,说明进入了串口中断了,并接受到数据
			
			if((USART_RX_STA&0x8000)==0)//接收未完成
				{
					
					//这里也加一个灯吧,但作用不大
					
					if(USART_RX_STA&0x4000)//接收到了0x0D
						{
							if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
							else 
							{
								USART_RX_STA|=0x8000;	//接收完成了
								
								//加入LED灯,判断有没有接收到0x0A,结束符
								
							}
						}
					else //还没收到0x0D
						{	
							if(Res==0x0d)
							{
								USART_RX_STA|=0x4000;
								
								//加入led,判断有没有接收到0x0D,结束符
								
							}
							else
							{
								USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
								USART_RX_STA++;
								
								//加入led,判断有没有进入数据转换
								
								if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始
							}		 
						}
				}   		 
     } 

} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

就是这样,看那些LED亮起来了,就可以明确程序运行到哪一步,因为接收结束符的那些LED灯没有亮起,一步步慢慢调试逐步发现问题根源。

那为什么我的串口中断服务函数会出现错误的呢,后来我在论坛上看到,有一位大佬说,最好不要再中断服务函数里面写太多的程序,然而我加入的led灯程序是这样的
bule = 0;
delsy-ms(200);
bule = 1;
200毫秒,对于单片机在说已经以很长很长的了,可以运行很多其他的代码了,大佬说的不要再服务函数里面写太多的程序的意思是,不要让程序再服务函数里面运行太久。我觉得说的很有道理,后来改了运行就正常了。问题解决。哎,这个问题真的搞了我好久好久。裂开。

下面是串口接收多帧数据的流程:
下面展示一些 内联代码片

//使用正点原子串口实验源代码
u8 USART_RX_BUF[USART_REC_LEN];          //一个八位的数组,用于存储接收的字符
u16 USART_RX_STA=0;      //这是一个接收的标志位,是程序员用来识别和记录用的,开始的时候我以为这个是stm内部的一个寄存器(说出来羞死人)
											//bit15 接收到完成标志位,收到0x0A程序就会将这位置1
											//bit14 接收到0x0D,收到0x0D程序就会将这位置1
											//bit0~13 用于记录接收到的字符的长度
  //那接下来我们开始接收数据啦!首先USART_RX_STA和USART_RX_BUF[USART_REC_LEN]都是空的;所有位都是零

void USART1_IRQHandler(void)                	//串口1中断服务函数
{
		
	uint8_t Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接受中断(接受到的数据必须是0x0D 0x0A结尾)
	!!!第一步  进入串口中断后,继续判断是否真的接收状态为真,也就是是否真的收到数据了,其实进入服务函数也就说明是接收到数据了,但为什么还要这样做呢,我也不是很清楚,可能是严谨一些吧,或者其他原因,有大佬知道的欢迎评论
		{
				
			Res =USART_ReceiveData(USART1);	//读取接受到的数据(每次是一位八位的数据)
			!!!第二步  串口收到数据后会将数据放在寄存器里面,我们通过这个函数USART_ReceiveData();读取出来,赋值给Res
			if((USART_RX_STA&0x8000)==0)//接收未完成
			!!!第三步  判断是否接受完成,我们才刚刚开始,怎么可能完成了呢 是吧,刚刚进来,USART_RX_STA的bit15位还是零,
			所以接受没完成,可以进入下一步。有朋友就有疑问了,诶!如果bit15是1,程序进入不了这一步,那中断服务函数岂不是运行
			了一段中程序吗,而且如果程序进来的话,一般我们都不是要进行数据存储和转换的吗?所以为什么要这么做呢!其实我们在接
			收完一帧一条字符串数据后,一般都在要进行一些处理是吧,比如在主函数里面进行一个数据的比较,那我们比较数据是要消耗
			时间的,如果让新的数据继续存到我们的USART_RX_BUF()数组里面,那主函数的数据比较不就会出错吗?所以我们会在数
			据用完后才将USART_RX_STA的bit15重新置零,置零后才能开始一次新的接收。所以,在OpenMv发送数据是,我们每次发送
			玩一次数据后,需要等待一段时间后才能继续发送,不然stm在处理数据(也就是bit15还没置零的时候)那段时间,你发送的数
			据我也是不会存储起来的,这样就会造成数据的丢失。
				{
			!!!第四步  在这里会进行一个判断,大家慢慢看就可以理解。		  现在  USART_RX_STA的bit14位还是零,所以不能进入if
			语句,程序跳到else语句。我们去else语句看看。
					if(USART_RX_STA&0x4000)//接收到了0x0D
						{
						!!!第六步  收到0x0d,USART_RX_STA的bit14置1 ,程序进入这一步,接下来会进行一个判断,判断Res是不是等
						于0x0a,因为一个完整的结束标志是有0x0d和0x0a组成的,缺一个也不可以。如果是,那就是这一帧一条数据真的完
						成了,进入else,将USART_RX_STA的bit15置1.。如果不是那就是接收发生错误了,需要重新开始。USART_RX_STA
						需要清零,不然bit14还是1,下次进入服务函数,程序就会以为已经收到0x0d了。
						那我们接受的步骤就讲完了。
							if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
							else 
							{
								USART_RX_STA|=0x8000;	//接收完成了
							}
						}
					else //还没收到0x0D
						{	
						!!!第五步  在这里也有一个判断,如果Res == 0x0D(结束符开始),如果是那就进入if语句,就会将USART_RX_STA
						的bit14位置1,标志着收到0x0d了。如果不等于0x0d,那就进入else语句,else里面的程序首先是将Res的数据给
						USART_RX_BUF数组存起来。然后有一个数据长度的判断,如果数据超过我们定于的长度后,那肯定就是错了
						呀(当然这可能是我们定于的数组长度太小了,我们可以根据需要调大一点)所以这里一般不会出错 只需要将空间
						调大一点就行,不过会消耗存储空间,适当就行。如果我们在这次接受到了0x0D,那么下次再第四步的判断结果就
						会发生改变(如果还没接收到0x0d,那下次进入中断还是这样运行下来,知道收到0xod才改变),那下面我们去看
						看收到0x0d后的运行步骤。
							if(Res==0x0d)
							{
								USART_RX_STA|=0x4000;
							}
							else
							{
								USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
								USART_RX_STA++;
								if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始
							}		 
						}
				}   		 
     } 

} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

话比较多,不过对新手应该比较友好。
当然,说多错多,各位发现了希望可以及时提出。

接受数据我们就完成了,可能还有一个东西可以讲讲,就是将我们收到的数据和程序已经提前设定好的数据进行比较。通过这样的处理我们就真正的可以利用串口了。
这个我们下一篇文章写。

想查看OpenMv代码的可以查看上一篇文章。
关于STM32与OpenMv通讯踩过的那些坑(1)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/474116
推荐阅读
相关标签
  

闽ICP备14008679号