This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
刚刚学习msp430,对于一些实现运到了对我来说很奇怪的问题。
我想实现每隔一段时间后,ADC12在单通道连续采样情况下进行采样,取均值操作。
用了两种方法:
1.使用Timer进行定时,在定时一段时间后重复开启和关闭ADC12(可以运行,mainnousepmw.c)
2.采用ADC12的Timer进行控制的方法,即SHP=1的方法
问题:程序卡死在某个位置,由于没有调制器,无法定位是在哪边出了问题
下面是我的代码
#include "msp430x14x.h"
#include "Config.h"
float MEAN = 1.0;
float MAX = -1.0;
uchar IDX = 0;
uchar MAXIDX = 0;
uchar FINISH = 0;
uchar ADCBUSY = 1;
uint TEMP = 0;
uchar CNT = 0; // for test
void port_init()
{
P6DIR |= 0xfe; // for test
P6OUT &= ~(0xfe);
}
void TIMERA_Init(void) //continue, to 0x007E create interrupt
{
TACTL |= TASSEL1 + TACLR + ID0 + ID1 + MC_1 + TAIE; //SMCLK / 8 as clock, up mode(to TACCR0), create interrupt
TACCR0 = 0xffff; // for test
}
//TIMERA interrupt, has interrupt type
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A(void)
{
//????
switch(TAIV) //interrupt type
{
case 2: break;
case 4: break;
case 10:
TACTL = 0x00; //close Timer A
ADC12CTL0 &= ~(ADC12SC + ENC);
ADCBUSY = 0;
break; //set the ADC to finish
}
}
void adc_init()
{
P6SEL &= 0x01; //select P6.0 as the adc input
ADC12CTL0 |= ADC12ON + SHT0_15 + REF2_5V + REFON + MSC; //for test, add multiply sample and conversion
ADC12CTL1 |= ADC12SSEL1 + ADC12SSEL0 + CONSEQ_2 + SHP + CSTARTADD_0; //SMCLK as clock, single channel continue convert mode,
ADC12MCTL0 = SREF0 + INCH_0 + EOS; //ref select, channel 0 select
ADC12IE |= 0x01; //interrupt allow
}
//ADC interrupt
#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(void)
{
switch(ADC12IV)
{
case ADC12IV_ADC12IFG0:
MEAN = MEAN + ADC12MEM0;
CNT = CNT + 1;
//P6OUT = ~(0x80);
break;
case ADC12IV_ADC12OVIFG:
//P6OUT = ~(0x10);
break;
case ADC12IV_ADC12TOVIFG:
//P6OUT = ~(0x20);
break;
default:
break;
}
}
void main()
{
WDT_Init();
Clock_Init();
port_init();
adc_init();
_EINT();
delay_ms(5000); // for test
while(1) {
while(!FINISH) {
delay_ms(500); // for test
CNT = 1;
MEAN = 0.0;
ADC12CTL0 |= ADC12SC + ENC; //Start conversion
//start the timer here
ADCBUSY = 1;
TIMERA_Init();// don't set the timer in running
//wait for the timer A interrupt to change the ADCBUSY
//meanwhile close the Timer A
while(ADCBUSY){};
MEAN = MEAN / CNT;
if (MEAN > MAX) {
MAX = MEAN;
MAXIDX = IDX;
}
//change the Q channel control
IDX = IDX + 1;
// for test 0x04
if (IDX == 0x04) {
FINISH = 1;
P1OUT = MAXIDX;
//P6OUT = ~(IDX << 1);
P6OUT &= ~(MAXIDX << 4);
break;
}
P6OUT = ~(IDX << 1);
}
//save power here
}
}
对于需要实现的功能是否有其他的解决方案,或者说上述两个方案的问题是否有解决的方法,不胜感激。
附件中是我写的方案1的代码,谢谢!
/* * main.c * * Created on: 2016.7.10 * Author: Jayson */ #include "msp430x14x.h" #include "Config.h" float MEAN = 1.0; float MAX = -1.0; uchar IDX = 0; uchar MAXIDX = 0; uchar FINISH = 0; uchar ADCBUSY = 1; uint TEMP = 0; uchar CNT = 0; // for test void port_init() { P6DIR |= 0xfe; // for test P6OUT &= ~(0xfe); } void TIMERA_Init(void) //continue, to 0x007E create interrupt { TACTL |= TASSEL1 + TACLR + ID0 + ID1 + MC_1 + TAIE; //SMCLK / 8 as clock, up mode(to TACCR0), create interrupt TACCR0 = 0xffff; // for test } //TIMERA interrupt, has interrupt type #pragma vector=TIMERA1_VECTOR __interrupt void Timer_A(void) { //???? switch(TAIV) //interrupt type { case 2: break; case 4: break; case 10: TACTL = 0x00; //close Timer A P6OUT = ~(0x40); ADC12CTL0 &= ~(ADC12SC + ENC); ADCBUSY = 0; break; //set the ADC to finish } } void adc_init() { P6SEL &= 0x01; //select P6.0 as the adc input ADC12CTL0 |= ADC12ON + SHT0_15 + REF2_5V + REFON + MSC; //for test, add multiply sample and conversion ADC12CTL1 |= ADC12SSEL1 + ADC12SSEL0 + CONSEQ_2 + SHP + CSTARTADD_0; //SMCLK as clock, single channel continue convert mode, ADC12MCTL0 = SREF0 + INCH_0 + EOS; //ref select, channel 0 select ADC12IE |= 0x01; //interrupt allow ADC12CTL0 |= ENC; //adc enable } //ADC interrupt #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR(void) { _EINT(); switch(ADC12IV) { case ADC12IV_ADC12IFG0: MEAN = MEAN + ADC12MEM0; CNT = CNT + 1; //P6OUT = ~(0x80); break; case ADC12IV_ADC12OVIFG: P6OUT = ~(0x10); break; case ADC12IV_ADC12TOVIFG: P6OUT = ~(0x20); break; default: break; } } void main() { WDT_Init(); Clock_Init(); port_init(); adc_init(); _EINT(); delay_ms(5000); // for test while(1) { while(!FINISH) { delay_ms(500); // for test CNT = 1; MEAN = 0.0; ADC12CTL0 |= ADC12SC + ENC; //Start conversion //start the timer here ADCBUSY = 1; TIMERA_Init();// don't set the timer in running P6OUT = ~(0x10); //wait for the timer A interrupt to change the ADCBUSY //meanwhile close the Timer A while(ADCBUSY){}; ADC12CTL0 &= ~(ADC12SC + ENC); //stop conversion //change the Q channel control IDX = IDX + 1; // for test 0x04 if (IDX == 0x04) { FINISH = 1; P6OUT &= ~(MAXIDX << 4); break; } P6OUT = ~(IDX << 1); } //save power here } }