abcfanyuan 发表于 2012-7-13 01:43:13

msp430f149,adc无法跳出中断,定时器和adc中断采样值不等?...

本帖最后由 abcfanyuan 于 2012-7-13 15:16 编辑

程序如下:
#include <msp430x14x.h>
#include "ADC.h"
#define uchar unsigned char
uchardis_code = {0x3f,0x06,0x5b,0x4f,0x66,//段码表   
                     // 0    1    2    3    4      对应内容   
                           0x6D,0x7D,0x07,0x7F,0x6F,0x80,0xFF};   
                     // 5    6    7    8    9   .
uchar ge,shi,bai,qian;
uchar s,q;
void Display(uchar wei ,uchar dat);
int k=0,j;
unsigned int count=0;


//--------------------------------------------------------------------------------

void delay_ms(unsigned long ms)       // 延时毫秒@12M,ms最大值255   
{   
    uchar i;
   
    while(ms--)   
      for(i = 0; i < 124; i++);   
}

void Ds_num(int g)
{
    int n;
    n=g;
    for(uchar i=0;i<3;i++)
    {
      qian=n/1000;
      Display(4,qian);
      
      
      bai=n/100%10;
      Display(3,bai);
   
      
      shi=n/10%10;
      Display(2,shi);
      
      ge=n%10;
      Display(1,ge);
    }
}

void Display(uchar wei ,uchar dat)
{

      switch(wei)
      {   
            case 4:
                P4OUT = dis_code;//dis_code; // 取个位的段码
                P3OUT &= ~BIT0;      // 开第一个显示(P3.0口控制个位数码管)   
                delay_ms(5); // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT0;
                P4OUT =0;
                break;
            case 3:
                P4OUT = dis_code; // 取个位的段码
                P3OUT &= ~BIT1;      // 开第二个显示(P3.1口控制个位数码管)   
               delay_ms(5);         // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT1;
                P4OUT =0;
                break;
            case 2:
                P4OUT = dis_code; // 取个位的段码         
                P3OUT &= ~BIT2;      // 开第三个显示(P3.2口控制个位数码管)   
                delay_ms(5);          // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT2;
                P4OUT =0;
                break;
            case 1:
                P4OUT = dis_code; // 取个位的段码
                P3OUT &= ~BIT3;      // 开第四个显示(P3.3口控制个位数码管)   
                delay_ms(5);         // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT3;
                P4OUT =0;
                break;

            default:
                break;
       }

}
//---------------------------------------------------------------------

void Init_ADCScan(void)
{
//ADC12初始化----------------------
   //单通道,单次采样模式
   P6SEL |= BIT0;//使能A/D通道 A0
   ADC12CTL0 &=~(ENC);
   ADC12CTL0 = ADC12ON + SHT0_2+REFON+REF2_5V;    //开ADC12内核和设置SHIT0=2(N=4)
   ADC12CTL1 |= SHP;               //SAMPCON信号选择为采样定时器输出
   ADC12CTL1 |= CSTARTADD_0;         //定义单次转换地址
   ADC12MCTL0 = 0x10;
// ADC12MCTL0 = SREF_2;             // 使用外部参考电压 Vr+ = VeREF+
   ADC12IE|=BIT0;
   ADC12CTL0 |= ENC;               //ADC转换允许
   ADC12CTL0 |= ADC12SC;
}
void Init_CLK(void)
{
   unsigned int iq0;
   BCSCTL1&=~0X00;      //打开XT2振荡器
   do
   {
      IFG1 &= ~OFIFG;   // 清除振荡器失效标志
      for (iq0 = 0xFF; iq0 > 0; iq0--); // 延时,等待XT2起振
    }
    while ((IFG1 & OFIFG) != 0);    // 判断XT2是否起振
    BCSCTL2 =SELM_2+SELS;   //选择MCLK、SMCLK为XT2
    _EINT();            //打开全局中断控制,若不需要打开,可以屏蔽本句
}





void main(void)
{
   
    // 停止WDT
    WDTCTL = WDTPW + WDTHOLD;
    Init_CLK();
    Init_ADCScan();
    //_EINT();
   // 将P4设置为I/O口
    P4SEL = 0x00;
    // 将P4设置为输出方向
    P4DIR = 0xFF;
    // 将P4口输出全高
    P4OUT = 0xFF;
    // 将P3设置为I/O口
    P3SEL = 0x00;
    // 将P3设置为输出方向
    P3DIR |= 0x0F;
    // 关所有数码管
    P3OUT |= 0x0F;   
   
    //ceshi
    P1DIR=0;
    P1SEL=1;
    //P1SEL=0;
    P1DIR=BIT7;
    for(;;)
    {
      
      Ds_num(count);
      
      
    }
   
    }

#pragma vector=ADC_VECTOR
__interrupt void ADC12(void)
{
uchar i;
if(P1OUT&BIT7) P1OUT &=~(BIT7);
else P1OUT |=BIT7;
//while((ADC12IFG & BIT0)==0);
s=ADC12MEM0;
j++;
if(j>20)
{
   //count=0;
   ADC12CTL0 &= ~(ENC);
   j=0;
   for(i=0;i<20;i++)
      {
      count+=s;      
      }
      count=count/20;
    ADC12IFG &=~ BIT0;

}
    ADC12CTL0 |= ADC12SC+ENC;
程序是按照书上和网上的一些程序,自己配置的。用数码管显示采样的电压值。但有时候是无法跳入中断,有时候是无法进入中断,。
现在有如下几个问题:
1,ADC12CTL0 &= ~(ENC);在中断函数中能不能关掉ADC中断?
2,ADC12IFG &=~ BIT0;中断标志位不是软件复位么?这里需要不?
3,ADC12IE&=~BIT0;如果写在中断函数中是否可以关掉ADC中断?
4,这个函数中断为什么无法跳出中断?

谢谢大家,希望大家帮小弟看看呀、






TXJ_yigo 发表于 2012-7-13 08:31:08

看看先{:lol:}

abcfanyuan 发表于 2012-7-13 09:07:46

怎么没有人额

Pupil 发表于 2012-7-13 09:31:32

到底是进不了中断呢,还是出不来中断呢,你写的太乱了吧

Pupil 发表于 2012-7-13 09:33:03

#pragma vector=ADC_VECTOR
__interrupt void ADC12(void)
这个函数少了一个}括号,你看你的原程序是不是也少呢

abcfanyuan 发表于 2012-7-13 10:15:19

Pupil 发表于 2012-7-13 09:31 static/image/common/back.gif
到底是进不了中断呢,还是出不来中断呢,你写的太乱了吧

无法跳出中断, 程序中有那个括号。

Pupil 发表于 2012-7-13 11:53:56

跳不出来应该是又有了中断请求,你在进入中断后先关掉中断再做别的任试试

Pupil 发表于 2012-7-13 11:55:37

ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下

Pupil 发表于 2012-7-13 11:57:52

中断的最后一句可能是引起了下一次的中断请求,所以出不来了

Pupil 发表于 2012-7-13 11:58:18

你删除最后一句看单次转换能不能成功

abcfanyuan 发表于 2012-7-13 14:49:54

Pupil 发表于 2012-7-13 11:58 static/image/common/back.gif
你删除最后一句看单次转换能不能成功

真的非常感谢,应该是你说的那个问题。我改为了如下可以用了
#include <msp430x16x.h>
#include "ADC.h"
#define uchar unsigned char
#defineuintunsigned int
uchardis_code = {0x3f,0x06,0x5b,0x4f,0x66,//段码表   
                     // 0    1    2    3    4      对应内容   
                           0x6D,0x7D,0x07,0x7F,0x6F,0x80,0xFF};   
                     // 5    6    7    8    9   .
uchar ge,shi,bai,qian;
unsignedints;
void Display(uchar wei ,uchar dat);
int k=0,j;
unsigned long int count=0;


//--------------------------------------------------------------------------------

void delay_ms(unsigned long ms)       // 延时毫秒@12M,ms最大值255   
{   
    uchar i;
   
    while(ms--)   
      for(i = 0; i < 124; i++);   
}

void Ds_num(int g)
{
    int n;
    n=g;
    for(uchar i=0;i<3;i++)
    {
      qian=n/1000;
      Display(4,qian);
      
      
      bai=n/100%10;
      Display(3,bai);
   
      
      shi=n/10%10;
      Display(2,shi);
      
      ge=n%10;
      Display(1,ge);
    }
}

void Display(uchar wei ,uchar dat)
{

      switch(wei)
      {   
            case 4:
                P4OUT = dis_code;//dis_code; // 取个位的段码
                P3OUT &= ~BIT0;      // 开第一个显示(P3.0口控制个位数码管)   
                delay_ms(5); // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT0;
                P4OUT =0;
                break;
            case 3:
                P4OUT = dis_code; // 取个位的段码
                P3OUT &= ~BIT1;      // 开第二个显示(P3.1口控制个位数码管)   
               delay_ms(5);         // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT1;
                P4OUT =0;
                break;
            case 2:
                P4OUT = dis_code; // 取个位的段码         
                P3OUT &= ~BIT2;      // 开第三个显示(P3.2口控制个位数码管)   
                delay_ms(5);          // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT2;
                P4OUT =0;
                break;
            case 1:
                P4OUT = dis_code; // 取个位的段码
                P3OUT &= ~BIT3;      // 开第四个显示(P3.3口控制个位数码管)   
                delay_ms(5);         // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT3;
                P4OUT =0;
                break;

            default:
                break;
       }

}
//---------------------------------------------------------------------

void Init_ADCScan(void)
{
//ADC12初始化----------------------
   //单通道,单次采样模式
   P6SEL |= BIT0;//使能A/D通道 A0
   ADC12CTL0 &=~(ENC);
   ADC12CTL0 = ADC12ON + SHT0_2+REFON+REF2_5V;    //开ADC12内核和设置SHIT0=2(N=4)
   ADC12CTL1 |= SHP+CONSEQ_2;               //SAMPCON信号选择为采样定时器输出
   ADC12CTL1 |= CSTARTADD_0;         //定义单次转换地址
   ADC12MCTL0 = 0x10;
// ADC12MCTL0 = SREF_1;             // 使用内部参考电压 2.5
   ADC12IE|=BIT0;
   ADC12CTL0 |= ENC;               //ADC转换允许
   ADC12CTL0 |= ADC12SC;
}
void Init_CLK(void)
{
   unsigned int iq0;
   BCSCTL1&=~0X00;      //打开XT2振荡器
   do
   {
      IFG1 &= ~OFIFG;   // 清除振荡器失效标志
      for (iq0 = 0xFF; iq0 > 0; iq0--); // 延时,等待XT2起振
    }
    while ((IFG1 & OFIFG) != 0);    // 判断XT2是否起振
    BCSCTL2 =SELM_2+SELS;   //选择MCLK、SMCLK为XT2
    _EINT();            //打开全局中断控制,若不需要打开,可以屏蔽本句
}





void main(void)
{
   
    // 停止WDT
    WDTCTL = WDTPW + WDTHOLD;
    Init_CLK();
    Init_ADCScan();
    //_EINT();
   // 将P4设置为I/O口
    P4SEL = 0x00;
    // 将P4设置为输出方向
    P4DIR = 0xFF;
    // 将P4口输出全高
    P4OUT = 0xFF;
    // 将P3设置为I/O口
    P3SEL = 0x00;
    // 将P3设置为输出方向
    P3DIR |= 0x0F;
    // 关所有数码管
    P3OUT |= 0x0F;   
   
    //ceshi
    P1DIR=0;
    P1SEL=1;
    //P1SEL=0;
    P1DIR=BIT7;
    for(;;)
    {      
      Ds_num(count);
      ADC12CTL0 |= ADC12SC+ENC;   
    }
   
    }

#pragma vector=ADC_VECTOR
__interrupt void ADC12(void)
{
uchar i;
ADC12IFG |= BIT0;
ADC12CTL0 &= ~(ENC);
if(P1OUT&BIT7) P1OUT &=~(BIT7);
else P1OUT |=BIT7;
s=ADC12MEM0;
j++;
if(j>20)
{
   count=0;
   j=0;
   for(i=0;i<20;i++)
      {
      count+=s;      
      }
      count=count/20;
}
}





abcfanyuan 发表于 2012-7-13 14:52:47

Pupil 发表于 2012-7-13 11:55 static/image/common/back.gif
ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下 ...

想请问你一下,
ADC12IE和 ENC我觉得关闭任何一个,ADC的中断应该都会关闭。请问是不是我说的那样呀?两者有什么区别?

abcfanyuan 发表于 2012-7-13 15:11:17

Pupil 发表于 2012-7-13 11:55 static/image/common/back.gif
ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下 ...

我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
如果不清IFG是不是一直在中断里面出不来?

abcfanyuan 发表于 2012-7-13 15:19:56

定时器中断采样和ADC中断在网友热心的帮助下终于调节好了。
定时器采样的如下:
#include <msp430x14x.h>
#include "ADC.h"
#define FILTER_TIME 2000   //滤波时间
#define uchar unsigned char
#define uintunsigned int
uchardis_code = {0x3f,0x06,0x5b,0x4f,0x66,//段码表   
                     // 0    1    2    3    4      对应内容   
                           0x6D,0x7D,0x07,0x7F,0x6F,0x80,0xFF};   
                     // 5    6    7    8    9   .
uchar ge,shi,bai,qian;
uint s,q;
void Display(uchar wei ,uchar dat);
int k=0,j=0;
unsigned long int count=0;


//--------------------------------------------------------------------------------

void delay_ms(unsigned long ms)       // 延时毫秒@12M,ms最大值255   
{   
    uchar i;
   
    while(ms--)   
      for(i = 0; i < 124; i++);   
}

void Ds_num(int g)
{
    int n;
    n=g;
    for(uchar i=0;i<10;i++)
    {
      qian=n/1000;
      Display(4,qian);
      
      
      bai=n/100%10;
      Display(3,bai);
   
      
      shi=n/10%10;
      Display(2,shi);
      
      ge=n%10;
      Display(1,ge);
    }
   
}

void Display(uchar wei ,uchar dat)
{

      switch(wei)
      {   
            case 4:
                P4OUT = dis_code;//dis_code; // 取个位的段码
                P3OUT &= ~BIT0;      // 开第一个显示(P3.0口控制个位数码管)   
                delay_ms(5); // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT0;
                P4OUT =0;
                break;
            case 3:
                P4OUT = dis_code; // 取个位的段码
                P3OUT &= ~BIT1;      // 开第二个显示(P3.1口控制个位数码管)   
               delay_ms(5);         // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT1;
                P4OUT =0;
                break;
            case 2:
                P4OUT = dis_code; // 取个位的段码         
                P3OUT &= ~BIT2;      // 开第三个显示(P3.2口控制个位数码管)   
                delay_ms(5);          // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT2;
                P4OUT =0;
                break;
            case 1:
                P4OUT = dis_code; // 取个位的段码
                P3OUT &= ~BIT3;      // 开第四个显示(P3.3口控制个位数码管)   
                delay_ms(5);         // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT3;
                P4OUT =0;
                break;

            default:
                break;
       }

}
//---------------------------------------------------------------------

void Init_ADCScan(void)
{
//ADC12初始化----------------------
   //单通道,单次采样模式
   P6SEL |= BIT0;//使能A/D通道 A0
   ADC12CTL0 &=~(ENC);
   ADC12CTL0 = ADC12ON + SHT0_2+REFON+REF2_5V;    //开ADC12内核和设置SHIT0=2(N=4)
   ADC12CTL1 |= SHP;               //SAMPCON信号选择为采样定时器输出
   ADC12CTL1 |= CSTARTADD_0;         //定义单次转换地址
   ADC12MCTL0 |= INCH_0;
   ADC12MCTL0 = SREF_1;             // 使用内部参考电压 2.5v
   ADC12CTL0 |= ENC;               //ADC转换允许

}
void Init_CLK(void)
{
   unsigned int iq0;
   BCSCTL1&=~0X00;      //打开XT2振荡器
   do
   {
      IFG1 &= ~OFIFG;   // 清除振荡器失效标志
      for (iq0 = 0xFF; iq0 > 0; iq0--); // 延时,等待XT2起振
    }
    while ((IFG1 & OFIFG) != 0);    // 判断XT2是否起振
    BCSCTL2 =SELM_2+SELS;   //选择MCLK、SMCLK为XT2
    _EINT();            //打开全局中断控制,若不需要打开,可以屏蔽本句
}


//Timer_A初始化--------------------
void Init_TimerA()
{
   TACTL = TASSEL_1+MC_1+TACLR;         //timerA CLK="ACLK",增计数模式   
   CCR0 =1000;
   CCTL0 = CCIE;
}

void main(void)
{
    // 停止WDT
    WDTCTL = WDTPW + WDTHOLD;
    Init_CLK();
    Init_TimerA();
    Init_ADCScan();
    //_EINT();
   // 将P4设置为I/O口
    P4SEL = 0x00;
    // 将P4设置为输出方向
    P4DIR = 0xFF;
    // 将P4口输出全高
    P4OUT = 0xFF;
    // 将P3设置为I/O口
    P3SEL = 0x00;
    // 将P3设置为输出方向
    P3DIR |= 0x0F;
    // 关所有数码管
    P3OUT |= 0x0F;   
   
    //ceshi
    P1DIR=0;
    P1SEL=1;
    //P1SEL=0;
    P1DIR=BIT7;
    for(;;)
    {
   
      Ds_num(count);
      
    }
    }
   


#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A(void)
{
uchar i;
if(P1OUT&BIT7) P1OUT &=~(BIT7);
else P1OUT |=BIT7;
   // ADC12CTL0 &= ~(ENC);
    _NOP();      
   s= ADC12MEM0; //读取结果
   j++;
   //ADC12CTL0 |= ADC12SC+ENC; // 开始转换
   ADC12CTL0 |= ADC12SC;
    _NOP();
    if(j==20)
    {
    j=0;
    count=0;
    for(i=0;i<20;i++)
    {
       count+=s;   
    }
   count=count/20;
    }
}



定时器采样的在11楼。
都是采样一个滑动变阻器,电压值没有变动。采样20次求平均

ADC中断获得的结果是1992
定时器获得的是1982

请问是什么原因啊?

Pupil 发表于 2012-7-14 08:07:53

abcfanyuan 发表于 2012-7-13 15:11 static/image/common/back.gif
我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
...

我没调过ad12,只调过sd16的,当时我不清IFG出不来,
关掉ECN应该不会清IFG,你关ad12时,不要关AD12IE,是关ENC,第一个只是关了
中断请求,并没有关掉转换,有可能转换在这断时间内还会写有新值,只是没有请求中断罢了。

Pupil 发表于 2012-7-14 08:09:55

abcfanyuan 发表于 2012-7-13 15:11 static/image/common/back.gif
我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
...

手册说IFG在读取MEM的数据后会自动清零的,可能是自动请零了

竹叶听筝 发表于 2012-7-14 11:20:00

楼主,那个采样电路是不是把采样的点用一根线连到p6.0口就可以了,不用接其他的IO口了?

abcfanyuan 发表于 2012-7-14 21:20:43

竹叶听筝 发表于 2012-7-14 11:20 static/image/common/back.gif
楼主,那个采样电路是不是把采样的点用一根线连到p6.0口就可以了,不用接其他的IO口了? ...

恩恩,开发板上的。直接采样电位器
页: [1]
查看完整版本: msp430f149,adc无法跳出中断,定时器和adc中断采样值不等?...