打印
[技术问答]

用PWM触发PDMA采集端口数据失败

[复制链接]
1586|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
taowenyang|  楼主 | 2015-5-4 14:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实验板Nano130
我用PWM0的0通道模拟时钟脉冲给外部存储设备,然后用2通道捕获0通道的上升沿功能触发PDMA采集端口GPIOA的数据,
PDMA中断发生时状态字是PDMA_ISR_TABORT(PDMA Read/Write Target Abort Interrupt Status Flag),采集失败,不知道为什么?
但采集PWM捕获的数据时是正常的。PDMA不能使用这种方式采集端口的数据吗?使用PDMA怎样才能采集端口的输入数据。
代码如下:

// PWM数据
void PWMn_Init(void)
{
S_DRVPWM_TIME_DATA_T sPt;
STR_PDMA_T sPDMA;
const uint8_t u8Timer = 0;
const uint8_t nCapTimer = 2;
//static uint32_t mm = 5;

PWM_Init(0); // 使用通道0,输出波形
PWM_Init(2); // 使用通道2,捕获

GCR->PA_H_MFP = (GCR->PA_H_MFP & ~(PA12_MFP_MASK | PA14_MFP_MASK)) | PA12_MFP_PWM0_CH0 |  PA14_MFP_PWM0_CH2;

// clock = 12MHz, 50% duty ratio, Freq 3MHz
// CN = clock / freq - 1  PWM 频率 = PWMxy_CLK/(prescale+1)*(clock divider)/(CN+1);
sPt.u8Mode = PWM_CTL_CHMOD_AUTO_RELOAD;
sPt.u8PreScale = 1;  // actually 1 + 1
sPt.u8Div = PWM_CLKSEL_CLKSEL_DIV1;
sPt.u32Cn = 3;  // 3MHz
sPt.u16Cm = 1; // 50% duty ratio
sPt.u8Inv = 0;   // Disable inverter

PWM_SetClk(u8Timer, &sPt);
PWM_ConfigOutput(u8Timer, 1); // Enable ch 0 output
//PWM_Enable(u8Timer);          // Enable PWM ch 0
//PWM_EnableInt(u8Timer);

// Configure capture channel
// PDMA Init
PDMA_Init(); // Use PDMA ch1 here.
PDMA_DISABLE_CH1();
PDMA_EnableChannelClock(PDMAGCR_CSR_CLK1);
PDMA_PWM0_CH2_TO_CH1();

sPDMA.SrcAddr   = (uint32_t)(&GPIOA->PIN);//(uint32_t)&(PWM0->CH2PDMA);//(uint32_t)(&GPIOA->PIN);
sPDMA.DestAddr   = (uint32_t)DestArray;
sPDMA.TransWidth  = PDMA_CSR_APB_TWS_8BIT;     // Change to 32 bit if cascade mode is enabled
sPDMA.Mode   = PDMA_CSR_IP2MEM;
sPDMA.SrcCtrl   = PDMA_CSR_SAD_FIX;
sPDMA.DestCtrl   = PDMA_CSR_DAD_INC;
sPDMA.ByteCnt        = PDMA_BUF_LENGTH;
sPDMA.IsTimeOutEnable = 0;
PDMA_Open(PDMA1, &sPDMA);
PDMA_EnableInt(PDMA1, PDMA_IER_TD); // 开启中断
//PDMA_CHEnableTransfer(PDMA1);
// PWM timer property for capture channel
sPt.u8Mode = PWM_CTL_CHMOD_AUTO_RELOAD;
sPt.u8PreScale = 1;  // actually 1 + 1
sPt.u8Div = PWM_CLKSEL_CLKSEL_DIV1;
sPt.u32Cn = 0xFFFF;  // Max CN in non-cascade mode
sPt.u16Cm = 0;    // don't care in capture function
sPt.u8Inv = 0;  // don't care in capture function
PWM_SetClk(nCapTimer, &sPt);
PWM_SetCaptureAttribute(nCapTimer, 0, 0, PWM_CAPCTL_CAPRELOADREN);// 上升沿 // PWM_CAPCTL_CAPRELOADFEN
PWM_ConfigCaptureIntput(nCapTimer, 1); // Enable PWM ch 2 input function
PWM_EnablePdma(nCapTimer, PWM_CAPCTL_CHRFORDER_R, PWM_CAPCTL_PDMACAPMOD_CRL); // Configure PDMA function
//PWM_CaptureEnable(nCapTimer); // Enable PWM ch 2

//while(pdma_done == 0); // Wait for PDMA capture complete

// STOP
//PWM_SetCounter(u8Timer, 0, 0);
//PWM_Disable(u8Timer);
//PWM_SetCounter(nCapTimer, 0, 0);
//PWM_CaptureDisable(nCapTimer);
//PDMA_DeInit();
}

void PWMn_Disable(void)
{
PWM_Disable(0);
PWM_CaptureDisable(2);
}


// DMA开始传输
void PWMn_Enable(void)
{
PDMA_CHEnableTransfer(PDMA1);
PWM_CaptureEnable(2); // Enable PWM ch 2
PWM_Enable(0);        // Enable PWM ch 0
}


void PDMA_IRQHandler(void)
{
uint32_t u32ISR;
u32ISR = PDMA1->ISR;
if(u32ISR & 0x01)    /* Check Target Abort INT and clear */
{
  PDMA1->ISR = 0x01;
  //printf("\tTransfer Target Abort !\r\n");
}
else if(u32ISR & PDMA_ISR_TD)   
{       /* Transfer Done INT and clear */
  PDMA1->ISR = PDMA1->ISR;
  //UART_DisablePDMA(UART1);
  //printf("\tTransfer Done!\r\n");
  
  //IsTestOver = TRUE;
}
else if(u32ISR & 0x04)
{       /* Wrap around Transfer complete and clear */
  PDMA1->ISR = 0x04;
  //printf("\tWrap around Transfer complete!\r\n");
}
else if(u32ISR & 0x10)
{       /* Wrap around Transfer Half and clear */
  PDMA1->ISR = 0x10;
  //printf("\tWrap around Transfer Half!\r\n");
}
else if(u32ISR & 0x40)
{       /* Transfer Timeout INT and clear */
  PDMA1->ISR = 0x40;
  //printf("\tTransfer Timeout!\r\n");
}

PWMn_Disable();
}


沙发
quray1985| | 2015-5-6 12:40 | 只看该作者
没用过这个功能,帮你顶到前面去

使用特权

评论回复
板凳
mintspring| | 2015-5-8 12:54 | 只看该作者
看了半天头大了,不知道楼主要做什么的感觉。楼主可以换个清晰的思路重新实现你要的功能。

使用特权

评论回复
地板
734774645| | 2015-5-10 07:46 | 只看该作者
你分成两个做看看行不行

使用特权

评论回复
5
taowenyang|  楼主 | 2015-5-15 09:53 | 只看该作者
我把摄像头模块连接到端口上,从摄像头模块中读取数据到内存时,需要一个时钟信号模拟RW引脚,这里用PWM模拟,然后触发DMA从端口读进数据到内存,什么时候触发DMA,这里使用的是PWM的捕获功能,每次在PWM的上升沿时,触发DMA,把端口的数据搬进内存。实现这个功能,但出问题了

使用特权

评论回复
6
稳稳の幸福| | 2015-5-16 22:06 | 只看该作者
最后一句出问题了,出啥问题了啊

使用特权

评论回复
7
598330983| | 2015-5-18 22:33 | 只看该作者
功能实现了,但是出问题了,很奇怪。

使用特权

评论回复
8
734774645| | 2015-5-19 11:58 | 只看该作者
void PWMn_Disable(void)
{
PWM_Disable(0);
PWM_CaptureDisable(2);
}

使用特权

评论回复
9
yiyigirl2014| | 2015-5-26 20:45 | 只看该作者
需要配置好DMA通道,把指定的位置要配置对

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

6

帖子

0

粉丝