OpenEdv-开源电子网

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

F103的串口DMA发送能进中断但没有数据发出来???

[复制链接]

3

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
121
金钱
121
注册时间
2019-7-4
在线时间
23 小时
发表于 2020-5-19 10:06:09 | 显示全部楼层 |阅读模式
void Usart2_Tx_DMAConfig()    //串口2-DMA的发送初始化配置                                               
{
DMA_InitTypeDef  DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA1时钟   

   
DMA_DeInit(DMA1_Channel7);//查映像,USART2_TX为DMA1的7通道
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;//外设DMA一个地址
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&HW_SendData;//数据内存地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//设置DMA单向传输
  DMA_InitStructure.DMA_BufferSize = Buffer_Len;//缓存大小
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//缓存地址增长
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//8bit
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//使用普通模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//存储器到存储器使能,仅DMA2用
  DMA_Init(DMA1_Channel7, &DMA_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
NVIC_Init(&NVIC_InitStructure);

DMA_ITConfig(DMA1_Channel7,DMA_IT_TC,ENABLE);//开启DMA发送完成中断
DMA_Cmd(DMA1_Channel7, DISABLE);             //关闭DMA传输
}

void Usart2_Rx_DMAConfig()   //串口2-DMA的接收初始化配置
{
DMA_InitTypeDef  DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA1时钟               
/* DMA1 channel6 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel6);//查映像,USART2_RX为DMA1的6通道
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;  ;//外设DMA一个地址
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&usart2_buf;//数据内存地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//设置DMA单向传输
  DMA_InitStructure.DMA_BufferSize = Buffer_Len;//缓存大小
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//缓存地址增长
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//8bit
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//使用普通模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//只用DMA1优先级可随意
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//存储器到存储器使能,仅DMA2用
  DMA_Init(DMA1_Channel6, &DMA_InitStructure);
  
  /* Enable DMA1 channel6 */
  DMA_Cmd(DMA1_Channel6, ENABLE);//开启DMA传输
}

void uart2_init(u32 bound)
{
//GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟  
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能USART2,GPIOA时钟在uart1_init()里已经打开了
//USART2_TX   GPIOA.2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
   
  //USART2_RX   GPIOA.3初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3  

  //Usart2 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
  
  //USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
  USART_Init(USART2, &USART_InitStructure); //初始化串口2
  USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//********开启串口空闲中断********
  USART_Cmd(USART2, ENABLE);                    //使能串口2  

USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);   //*******使能串口2的DMA发送 *******
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);  //*******使能串口2的DMA接收 *******

Usart2_Tx_DMAConfig();
Usart2_Rx_DMAConfig();
}

void Dma_Send_Enable(DMA_Channel_TypeDef* DMAy_Channelx,u16 ndtr)             //DMA的发送使能
{
DMA_SetCurrDataCounter(DMAy_Channelx,ndtr);                                //数据传输量  
DMA_Cmd(DMAy_Channelx, ENABLE);                                            //开启DMA传输
}   
//DMA的发送完成中断函数
void DMA1_Channel7_IRQHandler(void)                        
{
  if(DMA_GetFlagStatus(DMA1_FLAG_TC7)!=RESET)                //等待DMA1_channel7传输完成  
  {  
  断点2:  DMA_ClearFlag(DMA1_FLAG_TC7);                            //清除DMA1_channel7传输完成标志
  while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET);//等待发送为空
    DMA_Cmd(DMA1_Channel7,DISABLE);                          //关闭DMA           
    DMA_ClearITPendingBit(DMA1_IT_TC7);                      //清除中断屏蔽位     
  }  
}

//串口2中断服务程序,接收红外返回数据
void USART2_IRQHandler(void)               
{
u8 i;
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  //接收中断(5A data1 data2 crc)
{
  DMA_Cmd(DMA1_Channel6, DISABLE);//开启DMA传输   
  i =USART_ReceiveData(USART2); //读DR,是为了清除IDLE中断
   index_usart2 = Buffer_Len - DMA_GetCurrDataCounter(DMA1_Channel6);//获得这一帧的数据长度
  if(index_usart2!=0)
  {
   RX2_OK=1;                                                           //数据帧接收标志位置1
      for(i=0;i<index_usart2;i++)
      {
        SendBuffer[i]= usart2_buf[i];                                   //将接收的数据保存
      }
      for(i=0;i<index_usart2;i++)                                                //将数据缓存区清零
      {
        usart2_buf[i]=0;
      }
  }
  
  DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_HT6 | DMA1_FLAG_TE6 ); //清除DMA1_Channel3传输完成标志(非中断标志)
    DMA_SetCurrDataCounter(DMA1_Channel6, Buffer_Len); //设置DMA接收单元的长度
    DMA_Cmd(DMA1_Channel6, ENABLE);//开启DMA传输                                      
  
}
}

发送部分
  if(HW_SendNum>0)
{
  m_Out[0] = BPHW_STX;  //帧头
  btCheckSum=m_Out[0];
  for(i=0;i<HW_SendNum;i++)
  {
   m_Out[i+1] = HW_SendData[i];
   btCheckSum += HW_SendData[i];//加法
  }
  m_Out[1 + HW_SendNum] = btCheckSum%256; //校验码
  m_Out[2 + HW_SendNum] = BPHW_ETX1;   //帧尾
  m_Out[3 + HW_SendNum] = BPHW_ETX2;   //帧尾
  HW_SendNum = HW_SendNum + BPHW_SELEN;
  for ( i = 0;i<HW_SendNum;i++)
  {
   HW_SendData[i] = m_Out[i];
  }
  
  断点1:Dma_Send_Enable(DMA1_Channel7,HW_SendNum);//使能并开始DMA发送
//    HW_SendNum=0;
////  for(i=0;i<20;i++)
////  {
////   HW_SendData[i]=0;
////  }
      

串口2的DMA发送中断,查找了很多遍,不知配置哪里出问题。调试时候发现HW_SendData数组在断点1处有数据,在进入发送完成中断的断点2处:HW_SendData数组全部为0;且串口一直没数据出来。不知什么原因。DR也观察不到有数据。初调试请各位帮忙看看?
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

58

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2015-12-27
在线时间
0 小时
发表于 2020-5-19 10:06:09 | 显示全部楼层
回复 支持 反对

使用道具 举报

3

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
121
金钱
121
注册时间
2019-7-4
在线时间
23 小时
 楼主| 发表于 2020-5-19 14:08:14 | 显示全部楼层
已经找出问题了,传输方向设置错了将串口发送DMA配置为:DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST  ;设置DMA双向传输即可调通
回复 支持 反对

使用道具 举报

3

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
121
金钱
121
注册时间
2019-7-4
在线时间
23 小时
 楼主| 发表于 2020-5-22 10:04:18 | 显示全部楼层
注意在清发送缓存时,需要在产生DMA完成中断之后,可在中断设标志位,再在主处理中清,不可直接清。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-28 14:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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