xtaens 发表于 2014-6-17 09:29:27

msp430f5438A的DMA在code比较少时一切正常,但是当code较大时...

msp430f5438A的DMA在code比较少时一切正常,但是当code较大时,DMA死活不触发,这是怎么回事你?

下面的程序单独测试没有问题,dma数据传输正常,中断正常。

但是把下面的语句放到我的一个code量较大的工程中时,dma死活不工程啊。dma不放到此工程中时,此工程工作一切正常。

当我删除此工程中的大量代码后,dma工作正常了。

现在的现象好像是code量太大,dma不工作了????

难道程序跑飞了?


__no_init static uint16_t DMA_DST_AD0;
__no_init static uint16_t DMA_DST_AD1;
__no_init static uint16_t DMA_DST_AD2;

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

SFRIE1 |= OFIE;      // Enable global oscillator fault flag
__bis_SR_register(GIE);//enable interrupts


//ADC设置
P6SEL |=BIT0 + BIT1 + BIT2;               // Enable VeREF+ & A/D channel A0
ADC12CTL0 = ADC12ON                     // 打开ADC内核
             +ADC12MSC                      // 连续采样
             +ADC12SHT0_2;                  // 保持时间为16个cycles

ADC12CTL1 = ADC12SSEL_2                   // 时钟选择为:MCLK
            +ADC12DIV_4                   // 时钟分频为:4+1=5,即25M/5=5MHz
            +ADC12SHP                     // 采样信号源自采样定时器
            +ADC12CONSEQ_3;               // 序列通道多次采样
ADC12MCTL0 = ADC12INCH_0;               // ref+=AVcc, channel = A0
ADC12MCTL1 = ADC12INCH_1;               // ref+=AVcc, channel = A1
ADC12MCTL2 = ADC12INCH_2+ADC12EOS;      // ref+=AVcc, channel = A2, end seq.

ADC12CTL0 |= ADC12ENC;                  // Enable conversions
ADC12CTL0 |= ADC12SC;                     // Start conversion - software trigger

//DMA0、1、2设置
//触发源选择
DMACTL0 = DMA0TSEL_24      // 通道0 ADC12IFGx triggered
         +DMA1TSEL_24;       // 通道1 ADC12IFGx triggered
DMACTL1 = DMA2TSEL_24;       // 通道2 ADC12IFGx triggered
//公共参数设置
DMACTL4 = DMARMWDIS;         // CPU读写操作时禁止DMA传输

//DMA0通道参数设置
DMA0CTL = 0;               // 寄存器清零
DMA0CTL = DMADT_4            // 单次重复传输模式
         +DMAEN            // 使能DMA
         +DMADSTINCR_3       // 目标地址自增,源地址不变
         +DMAIE;             // 使能DMA传输完成中断
DMA0SZ = 2048;               // DMA0传输大小

//DMA1通道参数设置
DMA1CTL = 0;               // 寄存器清零
DMA1CTL = DMADT_4            // 单次重复传输模式
         +DMAEN            // 使能DMA
         +DMADSTINCR_3       // 目标地址自增,源地址不变
         +DMAIE;             // 使能DMA传输完成中断
DMA1SZ = 2048;               // DMA0传输大小

//DMA2通道参数设置
DMA2CTL = 0;               // 寄存器清零
DMA2CTL = DMADT_4            // 单次重复传输模式
         +DMAEN            // 使能DMA
         +DMADSTINCR_3       // 目标地址自增,源地址不变
         +DMAIE;             // 使能DMA传输完成中断
DMA2SZ = 512;               // DMA0传输大小

__data16_write_addr((uint16_t) &DMA0SA,(uint32_t) &ADC12MEM0);//源地址:ADC12MEM0
__data16_write_addr((uint16_t) &DMA0DA,(uint32_t) &DMA_DST_AD0);//目的地址:DMA_DST[]

__data16_write_addr((uint16_t) &DMA1SA,(uint32_t) &ADC12MEM1);//源地址:ADC12MEM1
__data16_write_addr((uint16_t) &DMA1DA,(uint32_t) &DMA_DST_AD1);//目的地址:DMA_DST[]

__data16_write_addr((uint16_t) &DMA2SA,(uint32_t) &ADC12MEM2);//源地址:ADC12MEM2
__data16_write_addr((uint16_t) &DMA2DA,(uint32_t) &DMA_DST_AD2);//目的地址:DMA_DST[]

while(1)
{
    Open_Beep;
    delay_nms(30);
    Close_Beep;
    delay_nms(100);
}
}

//------------------------------------------------------------------------------
// DMA Interrupt Service Routine
//------------------------------------------------------------------------------
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{
switch(__even_in_range(DMAIV,16))
{
    case 0: break;
    case 2:                                 // DMA0IFG = DMA Channel 0
      Close_Beep;                        // Toggle P1.0
      break;
    case 4:                                 // DMA1IFG = DMA Channel 1
      Close_Beep;                        // Toggle P1.0
      break;
    case 6:                                 // DMA2IFG = DMA Channel 2
      Close_Beep;                        // Toggle P1.0
      break;
    case 8: break;                        // DMA3IFG = DMA Channel 3
    case 10: break;                         // DMA4IFG = DMA Channel 4
    case 12: break;                         // DMA5IFG = DMA Channel 5
    case 14: break;                         // DMA6IFG = DMA Channel 6
    case 16: break;                         // DMA7IFG = DMA Channel 7
    default: break;
}
}


附件:我的调试仿真图,adc的参数都是正确的,数据也是正确的,但是dma就是不触发。我单独测试dma时,adc,dma各个寄存器的参数和把dma程序放到code量较大工程中是一样的。


wind2100 发表于 2014-6-17 09:34:22

方法就是慢慢隐藏直到能工作, 再找你那块程序的问题,DMA 应该是不受CPU 及中断的影响的,反正我试了 PWM 是会受中断的影响,根本不是硬件PWM. 所以能用ARM就用ARM,用起来很顺手.

xtaens 发表于 2014-6-17 09:41:03

wind2100 发表于 2014-6-17 09:34
方法就是慢慢隐藏直到能工作, 再找你那块程序的问题,DMA 应该是不受CPU 及中断的影响的,反正我试了 PWM ...

早就想换arm了,但是板子一大堆,仍不起啊。

两个工程单独测试都没有问题,合在一起,dam不触发,但是其他功能正常,堆栈我设置了10KB,还剩2KB,应该不是堆栈溢出的问题


xtaens 发表于 2014-6-17 18:06:25

wind2100 发表于 2014-6-17 09:34
方法就是慢慢隐藏直到能工作, 再找你那块程序的问题,DMA 应该是不受CPU 及中断的影响的,反正我试了 PWM ...

错误的地方已经找到了。但是不知道为啥会这样?

我在dma初始化前进行过一次AD3的采样,程序如下。我只要将下面的语句屏蔽掉后,dma工作就正常了。

ADC12CTL0 |= ADC12ENC;//使能转换
ADC12CTL0 |= ADC12SC;

for(j=0;j<BatteryBuffer_Lenght;j++)
{
    while(!(ADC12IFG & BIT2))//等待采样结束
    {
      Feed_Dog;      //喂外部狗CAT1023,2013-12-24
    }

    temp = ADC12MEM2;// Move A1 results, IFG is cleared
    Battery=temp;
}

ADC12IFG =0;
ADC12CTL0 &=~ADC12ENC;//停止转换
ADC12CTL0 &=~ADC12SC;

wind2100 发表于 2014-6-18 13:33:22

不会是 Feed_Dog 吧

xtaens 发表于 2014-6-18 14:02:27

wind2100 发表于 2014-6-18 13:33
不会是 Feed_Dog 吧

不是的

好像dma有问题?

xtaens 发表于 2014-6-18 14:05:30

wind2100 发表于 2014-6-18 13:33
不会是 Feed_Dog 吧

在新测试结果:

如果把下面的语句屏蔽掉,则dma工作正常,如果不屏蔽,则dma就死了,永远不中断了。


//uint8_t j=0;
//for(j=0;j<128;j++)
//{
//while(!(ADC12IFG & BIT0))//等待采样结束
//{
//    ;
//}
//DMA_DST_AD0 = ADC12MEM0;// Move A1 results, IFG is cleared
//}



__no_init uint16_t DMA_DST_AD0;

int main(void)
{
WDTCTL = WDTPW+WDTHOLD;                   // Stop WDT

//ADC设置
P6SEL |=BIT0;                           // Enable VeREF+ & A/D channel A0
ADC12CTL0 = ADC12ON                     // 打开ADC内核
             +ADC12MSC                      // 连续采样
             +ADC12SHT0_2;                  // 保持时间为16个cycles

ADC12CTL1 = ADC12SSEL_2                   // 时钟选择为:MCLK
            +ADC12DIV_4                   // 时钟分频为:4+1=5,即25M/5=5MHz
            +ADC12SHP                     // 采样信号源自采样定时器
            +ADC12CONSEQ_2;               // 单通道多次采样
ADC12MCTL0 = ADC12INCH_0+ADC12EOS;      // ref+=AVcc, channel = A0

ADC12CTL0 |= ADC12ENC;                  // Enable conversions
ADC12CTL0 |= ADC12SC;                     // Start conversion - software trigger

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//如果把下面的这些语句屏蔽掉,dma读取ad值正常,但是放开这些语句,即先
//直接读一次ad值后再用dma读,此时dma就永远不触发了,这是怎么回事?
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//uint8_t j=0;
//for(j=0;j<128;j++)
//{
//while(!(ADC12IFG & BIT0))//等待采样结束
//{
//    ;
//}
//DMA_DST_AD0 = ADC12MEM0;// Move A1 results, IFG is cleared
//}

//DMA0设置
//触发源选择
DMACTL0 = DMA0TSEL_24;       // 通道0 ADC12IFGx triggered

//DMA0通道参数设置
DMA0CTL = 0;               // 寄存器清零
DMA0CTL = DMADT_4            // 单次重复传输模式
         +DMAEN            // 使能DMA
         +DMADSTINCR_3       // 目标地址自增,源地址不变
         +DMAIE;             // 使能DMA传输完成中断
DMA0SZ = 2048;               // DMA0传输大小

__data16_write_addr((uint16_t) &DMA0SA,(uint32_t) &ADC12MEM0);//源地址:ADC12MEM0
__data16_write_addr((uint16_t) &DMA0DA,(uint32_t) &DMA_DST_AD0);//目的地址:DMA_DST[]

__bis_SR_register(GIE);//enable interrupts
while(1);
}

//------------------------------------------------------------------------------
// DMA Interrupt Service Routine
//------------------------------------------------------------------------------
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{
switch(__even_in_range(DMAIV,16))
{
    case 0: break;
    case 2:                                 // DMA0IFG = DMA Channel 0
      __no_operation();
      break;
    case 4: break;                        // DMA1IFG = DMA Channel 1
    case 6: break;                        // DMA2IFG = DMA Channel 2
    case 8: break;                        // DMA3IFG = DMA Channel 3
    case 10: break;                         // DMA4IFG = DMA Channel 4
    case 12: break;                         // DMA5IFG = DMA Channel 5
    case 14: break;                         // DMA6IFG = DMA Channel 6
    case 16: break;                         // DMA7IFG = DMA Channel 7
    default: break;
}
}

ringan865 发表于 2014-6-18 15:57:16

看起来像ADC中断标志位出问题了,设断点跟踪一下,可能中断标志位一直没清零,触发不了DMA。

xtaens 发表于 2014-6-19 14:15:09

ringan865 发表于 2014-6-18 15:57
看起来像ADC中断标志位出问题了,设断点跟踪一下,可能中断标志位一直没清零,触发不了DMA。 ...

嗯,我单步都看了dma和adc的寄存器

先读一次adc后ifg标志确实置位了,但是我清除了dma还是不中断{:mad:}
页: [1]
查看完整版本: msp430f5438A的DMA在code比较少时一切正常,但是当code较大时...