搜索
bottom↓
回复: 17

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

[复制链接]

出0入0汤圆

发表于 2012-7-13 01:43:13 | 显示全部楼层 |阅读模式
本帖最后由 abcfanyuan 于 2012-7-13 15:16 编辑

程序如下:
#include <msp430x14x.h>
#include "ADC.h"
#define uchar unsigned char
uchar  dis_code[12] = {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[20],q[100];
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[dat];//dis_code[dis_0]; // 取个位的段码  
                P3OUT &= ~BIT0;        // 开第一个显示(P3.0口控制个位数码管)   
                delay_ms(5); // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT0;
                P4OUT =0;
                break;
            case 3:
                P4OUT = dis_code[dat]; // 取个位的段码  
                P3OUT &= ~BIT1;        // 开第二个显示(P3.1口控制个位数码管)   
               delay_ms(5);           // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT1;
                P4OUT =0;
                break;
            case 2:
                P4OUT = dis_code[dat]; // 取个位的段码         
                P3OUT &= ~BIT2;        // 开第三个显示(P3.2口控制个位数码管)   
                delay_ms(5);          // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT2;
                P4OUT =0;
                break;
            case 1:
                P4OUT = dis_code[dat]; // 取个位的段码  
                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[j]=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,这个函数中断为什么无法跳出中断?

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






阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-7-13 08:31:08 | 显示全部楼层
看看先

出0入0汤圆

 楼主| 发表于 2012-7-13 09:07:46 | 显示全部楼层
怎么没有人额

出0入0汤圆

发表于 2012-7-13 09:31:32 | 显示全部楼层
到底是进不了中断呢,还是出不来中断呢,你写的太乱了吧

出0入0汤圆

发表于 2012-7-13 09:33:03 | 显示全部楼层
#pragma vector=ADC_VECTOR
__interrupt void ADC12(void)
这个函数少了一个}括号,你看你的原程序是不是也少呢

出0入0汤圆

 楼主| 发表于 2012-7-13 10:15:19 | 显示全部楼层
Pupil 发表于 2012-7-13 09:31
到底是进不了中断呢,还是出不来中断呢,你写的太乱了吧

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

出0入0汤圆

发表于 2012-7-13 11:53:56 | 显示全部楼层
跳不出来应该是又有了中断请求,你在进入中断后先关掉中断再做别的任试试

出0入0汤圆

发表于 2012-7-13 11:55:37 | 显示全部楼层
ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下

出0入0汤圆

发表于 2012-7-13 11:57:52 | 显示全部楼层
中断的最后一句可能是引起了下一次的中断请求,所以出不来了

出0入0汤圆

发表于 2012-7-13 11:58:18 | 显示全部楼层
你删除最后一句看单次转换能不能成功

出0入0汤圆

 楼主| 发表于 2012-7-13 14:49:54 | 显示全部楼层
Pupil 发表于 2012-7-13 11:58
你删除最后一句看单次转换能不能成功

真的非常感谢,应该是你说的那个问题。我改为了如下可以用了
#include <msp430x16x.h>
#include "ADC.h"
#define uchar unsigned char
#define  uint  unsigned int
uchar  dis_code[12] = {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;
unsigned  int  s[20];
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[dat];//dis_code[dis_0]; // 取个位的段码  
                P3OUT &= ~BIT0;        // 开第一个显示(P3.0口控制个位数码管)   
                delay_ms(5); // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT0;
                P4OUT =0;
                break;
            case 3:
                P4OUT = dis_code[dat]; // 取个位的段码  
                P3OUT &= ~BIT1;        // 开第二个显示(P3.1口控制个位数码管)   
               delay_ms(5);           // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT1;
                P4OUT =0;
                break;
            case 2:
                P4OUT = dis_code[dat]; // 取个位的段码         
                P3OUT &= ~BIT2;        // 开第三个显示(P3.2口控制个位数码管)   
                delay_ms(5);          // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT2;
                P4OUT =0;
                break;
            case 1:
                P4OUT = dis_code[dat]; // 取个位的段码  
                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[j]=ADC12MEM0;
  j++;
  if(j>20)
  {
   count=0;
   j=0;
   for(i=0;i<20;i++)
      {
        count+=s;      
      }
      count=count/20;
  }
  }





出0入0汤圆

 楼主| 发表于 2012-7-13 14:52:47 | 显示全部楼层
Pupil 发表于 2012-7-13 11:55
ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下 ...

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

出0入0汤圆

 楼主| 发表于 2012-7-13 15:11:17 | 显示全部楼层
Pupil 发表于 2012-7-13 11:55
ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下 ...

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

出0入0汤圆

 楼主| 发表于 2012-7-13 15:19:56 | 显示全部楼层
定时器中断采样和ADC中断在网友热心的帮助下终于调节好了。
定时器采样的如下:
#include <msp430x14x.h>
#include "ADC.h"
#define FILTER_TIME 2000   //滤波时间
#define uchar unsigned char
#define uint  unsigned int
uchar  dis_code[12] = {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[20],q[100];
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[dat];//dis_code[dis_0]; // 取个位的段码  
                P3OUT &= ~BIT0;        // 开第一个显示(P3.0口控制个位数码管)   
                delay_ms(5); // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT0;
                P4OUT =0;
                break;
            case 3:
                P4OUT = dis_code[dat]; // 取个位的段码  
                P3OUT &= ~BIT1;        // 开第二个显示(P3.1口控制个位数码管)   
               delay_ms(5);           // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT1;
                P4OUT =0;
                break;
            case 2:
                P4OUT = dis_code[dat]; // 取个位的段码         
                P3OUT &= ~BIT2;        // 开第三个显示(P3.2口控制个位数码管)   
                delay_ms(5);          // 延时nms使四位数码管动态显示时能看清
                P3OUT |= BIT2;
                P4OUT =0;
                break;
            case 1:
                P4OUT = dis_code[dat]; // 取个位的段码  
                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[j]= ADC12MEM0; //读取结果
     j++;  
   //ADC12CTL0 |= ADC12SC+ENC; // 开始转换
   ADC12CTL0 |= ADC12SC;
    _NOP();
    if(j==20)
    {
    j=0;
    count=0;
    for(i=0;i<20;i++)
    {
       count+=s[i];     
    }
     count=count/20;
    }
}



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

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

请问是什么原因啊?

出0入0汤圆

发表于 2012-7-14 08:07:53 | 显示全部楼层
abcfanyuan 发表于 2012-7-13 15:11
我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
...

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

出0入0汤圆

发表于 2012-7-14 08:09:55 | 显示全部楼层
abcfanyuan 发表于 2012-7-13 15:11
我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
...

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

出0入10汤圆

发表于 2012-7-14 11:20:00 | 显示全部楼层
楼主,那个采样电路是不是把采样的点用一根线连到p6.0口就可以了,不用接其他的IO口了?

出0入0汤圆

 楼主| 发表于 2012-7-14 21:20:43 | 显示全部楼层
竹叶听筝 发表于 2012-7-14 11:20
楼主,那个采样电路是不是把采样的点用一根线连到p6.0口就可以了,不用接其他的IO口了? ...

恩恩,开发板上的。直接采样电位器
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-28 06:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表