IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> QT连载4:基于QT和STM32H750的LORA试验平台(3) -> 正文阅读

[嵌入式]QT连载4:基于QT和STM32H750的LORA试验平台(3)

前言

? ? 前面已经介绍了QT的制作,包含收发和配置三部分。下面介绍STM32H750的程序架构。

? ? 先将程序的架构大致分为3个部分:

? ? 第一部分:根据收发机制,H750接收串口(暂时这样叫,这样好区分)将QT发送的数据接收,去除报头,提取数据,然后通过发送串口1发送给LORA1。

? ? 第二部分:LORA1发送后,LORA2接收,通过LORA2的接收串口,将数据保存。

? ? 第三部分:将LORA2接收的数据加入报头,通过LORA2的发送串口传递给QT,之后再QT中显示。

? ? 由于QT部分已经在上节中已经详细介绍,现介绍除了QT的剩下部分。

第一部分:初始化

UART_HandleTypeDef UART1_Handler; //UART??±ú
DMA_HandleTypeDef  UART1TxDMA_Handler;      //DMA??±ú

void UART1_Init(u32 bound)
{	
	//UART 3?ê??ˉéè??
	UART1_Handler.Instance=USART1;					    //USART1
	UART1_Handler.Init.BaudRate=bound;				    //2¨ì??ê
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //×?3¤?a8??êy?Y??ê?
	UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //ò???í£?1??
	UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //?T????D£?é??
	UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //?Tó2?tá÷??
	UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //ê?·¢?£ê?
	HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()?áê1?üUART1
	
	HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);
}

? ? 一块一块解释:

? ? 定义串口中断,定义发送DMA中断;

? ? 串口初始化函数

? ? 中间部分为串口的定义:串口1、波特率等等,这部分可以不用改

? ? 最后一句:将接收中断的数据放进buffer里面,定义buffer数,这里定义为1个。

void MYDMA1_Config(void)
{ 
    __HAL_RCC_DMA2_CLK_ENABLE();//DMA2ê±?óê1?ü	
    __HAL_LINKDMA(&UART1_Handler,hdmatx,UART1TxDMA_Handler);    
    
    UART1TxDMA_Handler.Instance=DMA2_Stream5;                            //êy?Yá÷????
	UART1TxDMA_Handler.Init.Request=DMA_REQUEST_USART1_TX;			//USART1·¢?íDMA
    UART1TxDMA_Handler.Init.Direction=DMA_MEMORY_TO_PERIPH;             //′?′¢?÷μ?íaéè
    UART1TxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                 //íaéè·???á??£ê?
    UART1TxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                     //′?′¢?÷??á??£ê?
    UART1TxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;   
    UART1TxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;      
    UART1TxDMA_Handler.Init.Mode=DMA_NORMAL;                            //íaéèá÷???£ê?
    UART1TxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;               //?Dμèó??è??
    UART1TxDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              
    UART1TxDMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
    UART1TxDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;                
    UART1TxDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;            
    
    HAL_DMA_DeInit(&UART1TxDMA_Handler);   
    HAL_DMA_Init(&UART1TxDMA_Handler);
} 
 
void DMA2_Stream5_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&UART1TxDMA_Handler);

}
void USART1_IRQHandler(void)                	
{ 
	HAL_UART_IRQHandler(&UART1_Handler);	//μ÷ó?HAL?a?D??′|àí1?ó?oˉêy

} 

? ? 此处为定义DMA初始化,DMA中断入口,没有中断处理函数。串口1中断入口。

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
	GPIO_InitTypeDef GPIO_Initure;

	if(huart->Instance==USART1)//è?1?ê?′??ú1£???DD′??ú1 MSP3?ê??ˉ
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//ê1?üGPIOAê±?ó
		__HAL_RCC_USART1_CLK_ENABLE();			//ê1?üUSART1ê±?ó
	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//?′ó?í?íìê?3?
		GPIO_Initure.Pull=GPIO_PULLUP;			//é?à-
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//???ù
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//?′ó??aUSART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//3?ê??ˉPA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//3?ê??ˉPA10
		
		HAL_NVIC_EnableIRQ(USART1_IRQn);				//ê1?üUSART1?D??í¨μà
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//?à??ó??è??3£?×óó??è??3	
		
		HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 3, 4);
        HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
	}
}

? ? 此处为串口初始化自动调用函数,如果定义串口1,那么会直接调用这个函数,里面定义管脚类型,中断类型,以及绑定串口和DMA。

第二部分:中断函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//è?1?ê?′??ú1
	{
		
		HostSpareSetData();
		
    HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);
	}
}

? ? 此处为串口接收中断。并配合HostSpareSetData()函数使用。

void HostSpareSetData(void)                  
{
		nSciaRxBuffer[nSciaRxBufHead]=aRxBuffer[0];
		nSciaRxBufHead++;
		if(nSciaRxBufHead>=SCIA_RX_BUF_SIZE)	nSciaRxBufHead=0;
		if(nSciaRxBufHead==nSciaRxBufTail)
		{
			nSciaRxBufTail++;
			if(nSciaRxBufTail>=SCIA_RX_BUF_SIZE)	nSciaRxBufTail=0;
		}
}

? ? 此函数为串口有数据后,进入中断,将中断数据的buffer内容放进一个fifo里面。然后再解析fifo。

第三部分:while执行

void HostSpareSetDataDeal(void)
{
	int i=0;
	nSciaRxLengthTemp = nSciaRxBufHead - nSciaRxBufTail;
	if( nSciaRxLengthTemp < 0 ) nSciaRxLengthTemp = nSciaRxLengthTemp+ SCIA_RX_BUF_SIZE;
	
	switch( nSciaRxCtrlMode )
	{
		case MODE_SCIARXCMD_WAIT:
			nSciaRxVerify = 0xFFFF;							
			if( nSciaRxLengthTemp >= 8 )
			{
				nSciaRxHeadCheck = SciaRdCharRxBuff(); 		
				if( nSciaRxHeadCheck == 0x03 )      
				{
          nSciaRxCtrlMode = MODE_SCIARX_LORA1;
				}
				if( nSciaRxHeadCheck == 0x04 )      
				{
          nSciaRxCtrlMode = MODE_SCIARX_LORA2;
				}				
			}
		break;
		case MODE_SCIARX_LORA1:					
			  nSciaRxOrder = SciaRdCharRxBuff();
				if( nSciaRxOrder == 0x06 )      
				{
          nSciaRxCtrlMode = MODE_SCIARX_LORA1_INIT;
				}
				if( nSciaRxOrder == 0x10 )      
				{
					nSciaRxID = SciaRdWordRxBuff();	
		      nSciaRxDataLength = SciaRdWordRxBuff();
          nSciaRxCtrlMode = MODE_SCIARX_LORA1_SEND;
				}	
		break;			
		case MODE_SCIARX_LORA2:					
			  nSciaRxOrder = SciaRdCharRxBuff();
				if( nSciaRxOrder == 0x06 )      
				{
          nSciaRxCtrlMode = MODE_SCIARX_LORA2_INIT;
				}
				if( nSciaRxOrder == 0x10 )      
				{
					nSciaRxID = SciaRdWordRxBuff();	
		      nSciaRxDataLength = SciaRdWordRxBuff();
          nSciaRxCtrlMode = MODE_SCIARX_LORA2_SEND;
				}	
		break;		
}	

? ? 此部分在while里面执行,具体流程为:中断里放数,这里解析数据。其中03和04代表不同的LORA发送的数据。具体可以看前面文章的通讯协议。当解析完数据后,再添加对应的case,就可以处理不同的数据了。

		case MODE_SCIARX_LORA1_SEND:
			  if( nSciaRxLengthTemp >= (nSciaRxDataLength+2) )
			  {
					for(i=0;i<nSciaRxDataLength;i++)
					{
					  nSciaRxData[i+3] = SciaRdCharRxBuff();
					}
					nSciaRxVerifyTemp = nSciaRxVerify;
				  nSciaRxCheck = SciaRdWordRxBuff();
				  nSciaRxVerifyTemp = HLChange(nSciaRxVerifyTemp);
				  if(nSciaRxVerifyTemp == nSciaRxCheck)
				  {
						nSciaRxData[0] = 0x5A;
						nSciaRxData[1] = 0xA5;
						nSciaRxData[2] = nSciaRxDataLength;
						
						nSciaTxVerify = 0xFFFF;		
						for(i=0;i<nSciaRxDataLength+3;i++)
						{
						  nSciaTxVerify = GetCRC16(nSciaRxData[i], nSciaTxVerify); 
						}		
						nSciaRxData[nSciaRxDataLength+3] = nSciaTxVerify&0x00FF;		
						nSciaRxData[nSciaRxDataLength+4] = (nSciaTxVerify&0xFF00)>>8;
						
						HAL_UART_Transmit_DMA(&UART7_Handler,nSciaRxData,nSciaRxDataLength+5);						
					}
					nSciaRxCtrlMode = MODE_SCIARXCMD_WAIT;
				}
		break;			
		case MODE_SCIARX_LORA2_SEND:					
			  if( nSciaRxLengthTemp >= (nSciaRxDataLength+2) )
			  {
					for(i=0;i<nSciaRxDataLength;i++)
					{
					  nSciaRxData[i+3] = SciaRdCharRxBuff();
					}
					nSciaRxVerifyTemp = nSciaRxVerify;
				  nSciaRxCheck = SciaRdWordRxBuff();
				  nSciaRxVerifyTemp = HLChange(nSciaRxVerifyTemp);
				  if(nSciaRxVerifyTemp == nSciaRxCheck)
				  {
						nSciaRxData[0] = 0x5A;
						nSciaRxData[1] = 0xA5;
						nSciaRxData[2] = nSciaRxDataLength;
						
						nSciaTxVerify = 0xFFFF;		
						for(i=0;i<nSciaRxDataLength+3;i++)
						{
						  nSciaTxVerify = GetCRC16(nSciaRxData[i], nSciaTxVerify); 
						}		
						nSciaRxData[nSciaRxDataLength+3] = nSciaTxVerify&0x00FF;		
						nSciaRxData[nSciaRxDataLength+4] = (nSciaTxVerify&0xFF00)>>8;
						
						
						HAL_UART_Transmit_DMA(&UART4_Handler,nSciaRxData,nSciaRxDataLength+5);						
					}
					nSciaRxCtrlMode = MODE_SCIARXCMD_WAIT;
				}
		break;

? ? 此处就为添加的case,当前面解析的数据解析之后,就可以进入这个case了,也就是进入这个状态机了。进入后,处理数据,然后发送对应发送数据。

HAL_UART_Transmit_DMA(&UART4_Handler,nSciaRxData,nSciaRxDataLength+5);这个就为发送函数。

第四部分:总结

? ? 发送函数比较简单,就上面最后一句话,将数据放好,长度放好,串口中断入口选好,就可以直接发送了。

? ? 接收函数比较麻烦。步骤是在中断里将接收数据放进buffer,再放进fifo,然后循环里解析数据,然后进行一步一步的跳转。这样就将数据解析并按照逻辑发送该发送的数据了。

? ? 上述程序仅仅是截取了一部分,但是大部分逻辑都在,放进去添加相关定义,就能正确运行了。如果需要源代码的话,可以扫描下面订阅号,届时我会把完整的代码放到里面,如果有什么问题也可以留言,到时候会耐心解释。

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:33:32  更:2021-08-17 15:34:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:38:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码