历史上的今天
今天是:2025年08月16日(星期六)
2019年08月16日 | HAL库之485+DMA通信(STM32F746)
2019-08-16 来源:eefocus
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);
}
上一篇:15-HAL库之定时器学习
下一篇:16.HAL库之SPI和QSPI
史海拾趣
|
就32分了! 请问大侠当时用9650采集图像时采集到的数据格式是什么(rgb,ycbcr?),当时大侠把它转化成图片了吗?是什么格式的?bmp,jpeg? 是怎么做的?谢谢了!… 查看全部问答> |
|
最近弄了个GPS,是2440/wince5.0做的,2.8寸的屏,开始的时候只能用别人已经写好了的程序,不能进入wince界面。实在想进wince看看就写了个小程序,哎呀,终于可以进wince界面了,可以看看图片,爽啊!! … 查看全部问答> |
|
PPC的440EP内部有个递减时钟计数器decrementor,它的计数初值决定了操作系统每个tick的周期。一般情况下它的计数初值都是提前预置好不会改变。比如linux里param.h中的HZ宏定义。 我想知道可不可以动态修改这个计数初值啊?比如来了外部中断后,在I ...… 查看全部问答> |
|
一個32位的單片機器,是不是說 int32_t c, b, a; c = a + b 和unsigned char c, b, a; c = b + a; 一樣快? 是不是在程序中應該儘量使用32 bit 整數類型。… 查看全部问答> |




