STM32/STM8技术论坛
直播中

张波

7年用户 1411经验值
私信 关注
[问答]

stm32h7的TIM2 DMA配置,数据不能传输

我遇到的问题是无法在输入捕获事件上配置DMA以正常工作,数据不能传输并发生错误。
static void my_TIM2_initInputCaptureTimer(void) {

  // enable clock source for timer
  RCC->APB1LENR |= (0x1 << 0);
  // set prescaler to 200
  TIM2->PSC = 200 - 1;

  // choose TIM2_CH1 input
  TIM2->TISEL |= (0x0 << 0);
  // set channel 1 as input mapped on TI1
  TIM2->CCMR1 |= (0x1 << 0);
  // digital filter length (0)
  TIM2->CCMR1 |= (0x0 << 4);
  // rising & falling edge
  TIM2->CCER |= (0x1 << 1);
  TIM2->CCER |= (0x1 << 3);
  // prescaler to (0)
  TIM2->CCMR1 |= (0x0 << 2);
  // enable DMA interrupt & Capture/Compare interrupt
  TIM2->DIER |= (0x1 << 9) | (0x1 << 1);
  // capture enabled
  TIM2->CCER |= (0x1 << 0);
  // reset registers WARNING: need for preloading PSC  
  TIM2->EGR |= (0x1 << 0);

  // enable TIM3 timer
  TIM2->CR1 |= TIM_CR1_CEN;
  // enable interrupt request
  NVIC_EnableIRQ(TIM2_IRQn);
  // set priority
  NVIC_SetPriority(TIM2_IRQn, 1);

}
DMA配置:

static void my_DMA_init(void) {
  // enable DMA1 clocking
  RCC->AHB1ENR |= (0x1 << 0);
  // clear EN bit to 0
  DMA1_Stream0->CR &= ~(0x1 << 0);
  // safeguard EN bit reset
  while (DMA1_Stream0->CR & 0x1);
  // check LISR HISR registers
  if ((DMA1->HISR == 0) && (DMA1->LISR == 0))
    printf("status registers is clearrn");
  else
    printf("status register is not clear -- DMA wont startrn");
  // set peripheral addres
  DMA1_Stream0->PAR = TIM2_CCR1_Address;
  // set memory addres
  DMA1_Stream0->M0AR = (unsigned int)buffer;
  // set total number of data items
  DMA1_Stream0->NDTR = 10;

  // NOTE: configurate TIM2_CH1 interrupt route
  // set DMAMUX to route request (TIM2_CH1)
  DMAMUX1_Channel0->CCR |= 18U;

  // set DMA priority (very high)
  DMA1_Stream0->CR |= (0x3 << 16);
  // set memory data size (32)
  DMA1_Stream0->CR |= (0x2 << 13);
  // set peripheral data size (32)
  DMA1_Stream0->CR |= (0x2 << 11);
  // set memory addres increment  (enable)
  DMA1_Stream0->CR |= (0x1 << 10);
  // set peripheral addres increment (disable)
  DMA1_Stream0->CR |= (0x0 << 9);
  // set circular buffer mode (enable)
  DMA1_Stream0->CR |= (0x1 << 8);
  // set data transfer direction (peripheral to memory)
  DMA1_Stream0->CR |= (0x0 << 6);
  // set transfer complete interrupt
  DMA1_Stream0->CR |= (0x1 << 4);
  // set transfer error interrupt
  DMA1_Stream0->CR |= (0x1 << 2);
  // enable DMA1
  DMA1_Stream0->CR |= (0x1 << 0);
  // enable IRQ
  NVIC_EnableIRQ(DMA1_Stream0_IRQn);
  printf("DMA1_Stream0 %u rn", (DMA1_Stream0->CR & 0x1));}
中断例程:

  1. void TIM2_IRQHandler(void) {

  2.   InCapTick = TIM2->CCR1;
  3.   // reset interrupt flag
  4.   TIM2->SR = 0;

  5.   tick = systick_ms;
  6.   flag++;
  7. }

  8. void DMA1_Stream0_IRQHandler(void) {

  9.   printf("withinrn");
  10.   printf("LISR: %u rn", DMA1->LISR);
  11.   // clear interrupt flag
  12.   DMA1->LIFCR |= (0x1 << 3) | (0x1 << 5);

  13. }

STM32h743zi-nucleo board)预期行为:(当你按下用户按钮(蓝色的那个) - > PG0引脚得到SET(1)状态 - >所以输入捕获引脚(PA5,它们应该通过跳线连接)得到低 - 高当你释放按钮时,转换并捕获第一个值(通过com-port输出),输入捕获引脚获得高 - 低转换并捕获另一个值(通过com-port输出),但这些事件都没有启动DMA请求。





回帖(1)

杨平

2018-9-4 11:23:51
DMA已正确初始化。问题是:缓冲区阵列没有初始化到任何SRAM存储区,所以当DMA试图通过AHB到达该存储器时(不可能)DMA崩溃并出现错误并设置TEI_flag(传输错误中断)。

使这项工作更容易的方式(显然这不是正确的方法,但为了熟人的目的,它的工作原理)

#define Destination_Address ((unsigned int)0x30000000)
  DMA1_Stream0->M0AR = Destination_Address;
0x30000000 -> 是SRAM1内存的边界

你需要先启用SRAM1  2  3:
static void my_SRAM_init(void) {
  // activate SRAM123
  RCC->AHB2ENR |= (0x7 << 29);   
}
你可以通过以下方式到达该地区

  uint32_t *Ptr_Dest = (uint32_t *)Destination_Address;
  printf("buffer: %lu %lu rn", *Ptr_Dest, *(Ptr_Dest + 1));
对于那些不起作用或一些UB发生的原因:

缓存(启用缓存可能会损坏数据)
您的地址应与PSIZE和MSIZE对齐
示例:如果您的MSIZE和PSIZE是32位地址,则必须以0x4结尾
1 举报

更多回帖

发帖
×
20
完善资料,
赚取积分