STM32串口通讯收不到数据求助
//STM32串口DMA通讯接收不到数据//请各位大神帮忙看看,下面的DMA配置问题出在哪里//程序编写思路是:用串口助手发数据给STM32的串口2,收到数据后返回收到的数据给串口助手;
//现在遇到的问题:用串口助手发数据给它,但不能返回数据,LED0和LED1会常亮;//小弟初学,这个问题弄了一个星期还没有解决,望大家高抬贵手帮帮我;//谢谢
u8 rcv_num_temp=0;//接收到的数据长度临时缓存u8 rcv_num=0;//接收到的数据长度缓存
u8 rcv_bufferfer_temp;//接收数据临时缓存,最大64个字节u8 rcv_buffer;//接收缓存,最大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;//PD7GPIO_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;//PA2GPIO_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;//PA3GPIO_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);//复位串口2RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位
//USART2通讯协议USART2_InitStructure.USART_BaudRate=115200;//波特率115200USART2_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;//抢占优先级为2NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//子优先级为0NVIC_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通道6DMA_DeInit(DMA1_Channel6);//恢复为缺省值DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;//DMA外设基地址DMA_InitStructure.DMA_MemoryBaseAddr = rcv_bufferfer_temp;//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接收中断通道6NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级为2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子优先级为0NVIC_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通道7DMA_DeInit(DMA1_Channel7);//恢复为缺省值DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;//DMA外设基地址DMA_InitStructure.DMA_MemoryBaseAddr = rcv_bufferfer_temp;//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接收中断通道7NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级为2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级为0NVIC_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 )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发送}
不要DMA 直接中断 开启接收非空中断允许那样接收到一个 就send一个 :):):):):):):):):):):) lovehxh-374732 发表于 2016-10-30 11:46
不要DMA 直接中断 开启接收非空中断允许那样接收到一个 就send一个
我之前就是用接收非空做的,很稳定但是很慢,所有现在做成DMA形式的,也参考了许多网上的资料,现在找不到问题出在哪里 DMA发送要主动触发的,485发送和接受的控制信号是相反的,串口接收中断一般是检测RXNE标志,不是IDLE。。。建议你看看原子哥的例程。。。 cuyebiren 发表于 2016-10-30 18:56
DMA发送要主动触发的,485发送和接受的控制信号是相反的,串口接收中断一般是检测RXNE标志,不是IDLE。。。 ...
//USART2½ÓÊÕÖжϺ¯Êý
void USART2_IRQHandler(void)//Êý¾Ý½ÓÊÕÖжÏ
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//ÓÃÕâ¾ä¿ÉÒÔÕý³£½ÓÊÕÒ»Ö¡Êý¾Ý
// if(USART2->SR&=1<<5)//½ÓÊÕµ½Êý¾Ý,ÓÃÕâ¾ä»á¾³£¶à½ÓÊÕÒ»Ö¡Êý¾Ý
{
rcv_bufferfer_temp=USART2->DR; //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
}
}
这是我之前的接收非空做法,很稳定也很慢,所以就改用DMA,有劳大家帮我出出主意,xiexie gtygg 发表于 2016-10-30 19:13
//USART2½ÓÊÕÖжϺ¯Êý
void USART2_IRQHandler(void)//Êý¾Ý½ÓÊÕÖжÏ
{
115200的波特率不会慢的。。。还是建议你看看开发板例程,如:正点原子,野火。。。 好多。。看不下去了。。。 本帖最后由 gtygg 于 2016-10-31 19:23 编辑
cuyebiren 发表于 2016-10-31 10:30
115200的波特率不会慢的。。。还是建议你看看开发板例程,如:正点原子,野火。。。 ...
谢谢,我之前就是用正点原子的例程改的,反正速度不快,所以就想用DMA,准备向500K奋斗,现在可以收数据了,但是有一部分乱码,还在研究,谢谢 静海惊天 发表于 2016-10-31 16:52
好多。。看不下去了。。。
加油,大家一起学习,共同进步
页:
[1]
2