完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
//STM32串口DMA通讯接收不到数据 //请各位大神帮忙看看,下面的DMA配置问题出在哪里 //程序编写思路是:用串口助手发数据给STM32的串口2,收到数据后返回收到的数据给串口助手; //现在遇到的问题:用串口助手发数据给它,但不能返回数据,LED0和LED1会常亮; //小弟初学,这个问题弄了一个星期还没有解决,望大家高抬贵手帮帮我; //谢谢 u8 rcv_num_temp=0; //接收到的数据长度临时缓存 u8 rcv_num=0; //接收到的数据长度缓存 u8 rcv_bufferfer_temp[128]; //接收数据临时缓存,最大64个字节 u8 rcv_buffer[128]; //接收缓存,最大64个字节 u8 rcv_complete_temp=0; //一帧接收完成临时缓存(1为完成) u8 rcv_complete=0; //接收完成标志 1为完成 u8 send_complete=0; //发送完成标志 1为完成 //USART2参数配置函数 void USART2_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART2_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); //使能GPIOD时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //使能USART2时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA1时钟 USART_DeInit(USART2); //发送接收控制模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PD7 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(GPIOD, GPIO_InitStructure); //USART2-TX GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //PA2 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽 GPIO_Init(GPIOA, GPIO_InitStructure); //USART2-RX GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3; //PA3 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, GPIO_InitStructure); RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2 RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位 //USART2通讯协议 USART2_InitStructure.USART_BaudRate=115200; //波特率115200 USART2_InitStructure.USART_WordLength=USART_WordLength_8b; //数据位8位 USART2_InitStructure.USART_StopBits=USART_StopBits_1; //停止位1位 USART2_InitStructure.USART_Parity=USART_Parity_No ; //无校验 USART2_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //无硬件流 USART2_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; //发送/接收使能 USART_Init(USART2, USART2_InitStructure); //初始化USART2成员变量 USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); //开启串口空闲IDEL中断 USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE); //开启串口DMA接收 USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE); //开启串口DMA发送 RS485_TX_EN=0; //默认为接收模式 USART_Cmd(USART2,ENABLE); //串口使能 } //USART2中断配置函数 void USART2_NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn; //USART2全局中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级为2 NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; //子优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //通道使能 NVIC_Init( NVIC_InitStructure); //初始化中断成员变量 } //USART2初始化函数 void USART2_Init(void) { USART2_Configuration( ); USART2_NVIC_Configuration( ); } //DMA1_USART2_RX参数配置函数 void DMA1_USART2_RX_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA1时钟 DMA_Cmd(DMA1_Channel6, DISABLE); //关DMA1通道6 DMA_DeInit(DMA1_Channel6); //恢复为缺省值 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) USART2->DR; //DMA外设基地址 DMA_InitStructure.DMA_MemoryBaseAddr = rcv_bufferfer_temp[0]; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //设置外设为数据源 DMA_InitStructure.DMA_BufferSize = 128; //DMA缓存大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不递增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度8位,一个字节 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度8位,一个字节 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //单次传输模式 DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //优先级设置 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //关闭内存到内存的DMA模式 DMA_Init(DMA1_Channel6, DMA_InitStructure); //初始化DMA成员变量 DMA_ClearFlag(DMA1_FLAG_GL6); //清除DMA1所有标志 // DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE); //开启DMA1通道6传输完成中断 DMA_Cmd(DMA1_Channel6, ENABLE); //开启DMA1通道6,等待接收数据 } /************************************************************************************************** //当使用总线空闲检测一帧数据是否发完时,DMA1_USART2_RX_NVIC_Configuration( )就不需要 //DMA1_USART2_RX中断配置函数 void DMA1_USART2_RX_NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn; //DMA1_USART2接收中断通道6 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级为2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能 NVIC_Init( NVIC_InitStructure); //初始化成员变量 } **************************************************************************************************/ //DMA1_USART2_RX初始化函数 void DMA1_USART2_RX_Init(void) { DMA1_USART2_RX_Configuration( ); // DMA1_USART2_RX_NVIC_Configuration( ); } //DMA1_USART2_TX参数配置函数 void DMA1_USART2_TX_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA1时钟 DMA_Cmd(DMA1_Channel7, DISABLE); //关DMA1通道7 DMA_DeInit(DMA1_Channel7); //恢复为缺省值 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) USART2->DR; //DMA外设基地址 DMA_InitStructure.DMA_MemoryBaseAddr = rcv_bufferfer_temp[0]; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //设置外设为目标 DMA_InitStructure.DMA_BufferSize = rcv_num_temp; //需要发送的字节数 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不递增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度8位,一个字节 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度8位,一个字节 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //单次传输模式 DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //优先级设置 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //关闭内存到内存的DMA模式 DMA_Init(DMA1_Channel7, DMA_InitStructure); //初始化DMA成员变量 DMA_ClearFlag(DMA1_FLAG_GL7); //清除DMA所有标志 DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE); //开启DMA1通道7传输完成中断 DMA_Cmd(DMA1_Channel7, ENABLE); //开启DMA1通道7,等待发送数据 } //DMA1_USART2_TX中断配置函数 void DMA1_USART2_TX_NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn; //DMA1_USART2接收中断通道7 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级为2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能 NVIC_Init( NVIC_InitStructure); //初始化成员变量 } //DMA1_USART2_TX初始化函数 void DMA1_USART2_TX_Init(void) { DMA1_USART2_TX_Configuration( ); DMA1_USART2_TX_NVIC_Configuration( ); } //DMA1_USART2初始化函数 void DMA1_USART2_Init(void) { DMA1_USART2_RX_Init( ); //DMA1_USART2_RX初始化函数 DMA1_USART2_TX_Init( ); //DMA1_USART2_TX初始化函数 } //RS485_USART2初始化函数 void RS485_USART2_Init(void) { USART2_Init( ); //USART2初始化函数 DMA1_USART2_Init( ); //DMA1_USART2初始化函数 } //USART2数据接收中断函数 void USART2_IRQHandler(void) { u8 Clear=Clear; LED0=0; if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //空闲中断 { Clear=USART2->SR; //读SR寄存器 Clear=USART2->DR; //读DR寄存器(先读SR再读DR,就是为了清除IDLE中断) DMA_Cmd( DMA1_Channel6, DISABLE ); //关DMA1通道6 rcv_complete_temp= 1; //一帧接收完成临时缓存 } } //USART2_DMA1数据发送中断函数 void DMA1_Channel7_IRQHandler(void) { if(DMA_GetITStatus(DMA1_FLAG_TC7)) //如果DMA1通道7发送完成 { LED1=1; DMA_Cmd( DMA1_Channel7, DISABLE ); // 关闭DMA通道7 DMA_ClearITPendingBit( DMA1_FLAG_GL7 ); // 清除标志 send_complete=1; //发送完成 } } //USART2_DMA1数据接收函数 void USART2_DMA1_Rx_Data(void) { if( rcv_complete_temp== 0 ) //如果未接收到一帧数据 { DMA_Cmd( DMA1_Channel6, DISABLE ); //关DMA1通道6 DMA_ClearFlag( DMA1_FLAG_GL6 ); //清除DMA1所有标志 DMA1_Channel6->CNDTR = 128; //重新赋值计数值(DMA缓存大小) DMA_Cmd(DMA1_Channel6, ENABLE); //开启DMA1通道6,等待接收数据 } if( rcv_complete_temp== 1 ) //如果接收到一帧数据 { DMA_Cmd( DMA1_Channel6, DISABLE ); //关DMA1通道6 DMA_ClearFlag( DMA1_FLAG_GL6 ); //清除DMA1所有标志 rcv_num_temp= 128- DMA_GetCurrDataCounter( DMA1_Channel6 ); //获取接收到的字节数 LED0=1; // if( rcv_bufferfer_temp[0]>0 ) LED0=0; rcv_complete=1; //接收完成 } } //USART2_DMA1数据发送函数 void USART2_DMA1_Tx_Data(void) { LED1=0; rcv_complete_temp= 0; DMA_Cmd( DMA1_Channel7, DISABLE ); // 关闭DMA通道 DMA_ClearFlag(DMA1_FLAG_GL7); //清除DMA所有标志 DMA1_Channel7->CNDTR = rcv_num_temp; // 设置要发送的字节数 DMA_Cmd( DMA1_Channel7, ENABLE ); //开始DMA发送 } |
|
相关推荐
1个回答
|
|
STM32串口DMA通讯接收不到数据的原因可能有以下几点,请逐一排查:
1. 串口配置问题:请检查串口的波特率、数据位、停止位和奇偶校验位等参数是否与发送端(串口助手)一致。 2. DMA配置问题:请检查DMA的通道、内存地址、外设地址、数据宽度、传输方向等参数是否正确配置。 3. 中断配置问题:请检查是否正确配置了串口接收中断和DMA中断,以及是否在中断服务程序中正确处理了接收到的数据。 4. 硬件连接问题:请检查STM32的串口TX和RX引脚是否正确连接到串口助手的RX和TX引脚。 5. 程序逻辑问题:请检查程序中的逻辑是否正确,例如是否在接收到数据后正确地将数据从DMA缓存区复制到用户定义的缓冲区。 6. LED灯问题:您提到LED0和LED1会常亮,这可能是因为程序中的某个条件判断错误或者中断服务程序中的逻辑错误导致的。 建议您按照以下步骤进行排查: 1. 检查串口配置参数,确保与发送端一致。 2. 检查DMA配置参数,确保正确配置。 3. 检查中断配置,确保串口接收中断和DMA中断已正确配置。 4. 检查硬件连接,确保TX和RX引脚正确连接。 5. 检查程序逻辑,确保接收到的数据能够正确处理。 6. 检查LED灯相关的条件判断和中断服务程序,确保逻辑正确。 希望以上建议能帮助您解决问题。如果问题仍然存在,请提供更详细的代码和硬件连接信息,以便进一步分析。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
645浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
516浏览 3评论
532浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
505浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 12:27 , Processed in 0.640190 second(s), Total 48, Slave 42 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号