我一直在使用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;
}
}
欢迎提出其他解决方案的建议,或者我应该阅读的任何其他资源将会非常有帮助,以使其发挥作用。 提前感谢您的参与和阅读。





