HAL库之485+DMA通信(STM32F746)

2019-08-16来源: eefocus关键字:HAL库  485  DMA通信  STM32F746

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);

}


关键字:HAL库  485  DMA通信  STM32F746

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic471329.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:15-HAL库之定时器学习
下一篇:16.HAL库之SPI和QSPI

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

使用stm32的HAL库完成pwm输入模式测量频率和占空比的详细教程

。 然后使能TIM2的中断接下来添加代码:main.c 中开启捕获中断    /* USER CODE BEGIN 2 */    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);//如果不需要占空比和频率数据就只开通道2即可。第一次的数据是不正确的,实际工作中要将第一次的数据丢弃    /* USER CODE END 2 */      
发表于 2019-08-21
使用stm32的HAL库完成pwm输入模式测量频率和占空比的详细教程

16.HAL库之SPI和QSPI

沿进行数据变化。DDR模式:在该模式下,指令阶段在SCLK下降沿发送数据,而在地址,交替字节,数据阶段在SCLK上升沿和下降沿均发送数据。双闪存模式:使用两个外部SPI四线,可将flash扩大一倍。QSPI配置:时钟使能,管脚定义,QSPI配置,flash初始化,QSPI读/写函数定义。void Qspi_Config(){ __HAL_RCC_QSPI_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); Flash_GPIO.Pin=GPIO_PIN_2; Flash_GPIO.Mode=GPIO_MODE_AF_PP
发表于 2019-08-16
16.HAL库之SPI和QSPI

15-HAL库之定时器学习

RepetitionCounter;   //重复计数,高级控制定时器所用   uint32_t AutoReloadPreload;   //自动预装载值}TIM_Base_InitTypeDef;应用例子如下:#include "basic_tim.h"TIM_HandleTypeDef Basic_Tim6;void Basic_Tim_Config(void){ HAL_TIM_Base_MspInit(&Basic_Tim6); __HAL_RCC_TIM6_CLK_ENABLE(); Basic_Tim6.Instance=TIM6
发表于 2019-08-16
15-HAL库之定时器学习

14-HAL库之I2C通信

发送停止传输信号P。读数据时,主机向从机发应答信号,当主机希望停止接收数据时,发送非应答信号。起始信号和停止信号见上图。数据有效性见上图。2.基于HAL库的I2C配置步骤:时钟使能—GPIO管脚配置—I2C配置初始化:void MyI2C_Init(void){ __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_6;  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  GPIO_InitStruct.Pull
发表于 2019-08-16
14-HAL库之I2C通信

13-HAL库DMA系统总结

。2.DMA相关函数解析关于DMA,ST官方提供了HAL库(封装函数)和LL库(直接操作寄存器)。和GPIO定义类似,需要先使能相关时钟,定义句柄结构体DMA_HandleTypeDef mydma2,随后进行DMA的各项配置,最后进行初始化。typedef struct __DMA_HandleTypeDef{    DMA_Stream_TypeDef          *Instance;                       
发表于 2019-08-16
13-HAL库DMA系统总结

stm32下面控制RS485发送有一定概率出错的情况

环境:stm32 72M时钟 串口波特率9600 RS485芯片 发送的数据每组16byte 原程序(未修改)://RS485 发送len个字节//buf:发送区首地址//len:发送的字节数void RS485SendData(u8 *buf,u8 len){    u8 t;    RS485_TX_EN=1;          //设置为发送模式    for(t=0;t<len;t++)      //循环发送数据    {   
发表于 2019-07-27

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved