HAL庫之485+DMA通信(STM32F746)

很讓人無語,一個簡單的485卡了很久。雖然簡單,但通過調485通信可以總結很多調試經驗:

1.首先一定要保證硬件正確,包括接線,工具正常;

2.其次基本配置一定要正確,例如此次配置485的時候,可以實現DMA發送,卻不能實現接收。而同樣的串口參數配置使用中斷方式和232接口都能實現發送接收,個人判斷是是接收DMA部分配置有問題,結果卡了很久才發現是基本的管腳配置有誤。485的三根引腳要配置成推輓輸出,複用,複用模式。

3.最後,還是要多總結經驗,多看看源代碼。

硬件如下:

 

 

其實本質上還是串口通信,只不過多了一個開關控制(485-DIR),用來控制是發送數據還是接收數據,因此是半雙工模式。

配置流程:時鐘使能,引腳配置,串口配置(波特率,校驗位等),DMA配置(需要配置串口中斷)

void USART2_UART_Init(uint32_t bound)
{
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_USART2_CLK_ENABLE();
	
  GPIO_InitTypeDef GPIO_Init2;
	
  GPIO_Init2.Pin = GPIO_PIN_4;           	  //485_RTS
  GPIO_Init2.Mode =GPIO_MODE_OUTPUT_PP;
  GPIO_Init2.Pull = GPIO_NOPULL;
  GPIO_Init2.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_Init2.Alternate = GPIO_AF7_USART2;
  HAL_GPIO_Init(GPIOD,&GPIO_Init2);

  GPIO_Init2.Pin = GPIO_PIN_5;         	    //485 TX config
  GPIO_Init2.Mode = GPIO_MODE_AF_PP;
  GPIO_Init2.Pull = GPIO_NOPULL;
  GPIO_Init2.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_Init2.Alternate = GPIO_AF7_USART2;
  HAL_GPIO_Init(GPIOD,&GPIO_Init2);

  GPIO_Init2.Pin = GPIO_PIN_6;            	//485 RX config
  GPIO_Init2.Mode = GPIO_MODE_AF_PP;
  GPIO_Init2.Pull = GPIO_NOPULL;
  GPIO_Init2.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_Init2.Alternate = GPIO_AF7_USART2;
  HAL_GPIO_Init(GPIOD,&GPIO_Init2);        //USART2_GPIO配置
	
  __HAL_RCC_DMA1_CLK_ENABLE();	
  huart2_dma_rx.Instance=DMA1_Stream5;  //USART2RX_ DMA1數據流5,通道4
  huart2_dma_rx.Init.Channel=DMA_CHANNEL_4;
  huart2_dma_rx.Init.Direction=DMA_PERIPH_TO_MEMORY;
  huart2_dma_rx.Init.PeriphInc=DMA_PINC_DISABLE;
  huart2_dma_rx.Init.MemInc=DMA_MINC_ENABLE;
  huart2_dma_rx.Init.MemDataAlignment= DMA_MDATAALIGN_BYTE;
  huart2_dma_rx.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;
  huart2_dma_rx.Init.Mode=DMA_NORMAL;
  huart2_dma_rx.Init.Priority=DMA_PRIORITY_LOW;
  huart2_dma_rx.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
  HAL_DMA_Init(&huart2_dma_rx);
	
       huart2_dma_tx.Instance=DMA1_Stream6;    	        //USART2TX_ DMA1數據流6,通道4
	huart2_dma_tx.Init.Channel=DMA_CHANNEL_4;
	huart2_dma_tx.Init.Direction=DMA_MEMORY_TO_PERIPH;
	huart2_dma_tx.Init.PeriphInc=DMA_PINC_DISABLE;
	huart2_dma_tx.Init.MemInc=DMA_MINC_ENABLE;
	huart2_dma_tx.Init.MemDataAlignment= DMA_MDATAALIGN_BYTE;
	huart2_dma_tx.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;
	huart2_dma_tx.Init.Mode=DMA_NORMAL;
	huart2_dma_tx.Init.Priority=DMA_PRIORITY_HIGH;
	huart2_dma_tx.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
	HAL_DMA_Init(&huart2_dma_tx);
	
   __HAL_LINKDMA(&huart2,hdmarx,huart2_dma_rx); //關聯USART2和DMA	
   __HAL_LINKDMA(&huart2,hdmatx,huart2_dma_tx);  
		
  HAL_NVIC_SetPriority(DMA1_Stream5_IRQn,1,1);  //配置DMA通道的中斷並使能
  HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
	
  HAL_NVIC_SetPriority(DMA1_Stream6_IRQn,1,1);  	
  HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);

  huart2.Instance =USART2; 
  huart2.Init.BaudRate =bound;
  huart2.Init.WordLength =UART_WORDLENGTH_8B;
  huart2.Init.StopBits =UART_STOPBITS_1;
  huart2.Init.Parity =UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl=UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; 
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  HAL_UART_Init(&huart2);    //串口2配置
	
  HAL_NVIC_SetPriority(USART2_IRQn,1,1);            //配置USART2的中斷並使能
  HAL_NVIC_EnableIRQ(USART2_IRQn);	              
	
	RS485_R;
}


void delay485(uint32_t num)
{
	while(num--);
}

void RS485_Send_data(uint8_t *pdata,uint16_t data_size)
{
	RS485_T;
	delay485(4);
	while(HAL_UART_GetState(&huart2)!=HAL_UART_STATE_READY);
	HAL_UART_Transmit_DMA(&huart2,pdata,data_size);
	while(HAL_UART_GetState(&huart2)!=HAL_UART_STATE_READY);
	RS485_R;
	delay485(4);
}

void RS485_Receive_data(uint8_t *pdata,uint16_t data_size)
{
	while(HAL_UART_GetState(&huart2)!=HAL_UART_STATE_READY);
	HAL_UART_Receive_DMA(&huart2,pdata,data_size);
}

主程序測試:

int main(void)    
{
  HAL_Init();
  Sysclk_config();
	USART2_UART_Init(38400);
	RS485_Send_data(buffer1,data_length);
	HAL_UART_Receive_DMA(&huart2,buffer2,data_length); //打開DMA接收
  while(1)
  { 
	   if(flag==1)
	  {
		 HAL_Delay(200);
	   RS485_Send_data(buffer2,data_length);
		 flag=0;
		 HAL_UART_Receive_DMA(&huart2,buffer2,data_length);//打開DMA接收 
	  }
 }
}


void USART2_IRQHandler(void)
{
	HAL_UART_IRQHandler(&huart2);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart==&huart2)
	{
	  flag=1;
	}
}

void DMA1_Stream6_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&huart2_dma_tx);
}


void DMA1_Stream5_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&huart2_dma_rx);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章