STM32H743 シリアル ポートの同時送受信の問題の概要

        まず、シリアル ポートは受信を中断するためにのみ使用します。受信時に、受信ロジックで問題が発生しました。つまり、HAL_UART_Receive(); および HAL_UART_Receive_IT(); 関数の使用については、私の最初の記事を参照してください。解決されました。

        今回は、送信と受信に同じシリアル ポートが使用されます。シリアル ポートを通じて特定のバイトをステアリング ギアに送信し、ステアリング ギアの関連パラメータを収集します。シリアルポートの送信と受信を同時に行うと、問題が発生します。シリアルポートが受信割り込みに入らない、送信しない、またはスタックして続行しません~

        csdn を通じて一般的な問題を知っています。

HAL_UART_Receive_IT(&Uart2_Handle,(uint8_t *)ces, 1);

HAL_UART_Transmit( &Uart3_Handle, &data ,1,1000);

HAL_UART_Transmit_IT();

HAL_UART_Receive();

        上記の関数は呼び出されたときにシリアル ポートをロックします。これが問題の原因です。

        したがって、最初の解決策があります: 上記の関数内のすべての自己ロック関数をコメントアウトします。残念ながら、この方法は私には機能しません。具体的な方法については、次の記事を参照してください。

(3 メッセージ) STM32 F103 シリアル ポートが同時に送受信するデッドロック問題の解決策

        上記の関数は stm32h7xx_hal_uart.c ファイルで定義されています。

       

         2つ目の解決策は、送受信時にhalライブラリの関連関数を使わずに、stm32f103のようなレジスタを直接操作する方法です、もちろんレジスタは面倒ですが、割り込み受信と送信に関係するレジスタを2つ見つけるだけで済みます。幸いなことに、私はブログで記事を見つけました。ブロガーも同じ問題に遭遇し、解決策は私と同じでした。ブロガーはレジスタを見つけ出し、クリアする必要があるフラグも見つけました。

(メッセージ 3 件) STM32H743 は、シリアル ポートの送信と受信を同時に行うときに発生する問題を解決します_ShineRoyal-CSDN Blog_stm32h743 シリアル ポート割り込み受信

        アイデアのまとめ:シリアルポートのバイト送信関数を再定義し、halライブラリ本来の関数を使わずにレジスタ操作方式を使用、割り込み受信はライブラリの受信関数を使わず、レジスタを直接読み出してフラグビットをクリアするフラグビットを判断して割り込みを再度許可します。

        関連構成: bsp_usart.c ファイル:

#include "bsp_usart.h"
UART_HandleTypeDef Uart6_Handle;
void UART6_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;

	RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
			
	UART6_RX_GPIO_CLK_ENABLE();
	UART6_TX_GPIO_CLK_ENABLE();
	
	/* 配置串口6时钟源*/
	RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART6;
	RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
	HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
	/* 使能 UART6 时钟 */
	UART6_CLK_ENABLE();

	/**USART6 GPIO Configuration    
    PC6    ------> USART6_TX
    PC7    ------> USART6_RX 
	*/
	/* 配置Tx引脚为复用功能  */
	GPIO_InitStruct.Pin = UART6_TX_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = UART6_TX_AF;
	HAL_GPIO_Init(UART6_TX_GPIO_PORT, &GPIO_InitStruct);
	
	/* 配置Rx引脚为复用功能 */
	GPIO_InitStruct.Pin = UART6_RX_PIN;
	GPIO_InitStruct.Alternate = UART6_RX_AF;
	HAL_GPIO_Init(UART6_RX_GPIO_PORT, &GPIO_InitStruct); 
	
	/* 配置串USART6 模式 */
	Uart6_Handle.Instance = UART6;
	Uart6_Handle.Init.BaudRate=115200;
	Uart6_Handle.Init.WordLength = UART_WORDLENGTH_8B;
	Uart6_Handle.Init.StopBits = UART_STOPBITS_1;
	Uart6_Handle.Init.Parity = UART_PARITY_NONE;
	Uart6_Handle.Init.Mode = UART_MODE_TX_RX;
/*
    Uart6_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    Uart6_Handle.Init.OverSampling = UART_OVERSAMPLING_16;
    Uart6_Handle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    Uart6_Handle.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_NO_INIT;
   */

	HAL_UART_Init(&Uart6_Handle);
	//__HAL_UART_ENABLE(&UartHandle);
	/*串口6中断初始化 */
    HAL_NVIC_SetPriority(UART6_IRQ, 0, 1);
    HAL_NVIC_EnableIRQ(UART6_IRQ);
    /*配置串口接收中断 */
    __HAL_UART_ENABLE_IT(&Uart6_Handle,UART_IT_RXNE); //关键

}


//定义发送函数:

unsigned char UART6_Putc(unsigned char data)		
{
	Uart6_Handle.Instance->TDR = data;
		while (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_TC) == RESET);
//	HAL_UART_Transmit(&Uart6_Handle, &data ,1,100);
	return data;
}

bsp_usart.h ファイル:

        シリアルポート1~6のピンとその中の関連モードを直接設定し、移植時にシリアルポート6の設定を直接コピーして番号を変更しました。

#ifndef __USARTx_H
#define	__USARTx_H

#include "stm32h7xx.h"
#include <stdio.h>

//引脚定义
///*******************************************************/
USART1:PA9  PA10
//#define UARTx                             USART1
//#define UARTx_CLK_ENABLE()                __USART1_CLK_ENABLE();

//#define RCC_PERIPHCLK_UARTx               RCC_PERIPHCLK_USART1
//#define RCC_UARTxCLKSOURCE_SYSCLK         RCC_USART1CLKSOURCE_SYSCLK

//#define UARTx_RX_GPIO_PORT                GPIOA
//#define UARTx_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
//#define UARTx_RX_PIN                      GPIO_PIN_9
//#define UARTx_RX_AF                       GPIO_AF7_USART1


//#define UARTx_TX_GPIO_PORT                GPIOA
//#define UARTx_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
//#define UARTx_TX_PIN                      GPIO_PIN_10
//#define UARTx_TX_AF                       GPIO_AF7_USART1

//#define UARTx_IRQHandler                  USART1_IRQHandler
//#define UARTx_IRQ                 		    USART1_IRQn
///************************************************************/

/*******************************************************/
//USART1:TX:PA9  RX:PA10
#define UART1                             USART1
#define UART1_CLK_ENABLE()                __USART1_CLK_ENABLE();

#define RCC_PERIPHCLK_UART1               RCC_PERIPHCLK_USART1
#define RCC_UART1CLKSOURCE_SYSCLK         RCC_USART1CLKSOURCE_SYSCLK

#define UART1_RX_GPIO_PORT                GPIOA
#define UART1_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
#define UART1_RX_PIN                      GPIO_PIN_9
#define UART1_RX_AF                       GPIO_AF7_USART1


#define UART1_TX_GPIO_PORT                GPIOA
#define UART1_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
#define UART1_TX_PIN                      GPIO_PIN_10
#define UART1_TX_AF                       GPIO_AF7_USART1

#define UART1_IRQHandler                  USART1_IRQHandler
#define UART1_IRQ                 		    USART1_IRQn
/************************************************************/
/*******************************************************/
//USART2:TX:PA2  RX:PA3
#define UART2                             USART2
#define UART2_CLK_ENABLE()                __USART2_CLK_ENABLE();

#define RCC_PERIPHCLK_UART2               RCC_PERIPHCLK_USART2
#define RCC_UART2CLKSOURCE_SYSCLK         RCC_USART2CLKSOURCE_SYSCLK

#define UART2_RX_GPIO_PORT                GPIOA
#define UART2_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
#define UART2_RX_PIN                      GPIO_PIN_3
#define UART2_RX_AF                       GPIO_AF7_USART2


#define UART2_TX_GPIO_PORT                GPIOA
#define UART2_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
#define UART2_TX_PIN                      GPIO_PIN_2
#define UART2_TX_AF                       GPIO_AF7_USART2

#define UART2_IRQHandler                  USART2_IRQHandler
#define UART2_IRQ                 		    USART2_IRQn
/************************************************************/
/*******************************************************/
//USART3:TX:PC10  RX:PC11
#define UART3                             USART3
#define UART3_CLK_ENABLE()                __USART3_CLK_ENABLE();

#define RCC_PERIPHCLK_UART3               RCC_PERIPHCLK_USART3
#define RCC_UART3CLKSOURCE_SYSCLK         RCC_USART3CLKSOURCE_SYSCLK

#define UART3_RX_GPIO_PORT                GPIOC
#define UART3_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOC_CLK_ENABLE()
#define UART3_RX_PIN                      GPIO_PIN_11
#define UART3_RX_AF                       GPIO_AF7_USART3


#define UART3_TX_GPIO_PORT                GPIOC
#define UART3_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOC_CLK_ENABLE()
#define UART3_TX_PIN                      GPIO_PIN_10
#define UART3_TX_AF                       GPIO_AF7_USART3

#define UART3_IRQHandler                  USART3_IRQHandler
#define UART3_IRQ                 		    USART3_IRQn
/************************************************************/


/*******************************************************/
//UART4:TX:PB9  RX:PB8
#define USART4                             UART4
#define UART4_CLK_ENABLE()                __UART4_CLK_ENABLE();

#define RCC_PERIPHCLK_USART4               RCC_PERIPHCLK_UART4
#define RCC_UART4CLKSOURCE_SYSCLK         RCC_UART4CLKSOURCE_SYSCLK

#define UART4_RX_GPIO_PORT                GPIOB
#define UART4_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
#define UART4_RX_PIN                      GPIO_PIN_8
#define UART4_RX_AF                       GPIO_AF8_UART4


#define UART4_TX_GPIO_PORT                GPIOB
#define UART4_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
#define UART4_TX_PIN                      GPIO_PIN_9
#define UART4_TX_AF                       GPIO_AF8_UART4

#define UART4_IRQHandler                  UART4_IRQHandler
#define UART4_IRQ                 		    UART4_IRQn
/************************************************************/
/*******************************************************/
//USART6:TX:PC6  RX:PC7
#define UART6                             USART6
#define UART6_CLK_ENABLE()                __USART6_CLK_ENABLE();

#define RCC_PERIPHCLK_UART6               RCC_PERIPHCLK_USART6
#define RCC_UART6CLKSOURCE_SYSCLK         RCC_USART6CLKSOURCE_SYSCLK

#define UART6_RX_GPIO_PORT                GPIOC
#define UART6_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOC_CLK_ENABLE()
#define UART6_RX_PIN                      GPIO_PIN_7
#define UART6_RX_AF                       GPIO_AF7_USART6


#define UART6_TX_GPIO_PORT                GPIOC
#define UART6_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOC_CLK_ENABLE()
#define UART6_TX_PIN                      GPIO_PIN_6
#define UART6_TX_AF                       GPIO_AF7_USART6

#define UART6_IRQHandler                  USART6_IRQHandler
#define UART6_IRQ                 		    USART6_IRQn
/************************************************************/


extern UART_HandleTypeDef Uart1_Handle;
extern UART_HandleTypeDef Uart2_Handle;
extern UART_HandleTypeDef Uart3_Handle;
extern UART_HandleTypeDef Uart4_Handle;
extern UART_HandleTypeDef Uart5_Handle;
extern UART_HandleTypeDef Uart6_Handle;

void UART1_Config(void);
void UART2_Config(void);
void UART3_Config(void);
void UART4_Config(void);
void UART6_Config(void);

int fputc(int ch, FILE *f);
int fgetc(FILE *f);

void foot_key_config(void);
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);

void Usart_SendArray(UART_HandleTypeDef *pUSARTx, uint8_t *array, uint16_t num);

unsigned char UART1_Putc(unsigned char data);
unsigned char Uart1_Put_Int16(unsigned int DataToSend);
unsigned char UART2_Putc(unsigned char data);		
unsigned char UART4_Putc(unsigned char data);
unsigned char UART3_Putc(unsigned char data);	
unsigned char UART6_Putc(unsigned char data);



#endif /* __USART1_H */

シリアル割り込みサービス関数:stm32h7xx_hal.c

        stm32h7xx_hal.c ファイルに直接記述し、コールバック関数を呼び出さずに、割り込みサービス関数を通じて受信およびロジック処理を行います。

        キーポイント 1 は、受信関数を RDR レジスタの処理に置き換えることです。

        Uart6_Handle.Instance->RDR;//レジスタはバイトを受信します

        トリガを受信する条件はフラグビット UART_FLAG_RXNE と UART_IT_RXNE を判定することであり、関連する関数を使用する必要があります (次のコードを参照)。

        キーポイント 2 は、バイトを受信した後にフラグ ビットをクリアしてゼロに設定することです。

        キーポイント 3 は、割り込みを再度有効にすることです。

        __HAL_UART_ENABLE_IT(&Uart6_Handle, UART_IT_RXNE); //受信割り込みを有効にする

#include "stm32h7xx_it.h"
#include "stm32h7xx_hal.h"
#include "bsp.h"
#include "bsp_basic_tim.h"
//-------------------------串口6接收中断--------------------------------------------------//

float PI=3.1415926;  
float YAW=0,ROLL=0,PITCH=0;
unsigned char SHU[41]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  //接收缓存
//unsigned char SHU[41]={0};  //接收缓存

uint8_t nn1=39; //接收数据长度


typedef union
{
	unsigned char Receive_Val[3];
	float Act_val;
}u8toointt;
u8toointt yaw,roll,pitch;


void UART6_IRQHandler(void)
{//static
unsigned char ch;
	static unsigned char i = 0; 	//记录数据个数
	static unsigned char j = 0; 
	static unsigned char conunt=0; // 接收记录
	
//判断是否有中断产生	
    if ((__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_RXNE) != RESET) &&
            (__HAL_UART_GET_IT_SOURCE(&Uart6_Handle, UART_IT_RXNE) != RESET))
    {

	ch=Uart6_Handle.Instance->RDR;//寄存器接收一个字节
		switch(conunt)
		{
			case 0:
				if(ch == 0xFF) conunt++;
				else conunt=0;    
				break;
			case 1:
				if(ch == 0x02) conunt ++; //角度包			
				else conunt = 0;
				break;
			case 2://角度包
				SHU[i] = ch;
				i++;
				if(i==41)//接收完成了开始验证;
				{
						if((SHU[39] ==(calcCRC(SHU,nn1)>>8))&&(SHU[40] ==(calcCRC(SHU,nn1)&0xFF))) //判断是否满足校验条件
						{
							for(j=0;j<=3;j++) //roll角度换算:弧度换算成角度
							{
								roll.Receive_Val[j]=SHU[3+j] ;
							}
							 ROLL=roll.Act_val*180/PI;
							
							for(j=0;j<=3;j++) //pitch角度换算:弧度换算成角度
							{
								pitch.Receive_Val[j]=SHU[7+j] ;
							}
							PITCH=pitch.Act_val*180/PI;
							
							for(j=0;j<=3;j++)//yaw角度换算,弧度换算成角度
							{
								yaw.Receive_Val[j]=SHU[11+j] ;
							}
							YAW=yaw.Act_val*180/PI;
							conunt ++;
					 } 
					 else conunt = 0;					
					i = 0;
				}
				break;
			case 3:
				if(ch == 0x03) 	
				{
					conunt = 0; //结束	
				}	
				else conunt = 0;
				break;
		}	
	}
		else //标注位清零
    {
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_ORE) != RESET)
        {
            __HAL_UART_CLEAR_OREFLAG(&Uart6_Handle);
        }
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_NE) != RESET)
        {
            __HAL_UART_CLEAR_NEFLAG(&Uart6_Handle);
        }
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_FE) != RESET)
        {
            __HAL_UART_CLEAR_FEFLAG(&Uart6_Handle);
        }
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_PE) != RESET)
        {
            __HAL_UART_CLEAR_PEFLAG(&Uart6_Handle);
        }
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_CTS) != RESET)
        {
            __HAL_UART_CLEAR_IT(&Uart6_Handle, UART_FLAG_CTS);
        }
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_TXE) != RESET)
        {
            __HAL_UART_CLEAR_IT(&Uart6_Handle, UART_FLAG_TXE);
        }
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_TC) != RESET)
        {
            __HAL_UART_CLEAR_IT(&Uart6_Handle, UART_FLAG_TC);
        }
        if (__HAL_UART_GET_FLAG(&Uart6_Handle, UART_FLAG_RXNE) != RESET)
        {
            __HAL_UART_CLEAR_IT(&Uart6_Handle, UART_FLAG_RXNE);
        }
    }
		__HAL_UART_ENABLE_IT(&Uart6_Handle, UART_IT_RXNE);	//使能接收中断

}
     

        移行方法: コード内の switch-case ステートメントを受信および処理ロジックに置き換えます。

        割り込みサービス関数の crc 検証コードが添付されています。

signed short int calcCRC (const unsigned char *pBuffer, signed short int bufferSize);//CRC校验

signed short int calcCRC (const unsigned char *pBuffer, signed short int bufferSize)//CRC校验
{

	uint16_t poly = 0x8408;
	uint16_t crc = 0;
	unsigned char carry;
	unsigned char i_bits;
	static uint16_t j;
	for (j=0; j<bufferSize; j++)
	{
			crc = crc ^ pBuffer[j] ;
			for (i_bits=0; i_bits<8; i_bits++)
			{
					carry = crc & 1;
					crc=crc/2;
					if (carry)
					{
						crc = crc^poly;
					}
			}
	}
	return crc;
}

おすすめ

転載: blog.csdn.net/m0_58644391/article/details/121777248