你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32串口通讯收不到数据求助

[复制链接]
gtygg 提问时间:2016-10-30 10:47 /
悬赏5ST金币未解决

//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 评论14 发布时间:2016-10-30 10:47

举报

14个回答
lovehxh-374732 回答时间:2016-10-30 11:46:39
不要DMA 直接中断 开启接收非空中断允许  那样接收到一个 就send一个

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

asssdz-382474 回答时间:2016-10-30 12:43:33
:)
gtygg 回答时间:2016-10-30 13:55:32
lovehxh-374732 发表于 2016-10-30 11:46
不要DMA 直接中断 开启接收非空中断允许  那样接收到一个 就send一个

我之前就是用接收非空做的,很稳定但是很慢,所有现在做成DMA形式的,也参考了许多网上的资料,现在找不到问题出在哪里
cuyebiren 回答时间:2016-10-30 18:56:59
DMA发送要主动触发的,485发送和接受的控制信号是相反的,串口接收中断一般是检测RXNE标志,不是IDLE。。。建议你看看原子哥的例程。。。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

gtygg 回答时间:2016-10-30 19:13:21
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[rcv_num_temp++]=USART2->DR;         //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý                 
        }               
}

这是我之前的接收非空做法,很稳定也很慢,所以就改用DMA,有劳大家帮我出出主意,xiexie
cuyebiren 回答时间:2016-10-31 10:30:34
gtygg 发表于 2016-10-30 19:13
//USART2½ÓÊÕÖжϺ¯Êý
void USART2_IRQHandler(void)  //Êý¾Ý½ÓÊÕÖжϠ      
{       

115200的波特率不会慢的。。。还是建议你看看开发板例程,如:正点原子,野火。。。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

静海惊天 回答时间:2016-10-31 16:52:50
好多。。看不下去了。。。
gtygg 回答时间:2016-10-31 19:16:54
本帖最后由 gtygg 于 2016-10-31 19:23 编辑
cuyebiren 发表于 2016-10-31 10:30
115200的波特率不会慢的。。。还是建议你看看开发板例程,如:正点原子,野火。。。 ...

谢谢,我之前就是用正点原子的例程改的,反正速度不快,所以就想用DMA,准备向500K奋斗,现在可以收数据了,但是有一部分乱码,还在研究,谢谢
gtygg 回答时间:2016-10-31 19:26:29
静海惊天 发表于 2016-10-31 16:52
好多。。看不下去了。。。

加油,大家一起学习,共同进步
12下一页
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版