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 CB0CBCTL1 |= CBPWRMD_1;// normal power modeCBCTL2 |= CBRSEL;// VREF is applied to -terminal//Vcb_refv = IN*(n+1)/32CBCTL2 |= CBRS_1+CBREF0_15;// VREF0设为16/32*Vcc == 1.15v3.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.15CBINT |= CBIE + CBIES;// Enable CompB Interrupt on falling edge of CBIFG (CBIES=1) 3.3 ---> 1.15CBCTL1 |= 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 flagif(index_port == 0)return;if(index_port == 1){// MOTOR1_TOUCHtouched|= 0x01;// Detect do touchtime1_bak = time_count_1ms; // Record curent time}if(index_port == 2){// MOTOR2_TOUCHtouched|= 0x02;// Detect do touchtime2_bak = time_count_1ms; // Record curent time}if(index_port == 3){// MOTOR3_TOUCHtouched|= 0x04;// Detect do touchtime3_bak = time_count_1ms; // Record curent time}if(index_port == 4){// MOTOR4_TOUCHtouched|= 0x08;// Detect do touchtime4_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 Touchif(time_count_1ms > time1_bak + 20){ //timeouttouched &=~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(); } }
gaoyang9992006:
楼主既然想用时间片的方式让B检测比较,那么你使用其中一个通道的时候,其他3个肯定不行的啊,没什么疑问的。你完全可以把每个通道的检测写成一个函数,分时调用,这样速度上肯定会降低为1个时候的四分之一,但是功能实现了,不知道你的项目对时效性要求高不高,频率能否满足。
x.c mo:
回复 gaoyang9992006:
目前我还没有到考虑到时效性的要求,问题已经卡在这个mcu不能动态切换输入比较通道,我只能配置最先配置那个通道,想在程序运行中切换成其他通道已经切换不了!不懂为什么? FAE回复太应付式了,说不能动态切换,要实现4个输入通道的信号检测,要外部加一个4选1开关切换电路!那我这个mcu要比较器何用??????????????????
gaoyang9992006:
回复 x.c mo:
FAE可能是想说不能够配置后自动完成这四个通道切换。因为这个比较器最大的好处就是配置完成后,不需要软件干预了,如果你需要4个不停切换干预的最好使用ADC来做。不过我看完官方例子和手册后有了以下想法:
配置使用一路比较器输入需要配置是否使用CBOUT,我看看到这个输出接口只有1个P3.3,所以你想让系统自动完成你多个通道也是只有一个表现的输出接口。另外一个方式就是使用中断,然后中断里判断是当时采用了哪个通道触发的。这样你的四路配置,就要编写4个函数了,每个函数里面包含通道配置,参考电压配置等,而中断里要先读取当时的通道数,然后根据通道号来确定中断后要处理的事情。
挺复杂的,这个东西设计的初衷不是这么玩的。如果非要这样用也可以,那就只能有一个CBOUT来反应情况了。如果你想知道是哪个通道的还需要额外使用4个IO,甚至做一些外部的电路来实现CB的自动处理。