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.

MSP430F5172 比较器B 不能动态切换为其他通道输入

Other Parts Discussed in Thread: MSP430F5172

HI

现在我要使用MSP430F5172的比较器B,对4个外部信号电平跟内部的参考电压进行比较判断,单独使用一个通道对外部电平信号进行比较都没有问题,

现在是问题是MCU只有一个比较器B,而我需要对4个外部电平进行判断,所以我想使用时间片来动态切换输入通道,验证了就是不行,输入通道配置为第一个后就不能配置为其他输入通道了,造成根本没办法检测到后面3个通道的输入变化。

我找了好多资料和例子,都是只使用一个输入通道的,如果说硬件上不支持多个通道进行切换,那为什么有CB0 到CB15 多达15个通道???

1.比较器B框图

2.原理图

3.部分代码

// MOTOR1_TOUCH   ---- CB15
// MOTOR2_TOUCH   ---- CB14
// MOTOR3_TOUCH   ---- CB13
// MOTOR4_TOUCH   ---- CB10
volatile uint8_t touched;         //Is the fader currently being touched?
volatile uint8_t index_port;
uint16_t time_count_1ms;

uint16_t time1_bak;
uint16_t time2_bak;
uint16_t time3_bak;
uint16_t time4_bak;

// Setup ComparatorB
void initCompare(void)
{
    CBCTL0 &=~(CBIPSEL_10+CBIPSEL_13+CBIPSEL_14+CBIPSEL_15);
    CBCTL3 &=~(BITA+BITD+BITE+BITF);

    CBCTL0 |= CBIPEN;// + CBIPSEL_15;// + CBIPSEL_13 + CBIPSEL_14 + CBIPSEL_15;
                                  // Enable V+, input channel CB0
    CBCTL1 |= CBPWRMD_1;          // normal power mode
    CBCTL2 |= CBRSEL;             // VREF is applied to -terminal

    //Vcb_refv = IN*(n+1)/32
    CBCTL2 |= CBRS_1+CBREF0_15;   // VREF0设为16/32*Vcc == 1.15v   3.3


    //CBCTL3 |= BITF;               // + BITD + BITE + BITF;
                                  // Input Buffer Disable @P3.7/CB10  @P3.3/CB13   @P3.2/CB14   @PJ.6/CB15

    __delay_cycles(7500);           // 延迟以待参考电压稳定

    CBINT &= ~(CBIFG + CBIIFG);   // Clear any errant interrupts
    //CBINT  |= CBIE;             // Enable CompB Interrupt on rising edge of CBIFG (CBIES=0) 0 ---> 1.15

    CBINT  |= CBIE + CBIES;       // Enable CompB Interrupt on falling edge of CBIFG (CBIES=1) 3.3 ---> 1.15
    CBCTL1 |= CBON;               // Turn On ComparatorB

    //
    index_port = 0;
}



// Comp_B ISR
#pragma vector=COMP_B_VECTOR
__interrupt void Comp_B_ISR (void)
{
    CBINT  &=~CBIFG;               // Clear Interrupt flag
    if(index_port == 0)
        return;

    if(index_port == 1){             // MOTOR1_TOUCH
        touched   |= 0x01;           // Detect do touch
        time1_bak  = time_count_1ms; // Record curent time
    }
    if(index_port == 2){             // MOTOR2_TOUCH
        touched   |= 0x02;           // Detect do touch
        time2_bak  = time_count_1ms; // Record curent time
    }
    if(index_port == 3){             // MOTOR3_TOUCH
        touched   |= 0x04;           // Detect do touch
        time3_bak  = time_count_1ms; // Record curent time
    }
    if(index_port == 4){             // MOTOR4_TOUCH
        touched   |= 0x08;           // Detect do touch
        time4_bak  = time_count_1ms; // Record curent time
    }
}


//Check to see if the fader is being touched
void checkTouch(void)
{
    if(time_count_1ms%1000 == 0){
        time_count_1ms++;
        index_port++;
        if(index_port>4)
            index_port = 1;
        CBCTL0 &=~(CBIPSEL_10+CBIPSEL_13+CBIPSEL_14+CBIPSEL_15);
        CBCTL3 &=~(BITA+BITD+BITE+BITF);
        if(index_port == 1){
            CBCTL0 |= CBIPSEL_15;
            CBCTL3 |= BITF;
        }else if(index_port == 2){
            CBCTL0 |= CBIPSEL_14;
            CBCTL3 |= BITE;
        }else if(index_port == 3){
            CBCTL0 |= CBIPSEL_13;
            CBCTL3 |= BITD;
        }else if(index_port == 4){
            CBCTL0 |= CBIPSEL_10;
            CBCTL3 |= BITA;
        }
    }

    //juge Touch 
    if(time_count_1ms > time1_bak + 20){ //timeout
        touched &=~0x01;
    }
    if(time_count_1ms > time2_bak + 20){
        touched &=~0x02;
    }
    if(time_count_1ms > time3_bak + 20){
        touched &=~0x04;
    }
    if(time_count_1ms > time4_bak + 20){
        touched &=~0x08;
    }

    printf("--touch--0x%d  index_port:%d\r\n",touched,index_port);
    
}


void main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer

	pmm_setVcoreUp(0x01);       // Vcore setting of at max 3 for 24MHz MCLK
	pmm_setVcoreUp(0x02);
	pmm_setVcoreUp(0x03);

    initPorts();                // Config all the GPIOS for low-power (output low)
    initClocks();               // Config clocks. MCLK=SMCLK=DCO=2*XT1=24MHz; ACLK=REFO=32kHz
	//....
    initCompare();
	//....
    initTimerA0();


    __enable_interrupt();




    while(1){


        checkTouch();
	}
}	
		

  • 楼主既然想用时间片的方式让B检测比较,那么你使用其中一个通道的时候,其他3个肯定不行的啊,没什么疑问的。你完全可以把每个通道的检测写成一个函数,分时调用,这样速度上肯定会降低为1个时候的四分之一,但是功能实现了,不知道你的项目对时效性要求高不高,频率能否满足。
  • 目前我还没有到考虑到时效性的要求,问题已经卡在这个mcu不能动态切换输入比较通道,我只能配置最先配置那个通道,想在程序运行中切换成其他通道已经切换不了!不懂为什么? FAE回复太应付式了,说不能动态切换,要实现4个输入通道的信号检测,要外部加一个4选1开关切换电路!那我这个mcu要比较器何用??????????????????
  • FAE可能是想说不能够配置后自动完成这四个通道切换。因为这个比较器最大的好处就是配置完成后,不需要软件干预了,如果你需要4个不停切换干预的最好使用ADC来做。不过我看完官方例子和手册后有了以下想法:
    配置使用一路比较器输入需要配置是否使用CBOUT,我看看到这个输出接口只有1个P3.3,所以你想让系统自动完成你多个通道也是只有一个表现的输出接口。另外一个方式就是使用中断,然后中断里判断是当时采用了哪个通道触发的。这样你的四路配置,就要编写4个函数了,每个函数里面包含通道配置,参考电压配置等,而中断里要先读取当时的通道数,然后根据通道号来确定中断后要处理的事情。
    挺复杂的,这个东西设计的初衷不是这么玩的。如果非要这样用也可以,那就只能有一个CBOUT来反应情况了。如果你想知道是哪个通道的还需要额外使用4个IO,甚至做一些外部的电路来实现CB的自动处理。