我一直在使用ADC,它可以从外部源转换电压读数。 我从ADCMEMM0中得到的数值范围是20到120。 我尝试使用I2C传输这些值,但由于某些原因,它们不起作用。
我已经尝试实施了一些示例,例如TI提供的一个示例文件eusci_b_i2c_ex3_masterTxMultiple.c. 按其原由实施会导致程序卡在eusci_b_i2c.c中的第318行,我不明白为什么,因为处理中断的方式非常复杂。 我也使用 了这个资源 ,但它用于另一个MSP430模型,它的中断是不同的,我也不知道如何实施。
另一个问题是,我是否一次发送一个字节的ADC结果? 或者,我是否指定MSP430读取并存储数据然后传输数据的特定时间量?
下面是第二个资源的代码:
//i2c implementation using the TI_I2C functions, gets stuck in the //interrupt at the end of the definitions file #include <msp430.h> #include <driverlib.h> #include "TI_USCI_I2C_master.h" #include <stdio.h> #include <math.h> unsigned int ADC_Result = 0; unsigned char SlaveAddress = 0xC0; unsigned char char_ADC_result[1] = {0}; unsigned long long numbin_watch,numbin = 0; int length = 0; int numbinArray[10]; int count = 0; long long convert(int num) { long long numbin = 0; int rem; long long i = 1; while (num!=0) { rem = num % 2; num /= 2; numbin += rem * i; i *= 10; } return numbin; } int lengthOfInt(unsigned long long numbin){ int count = 0; while (numbin != 0) { numbin /= 10; count++; } return count; } int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT // Configure GPIO P1DIR |= BIT0; // Set P1.0/LED to output direction P1OUT &= ~BIT0; // P1.0 LED off // Configure ADC A9 pin SYSCFG2 |= ADCPCTL9; // Configure Pins for I2C //P5SEL0 |= BIT2 | BIT3; // I2C pins, select pin P5.2 for SDA and pin P5.3 for SCL // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; __enable_interrupt(); //worked without this, uncomment to test with it // Configure ADC10 ADCCTL0 |= ADCSHT_2 | ADCON; // ADCON, S&H=16 ADC clks----ADCSHTx : 0000b = 4 ADCCLK cycles 0001b = 8 ADCCLK cycles 0010b = 16 ADCCLK cycles 0011b = 32 ADCCLK cycles ADCCTL1 |= ADCSHP | ADCSSEL_0 | ADCCONSEQ_2; // ADCCLK = MODOSC; sampling timer ADCCONSEQ_2 = Repeat-single-channel ---- remove it for single channel ADCCTL2 |= ADCRES_1 ; // 10/8-bit conversion results ADCRES_1 = 10 bit////ADCRES_0 = 8 bit ADCMCTL0 |= ADCINCH_9 | ADCSREF_0; // A9 ADC input select; pin 8.1 use this for mic setup ADCIFG &= ~0x01; //clear interrupt flag ADCIE |= ADCIE0; // Enable ADC conv complete interrupt // // Configure USCI_B0 for I2C mode // UCB0CTLW0 |= UCSWRST; // put eUSCI_B in reset state // UCB0CTLW0 |= UCMODE_3 | UCMST; // I2C master mode, SMCLK // //UCB0CTLW0 |= UCSLA10 | UCSSEL_2; // slave has 7 bit address, source clock is SMCLK // UCB0BRW = 0x8; // baudrate = SMCLK / 8 // UCB0CTLW0 &=~ UCSWRST; // clear reset register // UCB0IE |= UCTXIE0 | UCNACKIE; // transmit and NACK interrupt enable TI_USCI_I2C_transmitinit(SlaveAddress,0x01); // init transmitting with USCI and config while(1) { ADCCTL0 |= ADCENC | ADCSC; // Sampling and conversion start, could use ACCTL0 = 0x03 __bis_SR_register(LPM0_bits | GIE); // LPM0, ADC_ISR will force exit LOW POWER MODE 0 //__no_operation(); // For debug only if (ADC_Result < 0x00F){ P1OUT &= ~BIT0; // Clear P1.0 LED off } else{ P1OUT |= BIT0; // Set P1.0 LED on } char_ADC_result[0] = ADC_Result; __delay_cycles(5000); while ( TI_USCI_I2C_notready() ); // wait for bus to be free //if ( TI_USCI_I2C_slave_present(SlaveAddress) ) // slave address may differ from //{ // initialization //while ( TI_USCI_I2C_notready() ); // wait for bus to be free TI_USCI_I2C_transmit(1,char_ADC_result); // start transmitting //} //__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 //LPM0; // Remain in LPM0 until all data is TX'd } } // ADC interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = ADC_VECTOR __interrupt void ADC_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(ADCIV,ADCIV_ADCIFG)) { case ADCIV_NONE: break; case ADCIV_ADCOVIFG: break; case ADCIV_ADCTOVIFG: break; case ADCIV_ADCHIIFG: break; case ADCIV_ADCLOIFG: break; case ADCIV_ADCINIFG: break; case ADCIV_ADCIFG: ADC_Result = ADCMEM0; __bic_SR_register_on_exit(LPM0_bits); // Clear CPUOFF bit from LPM0 break; default: break; } }
下面是TI提供的示例代码:
//uses TI board-specific i2c example, gets stuck in an interrupt again, line 318 in esci_b_i2c.c #include <msp430.h> #include <driverlib.h> #include "Board.h" #define SLAVE_ADDRESS 0xC0 #define CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ 1000 //Target frequency for SMCLK in kHz #define CS_SMCLK_FLLREF_RATIO 30 //SMCLK/FLLRef Ratio unsigned int ADC_Result = 0; // Pointer to TX data uint8_t TXData = 0; uint8_t TXByteCtr; int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT // Configure GPIO P1DIR |= BIT0; // Set P1.0/LED to output direction P1OUT &= ~BIT0; // P1.0 LED off // Configure ADC A9 pin SYSCFG2 |= ADCPCTL9; //Set DCO FLL reference = REFO CS_initClockSignal( CS_FLLREF, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); //Set Ratio and Desired MCLK Frequency and initialize DCO CS_initFLLSettle( CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ, CS_SMCLK_FLLREF_RATIO ); //Set ACLK = VLO with frequency divider of 1 CS_initClockSignal( CS_ACLK, CS_VLOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); //Set SMCLK = DCO with frequency divider of 1 CS_initClockSignal( CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1 ); //Set MCLK = DCO with frequency divider of 1 CS_initClockSignal( CS_MCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1 ); // Configure Pins for I2C , SCL 5.3, SDA 5.2 GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_UCB0SCL, GPIO_PIN_UCB0SCL, GPIO_FUNCTION_UCB0SCL ); GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_UCB0SDA, GPIO_PIN_UCB0SDA, GPIO_FUNCTION_UCB0SDA ); /* * Disable the GPIO power-on default high-impedance mode to activate * previously configured port settings */ PMM_unlockLPM5(); EUSCI_B_I2C_initMasterParam param = {0}; param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; param.i2cClk = CS_getSMCLK(); param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS; param.byteCounterThreshold = 0; param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, ¶m); //Specify slave address EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, SLAVE_ADDRESS ); //Set Master in receive mode EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE ); //Enable I2C Module to start operations EUSCI_B_I2C_enable(EUSCI_B0_BASE); EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT ); //Enable master Receive interrupt EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT ); // Configure ADC10 ADCCTL0 |= ADCSHT_2 | ADCON; // ADCON, S&H=16 ADC clks----ADCSHTx : 0000b = 4 ADCCLK cycles 0001b = 8 ADCCLK cycles 0010b = 16 ADCCLK cycles 0011b = 32 ADCCLK cycles ADCCTL1 |= ADCSHP | ADCSSEL_0 | ADCCONSEQ_2; // ADCCLK = MODOSC; sampling timer ADCCONSEQ_2 = Repeat-single-channel ---- remove it for single channel ADCCTL2 |= ADCRES_1 ; // 10/8-bit conversion results ADCRES_1 = 10 bit////ADCRES_0 = 8 bit ADCMCTL0 |= ADCINCH_9 | ADCSREF_0; // A9 ADC input select; pin 8.1 use this for mic setup ADCIFG &= ~0x01; //clear interrupt flag ADCIE |= ADCIE0; // Enable ADC conv complete interrupt while(1) { ADCCTL0 |= ADCENC | ADCSC; // Sampling and conversion start, could use ACCTL0 = 0x03 __bis_SR_register(LPM0_bits | GIE); // LPM0, ADC_ISR will force exit LOW POWER MODE 0 //__no_operation(); // For debug only if (ADC_Result < 0x00F){ P1OUT &= ~BIT0; // Clear P1.0 LED off } else{ P1OUT |= BIT0; // Set P1.0 LED on } __delay_cycles(1000); // Delay between transmissions TXByteCtr = 1; // Load TX byte counter TXData = ADC_Result; while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE)); EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, TXData++); //__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts // Remain in LPM0 until all data // is TX'd // Increment data byte } } // ADC interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = ADC_VECTOR __interrupt void ADC_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(ADCIV,ADCIV_ADCIFG)) { case ADCIV_NONE: break; case ADCIV_ADCOVIFG: break; case ADCIV_ADCTOVIFG: break; case ADCIV_ADCHIIFG: break; case ADCIV_ADCLOIFG: break; case ADCIV_ADCINIFG: break; case ADCIV_ADCIFG: ADC_Result = ADCMEM0; __bic_SR_register_on_exit(LPM0_bits); // Clear CPUOFF bit from LPM0 break; default: break; } } //------------------------------------------------------------------------------ // The USCIAB0TX_ISR is structured such that it can be used to transmit any // number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData // points to the next byte to transmit. //------------------------------------------------------------------------------ #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_B0_VECTOR __interrupt #elif defined(__GNUC__) __attribute__((interrupt(USCI_B0_VECTOR))) #endif void USCIB0_ISR(void) { switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: // No interrupts break; break; case USCI_I2C_UCALIFG: // Arbitration lost break; case USCI_I2C_UCNACKIFG: // NAK received (master only) //resend start if NACK EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE); break; case USCI_I2C_UCTXIFG0: // TXIFG0 // Check TX byte counter if (TXByteCtr) { EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, TXData++); // Decrement TX byte counter TXByteCtr--; } else { EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE); // Exit LPM0 __bic_SR_register_on_exit(CPUOFF); } break; default: break; } }
欢迎提出其他解决方案的建议,或者我应该阅读的任何其他资源将会非常有帮助,以使其发挥作用。 提前感谢您的参与和阅读。