求助arduino串口发送数据DMA发送,只能发送一次

查看: 5644|回复: 5
F4 串口DMA接收,只进入一次DMA中断!
主题帖子精华
新手入门, 积分 46, 距离下一级还需 -26 积分
在线时间0 小时
我的问题,我想使用F4的DMA进行串口的DMA接收,配置过程:GPIO配置、UART配置、DMA优先级配置、DMA参数配置,就是这几个函数。
测试中,我用电脑串口发送数据给F4,并使用LED的翻转来表示进入中断。可问题出现了,只有我发送成功第一次的数据(设定的是6个字节)的时候,LED翻转,说明进入了DMA发送完成中断,但是以后不会再进入。更奇怪的是,我把存放DMA接收数据打印出来的 时候,发现里面的数据是实时更新的,也就是说DMA依然在正常工作,想不明白,那为什么不进入中断了呢?
请高手帮忙看看,谢谢!
谁有更好的串口DMA例程,能拿出来交流交流吗?
[C] 纯文本查看 复制代码/**************************实现函数********************************************
*函数原型:
void COM_Init(u32 baudrate)
*功  能:
初始化串口1
输入参数:
u32 baudrate 串口的波特率
输出参数:没有
*******************************************************************************/
void COM_Init(u32 baudrate)
USART_InitTypeDef USART_InitS //定义USART初始化结构体
COM_GPIO_Config();
//配置UART1的相关引脚
RCC_APB1PeriphClockCmd(COM_RCC_USART_CLK,ENABLE);//使能USART1外设时钟
/* Enable the USART OverSampling by 8 */
USART_OverSampling8Cmd(COM_USART, ENABLE);
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
USART_InitStructure.USART_BaudRate =
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_N
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_Init(COM_USART , &USART_InitStructure);
COM_DMA_NVIC_Config();
//配置串口DMA中断的优先级
COM_DAM_Config();
//配置串口DMA
USART_ClearFlag(COM_USART,USART_FLAG_TC);
//清除标志位,防止第一个数据发送失败
USART_Cmd(COM_USART,ENABLE);
//使能串口
void COM_GPIO_Config(void)
GPIO_InitTypeDef GPIO_InitS
//定义GPIO初始化结构体
RCC_AHB1PeriphClockCmd(COM_TX_GPIO_CLK|COM_RX_GPIO_CLK,ENABLE); //使能USART1对应的引脚端口TX RX
/* Configure USART Tx as alternate function
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//使用复用功能
GPIO_InitStructure.GPIO_Pin = COM_TX_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率 50M
GPIO_Init(COM_TX_GPIO_PORT, &GPIO_InitStructure);
//TX PIN 初始化
/* Configure USART Rx as alternate function
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//使用复用功能
GPIO_InitStructure.GPIO_Pin = COM_RX_PIN ;
GPIO_Init(COM_RX_GPIO_PORT, &GPIO_InitStructure);
//RX PIN初始化
/* Connect PXx to USARTx_Tx*/
GPIO_PinAFConfig(COM_TX_GPIO_PORT , COM_TX_GPIO_PinSource , COM_GPIO_AF);
/* Connect PXx to USARTx_Rx*/
GPIO_PinAFConfig(COM_RX_GPIO_PORT , COM_RX_GPIO_PinSource , COM_GPIO_AF);
/**********************************************************************************************
*函数名:void COM_DMA_NVIC_Config(void)
* 返回值:
* 功能:配置串口DMA的中断优先级
**********************************************************************************************/
void COM_DMA_NVIC_Config(void)
NVIC_InitTypeDef NVIC_InitS
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/**********************************************************************************************
*函数名:void COM_DAM_Config(void)
* 返回值:
* 功能: 配置串口的DMA
**********************************************************************************************/
void COM_DAM_Config(void)
DMA_InitTypeDef
/* Enable the DMA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
/* Configure DMA controller to manage USART TX and RX DMA request ----------*/
DMA_DeInit(DMA1_Stream5);
/* Configure DMA Initialization Structure */
DMA_InitStructure.DMA_BufferSize = 6 ;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_D
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterF
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_S
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
DMA_InitStructure.DMA_Mode = DMA_Mode_C
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(COM_USART-&DR)) ;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_S
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
DMA_InitStructure.DMA_Priority = DMA_Priority_H
DMA_InitStructure.DMA_Channel = DMA_Channel_4 ;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToM
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)COM_Rx_B
DMA_Init(DMA1_Stream5,&DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);
//开启DMA数据发送完成中断
DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
/* Enable USART RX DMA */
USART_DMACmd(COM_USART, USART_DMAReq_Rx, ENABLE);
//开启USART接收DMA请求
DMA_Cmd(DMA1_Stream5,ENABLE);
//以下是中断处理函数:
handles DMA Stream interrupt request.
* @retval None
void DMA1_Stream5_IRQHandler(void)
if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5))
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
STM_EVAL_LEDOn(LED2);
回复【2楼】正点原子:
---------------------------------
小弟出丑了,原来每次进入中断执行的都是STM_EVAL_LEDOn(LED2);led灯点亮函数,我以为是IO口翻转函数,怪不得没有现象!这一个小小的错误浪费了我一下午加一晚上的时间!,真不该!
谢谢原子哥!
主题帖子精华
新手入门, 积分 46, 距离下一级还需 -26 积分
在线时间0 小时
回复【2楼】正点原子:
---------------------------------
小弟出丑了,原来每次进入中断执行的都是STM_EVAL_LEDOn(LED2);led灯点亮函数,我以为是IO口翻转函数,怪不得没有现象!这一个小小的错误浪费了我一下午加一晚上的时间!,真不该!
谢谢原子哥!
主题帖子精华
金钱121736
在线时间983 小时
估计是你DMA重启的问题。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子& &
主题帖子精华
金钱121736
在线时间983 小时
回复【3楼】紫宸:
---------------------------------
额,谢谢分享。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子& &
主题帖子精华
中级会员, 积分 224, 距离下一级还需 276 积分
在线时间2 小时
这个是DMA发送吧&并不是接收
主题帖子精华
初级会员, 积分 53, 距离下一级还需 147 积分
在线时间13 小时
我也出现了这个问题,而且是真的只进了一次中断,我已经清标志,请DR寄存器,还有可能是什么原因呢?求教!
Powered by查看: 743|回复: 14
stm32 串口有校验位不能用DMA发送,有方法解决吗
用DMA发送带校验位的串口数据会成知乱码。是不是因为DMA只能发8位数据位的原因呢,请问有什么方法可以解决。
校验是串口外设的事情,dma当然只处理待发送值,dma外设相当于代替mcu将数据放入uart-&dr这个寄存器的过程
发多少位是串口的问题,与DMA没有关系的,我就用DMA发送9位也没有问题,你还是检查其它问题!
发多少位是串口的问题,与DMA没有关系的,我就用DMA发送9位也没有问题,你还是检查其它问题! ...
好的,谢谢。我再检查一下
校验是串口外设的事情,dma当然只处理待发送值,dma外设相当于代替mcu将数据放入uart-&dr这个寄存器的过程 ...
是呀,没想到呢。好的,我再检查一下看是什么问题。谢谢
但是由PC发送到stm32就没有问题,stm32发送到PC用串口助手接收就变了,原本发的是 01 02 03 04 05&&接收到的却是80 80 c0 E0
&&DMA_InitStructure.DMA_Channel =&&//?¨u?????
&&DMA_InitStructure.DMA_PeripheralBaseAddr =//DMA???èu??·
&&DMA_InitStructure.DMA_Memory0BaseAddr =//DMA ?ae??AE÷0u??·
&&DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToP//?ae??AE÷u 1/2 ???è??? 1/2
&&DMA_InitStructure.DMA_BufferSize =//?? 3/4 ??<<????
&&DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D//???è·???????? 1/2
&&DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E//?ae??AE÷??????? 1/2
&&DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B//???è?? 3/4 ??¤??:8?>>
&&DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B//?ae??AE÷?? 3/4 ??¤??:8?>>
&&DMA_InitStructure.DMA_Mode = DMA_Mode_N// ????AE??¨??? 1/2
&&DMA_InitStructure.DMA_Priority = DMA_Priority_M//??u????? 1/4 ?
&&DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_D& && && &
&&DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_F
&&DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_S//?ae??AE÷?>>·?u????<<??
&&DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_S//???è?>>·?u????<<??
&&DMA_Init(DMA_Streamx, &DMA_InitStructure);//??? 1/4 >>?DMA Stream
DMA_InitStructure.DMA_Channel =&&//?¨u?????
&&DMA_InitStructure.DMA_PeripheralBaseAdd ...
我的暂时好像也是这样,晚上回家再试试
我的暂时好像也是这样,晚上回家再试试
我还在搞,发现不了错呀。
我还在搞,发现不了错呀。
晚上我在看看,大家一起研究吧
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B//???è?? 3/4 ??¤??:8?>>
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B//?ae??AE÷?? 3/4 ??¤??:8?>>
DMA_MemoryDataSize_Byte要改成DMA_PeripheralDataSize_HalfWord
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B//???è?? 3/4 ??¤??:8 ...
试过了,没有用。而且最扯的是, 同样的配置,用usart3就能完全正常,就usart1不正常。我这板子有两个串口的。配成一样,usart1还是发乱码,但是接收却是正常的。
晚上我在看看,大家一起研究吧
你Q多少一起研究一下
你Q多少一起研究一下
我的已经好了,
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
就好了,不知道你是不是这个原因
我的已经好了,
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
我的也是这个原因,哈哈,谢谢了。
阿莫电子论坛, 原"中国电子开发网"
, 原www.ourdev.cn, 原www.ouravr.com串口DMA发送搞定
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32
cmar,u16 cndtr)
&u32 DR_B&
//做缓冲用,不知道为什么.非要不可
&RCC-&AHBENR|=1&&0;//开启DMA1时钟
&DMA_CHx-&CPAR=DR_B
& //DMA1 外设地址
&DMA_CHx-&CMAR=(u32)
//DMA1,存储器地址
&DMA1_MEM_LEN=&&&&&
//保存DMA传输数据量
&DMA_CHx-&CNDTR=&&&
//DMA1,传输数据量
&DMA_CHx-&CCR=0X;//复位
&DMA_CHx-&CCR|=1&&4;&
//从存储器读
&DMA_CHx-&CCR|=0&&5;&
//普通模式
&DMA_CHx-&CCR|=0&&6;&
//外设地址非增量模式
&DMA_CHx-&CCR|=1&&7;&
//存储器增量模式
&DMA_CHx-&CCR|=0&&8;&
//外设数据宽度为8位
&DMA_CHx-&CCR|=0&&10;
//存储器数据宽度8位
&DMA_CHx-&CCR|=1&&12;
//中等优先级
&DMA_CHx-&CCR|=0&&14;
//非存储器到存储器模式&&&
这个函数.设置DMA寄存器.要重复定义几次只定义一次不行,很诡异..
另外,重写了数组移动.
&for(i=0;i&5200;i++)//填充ASCII字符集数据
&&if(t&=j)//加入换行符
&&&SendBuff[i]=0x0d;
&&&i=5200;&
&&}else//复制TEXT_TO_SEND语句
&&&SendBuff[i]=TEXT_TO_SEND[t];
Load "C:\\Users\\Administrator\\Desktop\\DMA串口实验 可发送串口实验"
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。查看: 2013|回复: 12
串口DMA普通模式接收只能进一次中断问题
主题帖子精华
新手入门, 积分 41, 距离下一级还需 -21 积分
在线时间0 小时
由于需要把接收到的数据进行处理 所以dma使用了normal模式,但是问题是只能进一次dma完成中断,之后就不会进了。不管怎么改都不行。不知道是什么原因,请各位大神帮忙看看,提供下思路。谢谢!
void DMA1_Channel6_IRQHandler(void)
uint16_t i,j;
& &if(DMA_GetFlagStatus(DMA1_FLAG_TC6)==SET)&
for(i=0;i&(READBUFF_SIZE-11);i++)
if(ReadBuffer==0x55&&ReadBuffer[i+1]==0x53)
for(j=0;j&10;j++)
sum=ReadBuffer[i+j];
printf("%X ",ReadBuffer[i+j]);
printf("%X ",ReadBuffer[i+j+1]);
printf("%d\n",sum);
if(ReadBuffer[i+10]==sum)
Roll=((ReadBuffer[i+3]&&8)|ReadBuffer[i+2])/;
Pitch=((ReadBuffer[i+5]&&8)|ReadBuffer[i+4])/;
Yaw=((ReadBuffer[i+7]&&8)|ReadBuffer[i+6])/;
printf("Roll=%4.3f,Pitch=%4.3f,Yaw=%4.3f\n",Roll,Pitch,Yaw);
DMA_Cmd(DMA1_Channel6,DISABLE);
DMA1_Channel6-&CMAR=(u32)ReadB
DMA1_Channel6-&CNDTR=READBUFF_SIZE;
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
DMA_Cmd(DMA1_Channel6,ENABLE);
DMA_ClearFlag(DMA1_FLAG_GL6);
主题帖子精华
在线时间137 小时
normal模式需要重启DMA
DMA_Cmd(DMA1_Channel6,DISABLE);
重新设置源地址
重新设置目的地址
重设传输数量
DMA_Cmd(DMA1_Channel6,ENABLE);
另外DMA_ClearFlag(DMA1_FLAG_GL6);这句应该在DMA启动前完成。
主题帖子精华
新手入门, 积分 41, 距离下一级还需 -21 积分
在线时间0 小时
回复【2楼】ricefat:
---------------------------------
谢谢你的回复,我把清标志位放到DMA启动前也不行,还有别的原因吗?
主题帖子精华
新手入门, 积分 45, 距离下一级还需 -25 积分
在线时间2 小时
回复【3楼】似懂非懂:
---------------------------------
你有没有确定你进去中断后,你的DMA有没有再次跑起来了呢?
主题帖子精华
新手入门, 积分 41, 距离下一级还需 -21 积分
在线时间0 小时
回复【4楼】:
---------------------------------
谢谢你的回复!我可以确定进中断之后出了中断就没有再进去过,DMA有没有跑起来不清楚怎么看。
主题帖子精华
在线时间137 小时
屏蔽掉printf语句试试看,换成LED亮灭
主题帖子精华
新手入门, 积分 41, 距离下一级还需 -21 积分
在线时间0 小时
回复【6楼】ricefat:
---------------------------------
太感谢了,去掉printf语句就可以了!请问下这是什么原因呢?是因为printf占有时间太长导致dma传输完成了还没有出中断吗?用循环模式好像不会有这个问题。
主题帖子精华
在线时间137 小时
回复【7楼】似懂非懂:
---------------------------------
好像DMA1_Channel6是USART2的?printf定向到usart1还是2?
主题帖子精华
新手入门, 积分 41, 距离下一级还需 -21 积分
在线时间0 小时
回复【8楼】ricefat:
---------------------------------
DMA1_Channel6这个是uasrt2的,printf是定向到usart1的。我刚才想是因为printf占用时间太长了导致出中断前第二次中断丢失了,但是又想了想即便是这样也没有问题。因为后来又重新开启了dma并清除了中断标志位。奇怪的是用循环模式能正常进中断并用printf输出。具体原因还望指教。谢谢!
主题帖子精华
在线时间137 小时
回复【9楼】似懂非懂:
---------------------------------
试试看单步调试吧
主题帖子精华
新手入门, 积分 41, 距离下一级还需 -21 积分
在线时间0 小时
回复【10楼】ricefat:
---------------------------------
还有一个奇怪的问题,现在DMA是正常的,但是我在中断里设个断点中断之后再全速运行就不能再次进入中断了,我想这应该是DMA的某种机制导致,但是不清楚这是什么机制。
主题帖子精华
在线时间137 小时
回复【11楼】似懂非懂:
---------------------------------
DMA传输过程不受调试影像,一旦启动DMA,即使是调试,DMA传输过程也不会中断
主题帖子精华
新手入门, 积分 41, 距离下一级还需 -21 积分
在线时间0 小时
回复【12楼】ricefat:
---------------------------------
现在的情况是开了dma之后调试,在中断中设置断点后重新启动就不能重新进入中断,不知道什么情况。
Powered by匿名用户不能发表回复!|}

我要回帖

更多关于 串口发送字符串 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信