OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3611|回复: 3

串口DMA通讯接收不到数据

[复制链接]

33

主题

99

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
309
金钱
309
注册时间
2016-5-20
在线时间
45 小时
发表于 2016-10-23 21:14:57 | 显示全部楼层 |阅读模式
10金钱
请各位大神帮忙看看,下面的DMA配置问题出在哪里
程序编写思路是:用串口助手发数据给正点原子精英板,收到数据后返回收到的数据给串口助手;
现在遇到的问题:用串口助手发数据给它,但不能返回数据,LED0和LED1会常亮;
                        DMA1_Uart2_Init( ) 是在main(  )的开始处,初始化的;


                       试过不要DMA1_Uart2_Init( ) ,直接在USART2_DMA1_Rx_Data( )的开始处调用USART2_Rx_DMA1_Channe6_Configuration( )和
                                                                 直接在USART2_DMA1_Tx_Data( )的开始处调用USART2_Tx_DMA1_Channe7_Configuration( )都不行。


现在不知道问题出在哪里,请指点,谢谢!


//USART2及相关IO口初始化函数
void USART2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART2_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);  //使能GPIOD时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);  //使能GPIOF时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);  //使能USART2时钟
       
USART_DeInit(USART2);

//发送接收控制模式       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;  //PD7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);

//USART2-TX       
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;  //PA2
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
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_10MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  //浮空输入
GPIO_Init(GPIOA,&GPIO_InitStructure);

//ID站号
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;  
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;  //下拉输入
GPIO_Init(GPIOF,&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成员变量



//USART2发送DMA通道中断初始化
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;  //USART2发送DMA通道中断配置
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //抢占优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //子优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //通道使能
NVIC_Init(&NVIC_InitStructure);  

//USART2中断初始化
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);  //初始化中断成员变量

//USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);  //开串口RXNE中断使能
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_DMA1通道6数据接收初始化函数
void USART2_Rx_DMA1_Channe6_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)&USART1->DR;  //DMA外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = rcv_bufferfer_temp[0];  //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //设置外设为数据源
DMA_InitStructure.DMA_BufferSize = 64;  //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_Cmd(DMA1_Channel6, ENABLE);  //开启DMA1通道6,等待接收数据
}




//USART2_DMA1通道7数据发送初始化函数
void USART2_Tx_DMA1_Channe7_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)&USART1->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_Cmd(DMA1_Channel7, ENABLE);  //开启DMA1通道7,等待发送数据
       
DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);   //开启DMA1通道7的发送中断
}



//USART2_DMA初始化函数
void DMA1_Uart2_Init(void)
{
  USART2_Rx_DMA1_Channe6_Configuration();  //USART2_DMA1通道6数据接收初始化函数
  USART2_Tx_DMA1_Channe7_Configuration();  //USART2_DMA1通道7数据发送初始化函数

}




//USART2数据接收中断函数
void USART2_IRQHandler(void)
{
        u8 Clear=Clear;
       
  if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  //空闲中断
  {       
                LED0=0;
          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_ClearFlag( DMA1_FLAG_GL7 );  // 清除标志
                DMA_Cmd( DMA1_Channel7, DISABLE );   // 关闭DMA通道7
               
                send_complete=1;  //发送完成
  }
}






//USART2_DMA1数据接收函数
void USART2_DMA1_Rx_Data(void)
{       
        DMA_Cmd(DMA1_Channel6, ENABLE);   /* DMA 开启,等待数据。注意,如果中断发送数据帧的速率很快,MCU来不及处理此次接收到的数据,中断又发来数据的话,这里不能开启,否则数据会被覆盖。有2种方式解决。
    1. 在重新开启接收DMA通道之前,将LumMod_Rx_Buf缓冲区里面的数据复制到另外一个数组中,然后再开启DMA,然后马上处理复制出来的数据。
    2. 建立双缓冲,在LumMod_Uart_DMA_Rx_Data函数中,重新配置DMA_MemoryBaseAddr 的缓冲区地址,那么下次接收到的数据就会保存到新的缓冲区中,不至于被覆盖。*/
               
  if( rcv_complete_temp== 1 )  //如果接收到一帧数据
  {
    DMA_Cmd( DMA1_Channel6, DISABLE );  //关DMA1通道6
    DMA_ClearFlag( DMA1_FLAG_GL6 );  //清除DMA所有标志);  //清除DMA1标志位
    rcv_num_temp= 64- DMA_GetCurrDataCounter( DMA1_Channel6 );  //获取接收到的字节数
    DMA1_Channel6->CNDTR = 64;  //重新赋值计数值(DMA缓存大小)
                LED0=1;
                rcv_complete=1;  //接收完成  
  }
}





//USART2_DMA1数据发送函数
void USART2_DMA1_Tx_Data(void)
{       
        LED1=0;
  DMA_Cmd( DMA1_Channel7, DISABLE );   // 关闭DMA通道
  DMA1_Channel7->CNDTR = rcv_num_temp;  // 设置要发送的字节数
  DMA_Cmd( DMA1_Channel7, ENABLE );  //开始DMA发送
}













最佳答案

查看完整内容[请看2#楼]

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR; //DMA外设基地址 这行写错了是USART2才对
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

33

主题

99

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
309
金钱
309
注册时间
2016-5-20
在线时间
45 小时
 楼主| 发表于 2016-10-23 21:14:58 | 显示全部楼层
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;  //DMA外设基地址
这行写错了是USART2才对
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2016-10-24 22:48:33 | 显示全部楼层
论坛参考下别人的代码
回复

使用道具 举报

33

主题

99

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
309
金钱
309
注册时间
2016-5-20
在线时间
45 小时
 楼主| 发表于 2016-10-24 23:26:15 | 显示全部楼层
正点原子 发表于 2016-10-24 22:48
论坛参考下别人的代码

谢谢提醒,别人的代码我也看了,也是这样配置的,暂时没有看出问题
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-24 10:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表