STM32 hal 라이브러리는 직렬 포트 + DMA 수신 데이터를 해결합니다.

STM32F407 직렬 포트 유휴 인터럽트 + DMA 수신, DJI DT7 무선 원격 제어에 적용

# stm32CubeIDE STM32F4 HAL 라이브러리 DJI DT7 직렬 포트 + DMA ()

1. 하드웨어 설계
먼저 반전 회로를 만들 필요가 여기에 그림 설명을 삽입하십시오.
그림과 같이 DJI 수신기가 전송하는 직렬 포트 데이터의 신호 유형을 이해하고 아래 그림과 같이 반전 회로를 만들어야합니다.
여기에 사진 설명 삽입

사진은 인터넷에서 가져온 것입니다. 인터넷에서 찾을 수 있습니다. 풀업 저항이 있어야합니다. 외부가없는 경우 MCU USART의 RX의 GPIO를 사용
하여 후 전송 되도록 구성 할 수 있습니다. -up 리모콘 외부 직렬 포트의 TX 동의어로서 수신된다. 연결은 마이크로 컨트롤러의 RX와.

다음은 소프트웨어 부분입니다. 저는 STM32CubeIDE를 사용합니다. 먼저 환경을
구성 합니다 . 1. RCC 시계를 구성합니다. 이에 대해 더 이상 말하지 않겠습니다. 할 수없는 경우 코멘트 영역에 표시됩니다.
2. 여기에 사진 설명 삽입
직렬 포트 데이터를 구성합니다. GPIO 모드 구성
여기에 사진 설명 삽입을 수신하도록 직렬 포트 DMA를
여기에 사진 설명 삽입
구성하고
마지막으로 인터럽트를 수신하도록 직렬 포트를 활성화합니다.
여기에 사진 설명 삽입
인터럽트가 아닌 타이머에서 데이터를 처리하기 위해 10ms 타이머 인터럽트를 사용했습니다. 인터럽트는 데이터 수신에만 사용됩니다. 타이머 구성에 대해서는별로 말하지 않겠습니다.

여기에 사진 설명 삽입
사진 추가,
아래 코드

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); //使能串口空闲中断
  HAL_UART_Receive_DMA(&huart1, receive_buff,18);//开启串口DMA接收
  HAL_TIM_Base_Start_IT(&htim2);//开启1定时器中断
  /* USER CODE END 2 */

uint8_t receive_buff [18]; 정의 된 수신 배열입니다
receive_buff는 수신 배열, 수신 된 데이터는 여기에 배치되며 18은 한 번에 18 바이트 수신을 나타냅니다.
다음으로 stm32f4xx_it.c 파일을 찾습니다 .

 * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);  //这个可有可无
  /* USER CODE BEGIN USART1_IRQn 1 */
  if(USART1==huart1.Instance)  //判断是否为串口1的中断
  {
  if( __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)!=RESET )                /判断是否为空闲中断
  			   {
  				__HAL_UART_CLEAR_IDLEFLAG(&huart1);        //  如果是空闲中断清除空闲中断标志
  				HAL_UART_DMAStop(&huart1);                 // 关闭串口的DMA接收
  				DMA2_Stream2->NDTR=(uint16_t)(RC_FRAME_LENGTH);  //  这个参考的大疆DT7历程,重置DMA存储指针到起始位置
  				HAL_UART_Receive_DMA(&huart1, (uint8_t*) receive_buff, 18); //再开启接收
  				HAL_Delay(25);    //为什么加延时呢,见后面
              if(__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)==0&&receive_buff[17]==4)  // 见后面
                {
                memcpy(data_Handle, receive_buff, 18);      //复制到其他数组方便处理
      
                }
  			   }
  }
  /* USER CODE END USART1_IRQn 1 */
}
/**

__HAL_DMA_GET_COUNTER (& hdma_usart1_rx) 문장은 현재 DMA 스트림 전송에 남아있는 데이터 단위의 수를 의미합니다. 즉, 수신이 켜진 후 데이터를 처리하기 전에 수신이 완료 될 때까지 기다려야합니다. , __HAL_DMA_GET_COUNTER (& hdma_usart1_rx) 이것은 0과 같습니다. 이는 18 바이트가 모두 수신되었음을 의미합니다.
HAL 라이브러리에서이 매크로 정의를 볼 수 있습니다 . #define __HAL_DMA_GET_COUNTER ( HANDLE ) (( HANDLE )-> Instance-> NDTR) 및 그런 다음
ST 문서 NDTR 레지스터의 의미 살펴보면
여기에 사진 설명 삽입
HAL_UART_Receive_DMA (& huart1, (uint8_t *) receive_buff, 18); 수신이 켜진 후 수신이 완료 될 때까지 20m를 기다려야합니다. 그렇지 않으면 디버깅 중 중단 점을 설정하면 입력되지 않습니다. 아직 남아 있기 때문에 0이되지 않습니다.
정보 && receive_buff [17] == 4, 내 데이터 수신 특성이어야합니다. root. 데이터의 정확성을 높이기 위해 판단 조건을 추가했습니다.
직설적으로 말하면이 문장은 수신 된 데이터의 길이 확인과 데이터에있는 데이터의 또 다른 A 특성으로 데이터의 정확성을 보장 할 수 있습니다. 데이터가 혼란
스럽 습니다. 다음 경우 필터링 됩니다. (__HAL_DMA_GET_COUNTER (& hdma_usart1_rx) == 0 && receive_buff [17] == 4)
좋아요, 그게 전부입니다. 네티즌의 비판과 비판을 환영합니다. 이것, 서로 배우고, 응원하십시오!

추천

출처blog.csdn.net/m0_49933527/article/details/114187881