[ARM入门] STM32F0 SPI和串口同时使用DMA造成通道冲突的问题

[复制链接]
2284|0
 楼主| 呐咯密密 发表于 2022-2-21 11:28 | 显示全部楼层 |阅读模式
DM, ST, pi, AC, AD
在开发STM32F031芯片的项目时同时用到了串口DMA发送和SPI的DMA,因为两个功能我独立开发,开发完成之后准备移植到一起,结果代码运行出问题,检查后发现是串口发送DMA和SPI的接收DMA共用了DMA1_Channel2,于是马上翻看手册,嘿,还真看到了好消息。在STM32F1 系列与 STM32F0 系列移植手册的表9.STM32F1 系列与 STM32F0 系列之间的 DMA 请求区别 中发现了这个大宝贝:

USART1除了使用通道2和3还可以使用通道4和5。
于是马上修改代码,编译后再调试。。。。。。。。。。不行啊!!!!!
检查配置,没错啊,不过是换通道而已,那到底怎么回事,总不能手册从写错了吧,于是开始搜索之路,就在地铁上突然看到有人遇到同样的问题,最后说的是需要重映像,于是就去找库函数,别说,还真有。
void SYSCFG_DMAChannelRemapConfig(uint32_t SYSCFG_DMARemap, FunctionalState NewState)函数。函数原型如下:
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]  Configure the DMA channels remapping.
  3.   * @param  SYSCFG_DMARemap: selects the DMA channels remap.
  4.   *          This parameter can be one of the following values:
  5.   *            [url=home.php?mod=space&uid=2817080]@ARG[/url] SYSCFG_DMARemap_TIM17: Remap TIM17 DMA requests from channel1 to channel2
  6.   *            @arg SYSCFG_DMARemap_TIM16: Remap TIM16 DMA requests from channel3 to channel4
  7.   *            @arg SYSCFG_DMARemap_USART1Rx: Remap USART1 Rx DMA requests from channel3 to channel5
  8.   *            @arg SYSCFG_DMARemap_USART1Tx: Remap USART1 Tx DMA requests from channel2 to channel4
  9.   *            @arg SYSCFG_DMARemap_ADC1: Remap ADC1 DMA requests from channel1 to channel2
  10.   * @param  NewState: new state of the DMA channel remapping.
  11.   *         This parameter can be: ENABLE or DISABLE.
  12.   * [url=home.php?mod=space&uid=536309]@NOTE[/url]   When enabled, DMA channel of the selected peripheral is remapped
  13.   * @note   When disabled, Default DMA channel is mapped to the selected peripheral
  14.   * @note   By default TIM17 DMA requests is mapped to channel 1,
  15.   *         use SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_TIM17, Enable) to remap
  16.   *         TIM17 DMA requests to channel 2 and use
  17.   *         SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_TIM17, Disable) to map
  18.   *         TIM17 DMA requests to channel 1 (default mapping)
  19.   * @note   This function is only used for STM32F030, STM32F031, STM32F042, STM32F072 and STM32F051 devices.   
  20.   * @retval None
  21.   */
  22. void SYSCFG_DMAChannelRemapConfig(uint32_t SYSCFG_DMARemap, FunctionalState NewState)
  23. {
  24.   /* Check the parameters */
  25.   assert_param(IS_SYSCFG_DMA_REMAP(SYSCFG_DMARemap));
  26.   assert_param(IS_FUNCTIONAL_STATE(NewState));

  27.   if (NewState != DISABLE)
  28.   {
  29.     /* Remap the DMA channel */
  30.     SYSCFG->CFGR1 |= (uint32_t)SYSCFG_DMARemap;
  31.   }
  32.   else
  33.   {
  34.     /* use the default DMA channel mapping */
  35.     SYSCFG->CFGR1 &= (uint32_t)(~SYSCFG_DMARemap);
  36.   }
  37. }
@arg SYSCFG_DMARemap_USART1Tx: Remap USART1 Tx DMA requests from channel2 to channel4
将串口1的DMA发送从通道2重映射到通道4。雾操,我这英语4级没过的都看懂了,简直欣喜若狂,感觉用起来。
已经水了这么多了,结贴吧,结果确实没问题,不过还要打开SYSCFG的时钟,这是重点。不然又是一个坑。下面把我的贴出来:
  1. //DMA的通道二被SPI占用,此处使用SYSCFG_DMAChannelRemapConfig将DMA通道重定向
  2. void MYDMA_485_Config(void)
  3. {
  4.                 DMA_InitTypeDef DMA_InitStructure;
  5.        
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);      //使能SYSCFG时钟,必须的
  7.         SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_USART1Tx, ENABLE);//将DMA串口发送从通道2重映射到通道4
  8.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);        //使能DMA传输
  9.        
  10.         SPI_DMA1_MEM_LEN = 11;
  11.         DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_BASE+0x28;  //DMA外设基地址
  12.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RS485_TX_BUF;  //DMA内存基地址
  13.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设
  14.         DMA_InitStructure.DMA_BufferSize = SPI_DMA1_MEM_LEN;  //DMA通道的DMA缓存的大小
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
  16.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
  17.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位
  18.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
  19.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常缓存模式
  20.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
  21.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
  22.         DMA_Init(DMA1_Channel4, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
  23.         DMA_Cmd(DMA1_Channel4, ENABLE);  //使能USART1 TX DMA1 所指示的通道         

  24. }



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

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

本版积分规则

认证:苏州澜宭自动化科技嵌入式工程师
简介:本人从事磁编码器研发工作,负责开发2500线增量式磁编码器以及17位、23位绝对值式磁编码器,拥有多年嵌入式开发经验,精通STM32、GD32、N32等多种品牌单片机,熟练使用单片机各种外设。

568

主题

4085

帖子

56

粉丝
快速回复 在线客服 返回列表 返回顶部