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,这个函数中断为什么无法跳出中断?
谢谢大家,希望大家帮小弟看看呀、
看看先{:lol:} 怎么没有人额 到底是进不了中断呢,还是出不来中断呢,你写的太乱了吧
#pragma vector=ADC_VECTOR
__interrupt void ADC12(void)
这个函数少了一个}括号,你看你的原程序是不是也少呢 Pupil 发表于 2012-7-13 09:31 static/image/common/back.gif
到底是进不了中断呢,还是出不来中断呢,你写的太乱了吧
无法跳出中断, 程序中有那个括号。 跳不出来应该是又有了中断请求,你在进入中断后先关掉中断再做别的任试试 ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下 中断的最后一句可能是引起了下一次的中断请求,所以出不来了 你删除最后一句看单次转换能不能成功 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;
}
}
Pupil 发表于 2012-7-13 11:55 static/image/common/back.gif
ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下 ...
想请问你一下,
ADC12IE和 ENC我觉得关闭任何一个,ADC的中断应该都会关闭。请问是不是我说的那样呀?两者有什么区别? Pupil 发表于 2012-7-13 11:55 static/image/common/back.gif
ADC12IFG &=~ BIT0;
这句写在中断第一行,手册是说自动清零,但是好像还要手动清零一下 ...
我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
如果不清IFG是不是一直在中断里面出不来? 定时器中断采样和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
请问是什么原因啊? abcfanyuan 发表于 2012-7-13 15:11 static/image/common/back.gif
我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
...
我没调过ad12,只调过sd16的,当时我不清IFG出不来,
关掉ECN应该不会清IFG,你关ad12时,不要关AD12IE,是关ENC,第一个只是关了
中断请求,并没有关掉转换,有可能转换在这断时间内还会写有新值,只是没有请求中断罢了。 abcfanyuan 发表于 2012-7-13 15:11 static/image/common/back.gif
我试了一下,不清中断标志,我上面的额那个也可以用呀。
这是什么情况?是不是ENC关了,IFG就自动清了?
...
手册说IFG在读取MEM的数据后会自动清零的,可能是自动请零了 楼主,那个采样电路是不是把采样的点用一根线连到p6.0口就可以了,不用接其他的IO口了? 竹叶听筝 发表于 2012-7-14 11:20 static/image/common/back.gif
楼主,那个采样电路是不是把采样的点用一根线连到p6.0口就可以了,不用接其他的IO口了? ...
恩恩,开发板上的。直接采样电位器
页:
[1]