前言
? ? 前面已经介绍了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,然后循环里解析数据,然后进行一步一步的跳转。这样就将数据解析并按照逻辑发送该发送的数据了。
? ? 上述程序仅仅是截取了一部分,但是大部分逻辑都在,放进去添加相关定义,就能正确运行了。如果需要源代码的话,可以扫描下面订阅号,届时我会把完整的代码放到里面,如果有什么问题也可以留言,到时候会耐心解释。
?
|