OpenEdv-开源电子网

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

stm32F103 UART4 不能同时使用DAM发送和接收的问题。

[复制链接]

1

主题

6

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2017-4-20
在线时间
2 小时
发表于 2021-4-26 16:56:48 | 显示全部楼层 |阅读模式
10金钱
1.使用芯片:STM32F103RCT6
2.使用串口:UART4
3.想实现的功能:UART4使用DMA发送和接收。
4.存在的问题:不使能UART4的DMA发送功能时,DMA可以接收到数据,但是一旦使能UART4的DMA发送,DMA就接收不到数据。
5.代码
(1)UART4配置及中断代码:
void uart_init(u32 baud)
{   
  float temp;
  u16 mantissa;
  u16 fraction;   
  temp=(float)(36*1000000)/(baud*16);//得到USARTDIV pclk1 = 36MHz
  mantissa=temp;     //得到整数部分
   fraction=(temp-mantissa)*16; //得到小数部分  
     mantissa<<=4;
  mantissa+=fraction;
  RCC->APB1ENR |= 1<<19; // 使能USART4串口时钟
  RCC->APB1RSTR |= 1<<19;  // 复位USART4
  RCC->APB1RSTR &= ~(1<<19); // 停止复位
  //波特率设置
  UART4->BRR = mantissa; // 波特率设置
  UART4->CR1 |= 0X200C;  //1位停止,无校验位.

  UART4->CR3 = 1<< 6;   // DMAR = 1, 使能UART4的DMA接收
      // 只要置位DMAT(使能DMA发送),就不能接收???????????????????????????
  UART4->CR3 = 1<< 7;  // DMAT = 1, 使能UART4的DMA发送
             // 只要开启DMA发送使能,就不能接收,奇怪
             // ?????????????????????????????????????????

  //使能空闲中断
  UART4->CR1 |= 1<<4;   // IDLEIE = 1, IDLE interrupt enable

  MY_NVIC_Init(3,2,UART4_IRQn,2); //抢占3,子优先级3,组2
}

void UART4_IRQHandler(void)
{
  u8 tempByte;
  u16 tempWord;


  // IDLE line detected
  if(UART4->SR & (1<<4))
  {
      DMA2_Channel3->CCR  &= ~(1<<0);    // 关闭DMA2的通道3
  
      // 清除IDLE标志位方式:先读USART_SR,然后读USART_DR
      tempByte = UART4->SR;
      tempByte = UART4->DR;
      UART4->SR &= ~(1<<4);
  
     uart4RxRevLen = UART4_RX_BUF_LEN - DMA2_Channel3->CNDTR;  // 读取接收到的字节数
      DMA2_Channel3->CNDTR = UART4_RX_BUF_LEN;    // 重置字节数
      DMA2_Channel3->CCR  |= 1<<0;    // 打开DMA2的通道3
  }

}
(2)DMA配置及收发代码
void InitDma(void)
{
// ******************************** DMA2 Channel3 - UART4_RX ***************************************
// UART4使用DMA2的通道3作为发送通道
     RCC->AHBENR |= 1<<1;  // 开启DMA2时钟
     delay_ms(5);    // 等待DMA时钟稳定

     DMA2_Channel3->CPAR  = (u32)&UART4->DR; // Peripheral address register, point to UART4_DR
     DMA2_Channel3->CMAR  = (u32)uart4RxBuf; // Memory address register
     DMA2_Channel3->CNDTR = UART4_RX_BUF_LEN; // Number of data
     DMA2_Channel3->CCR  = 0x00000000;  // RESET DMA
     DMA2_Channel3->CCR  |= 1<<1;   // TCIE = 1, transfer complete interrupt enable
     DMA2_Channel3->CCR   |= 1<<3;   // TEIE = 1, Transfer error interrupt enable
     DMA2_Channel3->CCR  |= 0<<4;   // DIR = 0, read from peripheral
     DMA2_Channel3->CCR  |= 0<<5;   // CIRC = 0, circular mode disable
     DMA2_Channel3->CCR  |= 0<<6;   // PINC = 0, Peripheral increment mode disabled
     DMA2_Channel3->CCR  |= 1<<7;   // MINC = 1, Memory increment mode enabled
     DMA2_Channel3->CCR  |= 0<<8;   // PSIZE =0, peripheral data 8-bits
     DMA2_Channel3->CCR  |= 0<<10;   // MSIZE =0, memory data 8-bits
     DMA2_Channel3->CCR  |= 2<<12;   // PL = 1, channel priority level:medium
     DMA2_Channel3->CCR  |= 0<<14;   // MEM2MEM = 0, memory to memory mode disable

     DMA2_Channel3->CCR  |= 1<<0;   // EN = 1, channel enable

     MY_NVIC_Init(3,3,DMA2_Channel3_IRQn,2);  //抢占3,子优先级3,组2

// ******************************** DMA2 Channel5 - UART4_TX ***************************************
// UART4使用DMA2的通道5作为发送通道
     RCC->AHBENR |= 1<<1;  // 开启DMA2时钟
     delay_ms(5);    // 等待DMA时钟稳定

     DMA2_Channel5->CPAR  = (u32)&UART4->DR; // Peripheral address register, point to UART4_DR
     DMA2_Channel5->CMAR  = (u32)uart4TxBuf; // Memory address register
     DMA2_Channel5->CNDTR = UART4_TX_BUF_LEN; // Number of data,实际设置128
     DMA2_Channel5->CCR  = 0x00000000;  // RESET DMA
     DMA2_Channel5->CCR   |= 1<<1;   // TCIE = 1, transfer complete interrupt enable
     DMA2_Channel5->CCR  |= 1<<4;   // DIR = 1, Read from memory
     DMA2_Channel5->CCR  |= 0<<5;   // CIRC = 0, Circular mode disabled
     DMA2_Channel5->CCR  |= 0<<6;   // PINC = 0, Peripheral increment mode disabled
     DMA2_Channel5->CCR  |= 1<<7;   // MINC = 1, Memory increment mode enabled
     DMA2_Channel5->CCR  |= 0<<8;   // PSIZE =0, peripheral data 8-bits
     DMA2_Channel5->CCR  |= 0<<10;   // MSIZE =0, memory data 8-bits
     DMA2_Channel5->CCR  |= 1<<12;   // PL = 1, channel priority level:medium
     DMA2_Channel5->CCR  |= 0<<14;   // MEM2MEM = 0, memory to memory mode disable

     DMA2_Channel5->CCR  |= 1<<0;   // EN = 1, channel enable

     MY_NVIC_Init(2,2,DMA2_Channel4_5_IRQn,2);  //抢占3,子优先级3,组2
}

// 在DMA2通道5的发送完成中断中置位允许发送标志,这里用全局变量dmasend
void DMA2_Channel4_5_IRQHandler(void)
{
     u8 tempByte;
     if(DMA2->ISR & (1<<17))
     {
          DMA2->IFCR |= 1<<17; // CTCIF5 = 1, Clear transfer complete flag
          //DMA2->IFCR |= 1<<19; // CTEIF = 1, Clear Channel 3 transfer error flag
          DMA2_Channel5->CCR  &=~(1<<0);       //关闭DMA传输
         dmaSend = 1;      // 置位允许发送标值
         UART4->SR &= ~(1<<6);

     }
}

//开启一次DMA传输
// 主程序中定时调用该函数进行发送
static u8 byteSend1 = 0;
void uart4_dma_send(void)
{
     if(dmaSend == 1)
     {
          // 更新发送缓冲区
          uart4TxBuf[0] = byteSend1;
          uart4TxBuf[1] = byteSend1+1;
          uart4TxBuf[2] = byteSend1+2;
          uart4TxBuf[3] = byteSend1+3;
          uart4TxBuf[4] = byteSend1+4;

          byteSend1 += 1;

          DMA2_Channel5->CNDTR = 5;    // 重置DMA发送字节数
          DMA2_Channel5->CCR |= 1<<0;   // 开启DMA传输

          dmaSend = 0;
     }
}

         说明:以上就是DMA发送接收的代码,思路就是定时调用发送函数uart4_dma_send()进行DMA发送;
接收是在UART4的空闲中断中读取DMA缓冲区的数据,并重新启动DMA接收。
   现在的问题是,只要在串口配置函数中添加这一行:
   UART4->CR3 = 1<< 7;  // DMAT = 1, 使能UART4的DMA发送

   DMA就不能接收到数据,注释掉就能接收到,不知为何。

   还请论坛高手前辈们指点。

最佳答案

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

问题找到。 这两行代码写错: UART4->CR3 = 1CR3 = 1CR3 |= 1CR3 |= 1
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2017-4-20
在线时间
2 小时
 楼主| 发表于 2021-4-26 16:56:49 | 显示全部楼层
问题找到。
这两行代码写错:
       UART4->CR3 = 1<< 6;   // DMAR = 1, 使能UART4的DMA接收
  UART4->CR3 = 1<< 7;  // DMAT = 1, 使能UART4的DMA发送
应该写成:
       UART4->CR3 |= 1<< 6;   // DMAR = 1, 使能UART4的DMA接收
  UART4->CR3 |= 1<< 7;  // DMAT = 1, 使能UART4的DMA发送

本来该位或,写成直接赋值了,粗心啊。以后能拷贝粘贴绝不手写,哈哈。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165352
金钱
165352
注册时间
2010-12-1
在线时间
2108 小时
发表于 2021-4-26 23:53:41 | 显示全部楼层
帮顶
回复

使用道具 举报

13

主题

643

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2432
金钱
2432
注册时间
2019-12-28
在线时间
527 小时
发表于 2021-4-27 10:42:21 | 显示全部楼层
帮顶  
回复

使用道具 举报

70

主题

275

帖子

0

精华

高级会员

Rank: 4

积分
728
金钱
728
注册时间
2017-6-20
在线时间
188 小时
发表于 2023-5-9 13:47:46 | 显示全部楼层
帮顶
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-24 09:33

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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