完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6。在调试的过程中发现,一直出现数据错位的问题,接收端尝试了串口空闲中断和串口DMA传输完成中断,错位问题依旧,其实我之前遇到过这个问题,那次发送端没有使用DMA,而是直接用串口发送,接收端采用DMA接收完成中断,检测到错位后,延时重置DMA,直到DMA接收同步后,不再重置,此后DMA便会保持同步,不会错位。但是这次不知道为什么采用上次的方法没有解决,因此决定直接用最简单粗暴的方法——查找,但是弊端是会在中断中运行一段比较占空时间的代码。
说明:主要部分在接收中断(本文最后的代码段),发送端发送的DMA数据长度为a,接收端DMA配置的BufferSize为2a,这样即使错位,在2a的数据长度中也一定会存在一段完整的有效数据。接收中断中,在接收buffer的前半段查找帧头,找到之后,判断帧头+a-1的位置是否是帧尾,如果是,则基本可以认为中间即为有效数据,将该段数据拷贝到一个新的数组中,等待解析。 配置部分:发送端 STM32F103C8T6 /* uart3 for communicate with the master */ void vUart3Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* USART3_RX GPIOB.11 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure); /* USART3_TX GPIOB.10 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, &USART_InitStructure); USART_Cmd(USART3, ENABLE); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); { /* send dma */ USART_DMACmd(USART3,USART_DMAReq_Tx,ENABLE); DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(USART3->DR)); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendToMaster_Buff; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = USART3_DMA_send_buffersize; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel2,&DMA_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE); DMA_Cmd(DMA1_Channel2,ENABLE); } } 配置部分:接收端 STM32F407VET6 void vUTConfig(void) { USART_InitTypeDef usart; GPIO_InitTypeDef gpio; NVIC_InitTypeDef nvic; DMA_InitTypeDef dma; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); GPIO_PinAFConfig(GPIOA,GPIO_PinSource9 ,GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); /* USART1_RX GPIOA.10 */ gpio.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; gpio.GPIO_Mode = GPIO_Mode_AF; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_Speed = GPIO_Speed_100MHz; gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA,&gpio); usart.USART_BaudRate = 115200; usart.USART_WordLength = USART_WordLength_8b; usart.USART_StopBits = USART_StopBits_1; usart.USART_Parity = USART_Parity_No; usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1,&usart); USART_Cmd(USART1,ENABLE); { /* receive dma */ USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); DMA_DeInit(DMA2_Stream2); dma.DMA_Channel= DMA_Channel_4; dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR); dma.DMA_Memory0BaseAddr = (uint32_t)ReceiveFromUT_Buffer; dma.DMA_DIR = DMA_DIR_PeripheralToMemory; dma.DMA_BufferSize = USART1_UT_DMA_receive_buffersize; dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dma.DMA_MemoryInc = DMA_MemoryInc_Enable; dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; dma.DMA_Mode = DMA_Mode_Circular; dma.DMA_Priority = DMA_Priority_VeryHigh; dma.DMA_FIFOMode = DMA_FIFOMode_Disable; dma.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; dma.DMA_MemoryBurst = DMA_MemoryBurst_Single; dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream2,&dma); nvic.NVIC_IRQChannel = DMA2_Stream2_IRQn; nvic.NVIC_IRQChannelPreemptionPriority = 1; nvic.NVIC_IRQChannelSubPriority = 1; nvic.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic); DMA_ITConfig(DMA2_Stream2,DMA_IT_TC,ENABLE); DMA_Cmd(DMA2_Stream2,ENABLE); } } 中断部分:发送中断 /* USART3 DMA send interrupt */ void DMA1_Channel2_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC2)) { DMA_ClearFlag(DMA1_IT_TC2); DMA_ClearITPendingBit(DMA1_IT_TC2); // DMA_Cmd(DMA1_Channel2,DISABLE); // DMA_SetCurrDataCounter(DMA1_Channel2,USART3_DMA_send_buffersize); // DMA_Cmd(DMA1_Channel2, ENABLE); } } 中断部分:接收中断 /* USART1 dma receive for ut */ void DMA2_Stream2_IRQHandler(void) { uint8_t i = 0; if(DMA_GetFlagStatus(DMA2_Stream2,DMA_IT_TCIF2) == SET) { /* 在前半部分查找帧头并校验对应位置是否为帧尾 */ for(i=0;i<(USART1_UT_DMA_receive_buffersize/2);i++) { if((ReceiveFromUT_Buffer == 0x05)&&(ReceiveFromUT_Buffer[i+USART1_UT_DMA_receive_buffersize-1] == 0x06)) { /* 拷贝有效数据段到待解析数组 */ memcpy(ReceiveFromUT_Data,&ReceiveFromUT_Buffer,USART1_UT_DMA_receive_buffersize/2); /* 数据解析 */ UTReceive(); } } /* 没有有效数据 */ if(i >= USART1_UT_DMA_receive_buffersize/2) { /* 重置DMA */ DMA_Cmd(DMA2_Stream2,DISABLE); DMA_SetCurrDataCounter(DMA2_Stream2,USART1_UT_DMA_receive_buffersize); DMA_Cmd(DMA2_Stream2,ENABLE); } DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2); DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2); } } |
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
4138 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
3228 浏览 1 评论
2752 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
2181 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
14980 浏览 2 评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
3086浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
1896浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
2066浏览 3评论
1979浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
2168浏览 3评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 10:30 , Processed in 0.558501 second(s), Total 74, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1494