Part Number: MSP430FR2355
Other Parts Discussed in Thread: OPT3001
Tool/software: Code Composer Studio
I was trying to run two servo motors and one OPT3001 using MSP430, i m adding how it is supposed to work.
The servo motor rotation is controlled using ADC input and pin 2.2 is set using value from result register of OPT3001. During debugging my program is only performing ADC function, only ADC_Result variable is getting updated.
I tried adding breakpoints and debugging, but my program is getting stuck at this line from ADC_capture() function and that's why only ADC_Result is getting updated from ADC_ISR.
__bis_SR_register(LPM0 | GIE); // Enter LPM3 w/ interrupts
I tried removing ADC ISR and used If statement,
if(ADCIV_ADCIFG)
{
ADC_Result = ADCMEM0;
}
but this did not work.
Can you tell my what is the problem with this.
Thank You
I m attaching my code here.
#include <msp430.h> // Generic MSP430 Device Include
#include <stdint.h>
#define OPT3001 0x44
#define Result 0x00
#define Configuration 0x01
#define ONE_BYTE 0x1
#define TWO_BYTES 0x2
#define THREE_BYTES 0x3
unsigned long lux;
unsigned int ADC_Result;
void GPIO_pin_configurations(void);
void Turning_MECH(void);
void Dipping_SYS(void);
void ADC_capture(void);
void ADC_CONFIG(void);
void I2C_transmission_setup(unsigned char num_of_bytes);
void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2);
void I2C_setup_write(unsigned char slave_address, unsigned char register_address);
void I2C_read(unsigned char slave_address);
unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa);
unsigned char TXData[3];
unsigned char RXData[2];
unsigned char ByteCtr;
void main(void)
{
GPIO_pin_configurations();
unsigned int exponent;
unsigned int mantissa;
//Write to Configuration Register (0x01) to set the operational mode of the OPT3001
I2C_transmission_setup(THREE_BYTES);
I2C_write(OPT3001, Configuration, 0xC6, 0x08);
// Delay for 100 milliseconds to allow conversion process to complete
__delay_cycles(100);
while(1)
{
I2C_transmission_setup(ONE_BYTE);
I2C_setup_write(OPT3001, Result);
I2C_transmission_setup(TWO_BYTES);
I2C_read(OPT3001);
//Extract the upper four bits of exponent and the lower 12 bits of mantissa from the raw result value
exponent = RXData[0] >> 4;
mantissa = (RXData[0] << 8 | RXData[1]) & 0x0FFF;
//Take the exponent and mantissa values and calculate the corresponding lux value
lux = convert_to_lux(exponent, mantissa);
ADC_CONFIG();
Dipping_SYS();
Turning_MECH();
ADC_capture();
} // End background loop
} // End main()
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCB0IV,USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts break;
case USCI_I2C_UCALIFG: break;
case USCI_I2C_UCNACKIFG:
UCB0CTL1 |= UCTXSTT; //resend start if NACK
break; // Vector 4: NACKIFG break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG break;
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG break;
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3 break;
case USCI_I2C_UCTXIFG3: break; // Vector 14: TXIFG3 break;
case USCI_I2C_UCRXIFG2: break; // Vector 16: RXIFG2 break;
case USCI_I2C_UCTXIFG2: break; // Vector 18: TXIFG2 break;
case USCI_I2C_UCRXIFG1: break; // Vector 20: RXIFG1 break;
case USCI_I2C_UCTXIFG1: break; // Vector 22: TXIFG1 break;
case USCI_I2C_UCRXIFG0: // Vector 24: RXIFG0 break;
RXData[ByteCtr] = UCB0RXBUF; // Load RX buffer
ByteCtr++; // Increment RX byte counter
break;
case USCI_I2C_UCTXIFG0: // Vector 26: TXIFG0 break;
UCB0TXBUF = TXData[ByteCtr]; // Load TX buffer
ByteCtr++; // Increment TX byte counter
break;
case USCI_I2C_UCBCNTIFG: // Vector 28: BCNTIFG
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
break;
case USCI_I2C_UCCLTOIFG: break; // Vector 30: clock low timeout
case USCI_I2C_UCBIT9IFG: break; // Vector 32: 9th bit
default: break;
}
}
// 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;
}
}
void I2C_transmission_setup(unsigned char num_of_bytes)
{
//Configure USCI_B0 for I2C Mode and designate the number of bytes to be transmitted/received
UCB0CTLW0 |= UCSWRST; // Software reset enabled
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C master mode, SMCLK
UCB0CTLW1 |= UCASTP_2; // Automatic stop generated
// after UCB0TBCNT is reached
UCB0BRW = 0x8; // baudrate = SMCLK / 8
UCB0TBCNT = num_of_bytes; // number of bytes to be received
UCB0CTL1 &= ~UCSWRST; // clear reset register
UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE | UCBCNTIE; // transmit and NACK interrupt enable
}
void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2)
{
UCB0I2CSA = slave_address; // Set the slave address
TXData[0] = register_address; // Set the control register address
TXData[1] = byte_1; // Set the Register Data LSB
TXData[2] = byte_2; // Set the Register Data MSB
ByteCtr = 0; // Load byte counter
while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
UCB0CTLW0 |= UCTR; // I2C TX
UCB0CTLW0 |= UCTXSTT; // I2C start condition
__bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupts
// Remain in LPM0 until all data
// is TX'd
}
void I2C_setup_write(unsigned char slave_address, unsigned char register_address)
{
UCB0I2CSA = slave_address; // Set the slave address
TXData[0] = register_address; // Set the control register address
ByteCtr = 0; // Load byte counter
while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
UCB0CTLW0 |= UCTR; // I2C TX
UCB0CTLW0 |= UCTXSTT; // I2C start condition
__bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupts
// Remain in LPM0 until all data
// is TX'd
}
void I2C_read(unsigned char slave_address)
{
UCB0I2CSA = slave_address; // Set the slave address
ByteCtr = 0; // Load byte counter
while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
UCB0CTLW0 &= ~UCTR; // I2C RX
UCB0CTLW0 |= UCTXSTT; // I2C start condition
__bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupts
// Remain in LPM0 until all data
// is RX'd
}
unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa)
{
// Convert the Result Register into a lux measurement based on formula below:
// lux = 0.01 * (2^E[3:0]) * R[11:0]
unsigned int result;
unsigned int count;
unsigned long converted_lux;
result = 1;
for(count = exponent; count > 0; count--)
{
result = result * 2;
}
converted_lux = mantissa / 100;
converted_lux *= result;
return converted_lux;
}
void GPIO_pin_configurations(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
// Configure ADC A1 pin
P1SEL0 |= BIT1 | BIT2 | BIT3; //Configure ADC A1 pin, I2C pins and Timer_B 0 pins
P1SEL1 |= BIT1 | BIT6 | BIT7; // P1.1, 1.2, 1.3 , 1.6 and 1.7 options select
P1DIR |= BIT6; // P1.6 output
// Configure XT1 oscillator
P2SEL1 |= BIT6 | BIT7; // P2.6~P2.7: crystal pins
CSCTL4 = SELA__XT1CLK; // Set ACLK = XT1; MCLK = SMCLK = DCO
/*Configuring Unused pins to avoid floating voltage
and extra current consumption*/
P1OUT = 0x00;
P3DIR = 0xFF;
P3OUT = 0x00;
P4DIR = 0xFF;
P4OUT = 0x00;
P5DIR = 0xFF;
P5OUT = 0x00;
P6DIR = 0xFF;
P6OUT = 0x00;
P7DIR = 0xFF;
P7OUT = 0x00;
P8DIR = 0xFF;
P8OUT = 0x00;
P9DIR = 0xFF;
P9OUT = 0x00;
P10DIR = 0xFF;
P10OUT = 0x00;
PADIR = 0xFF;
PAOUT = 0x00;
PBDIR = 0xFF;
PBOUT = 0x00;
PCDIR = 0xFF;
PCOUT = 0x00;
PDDIR = 0xFF;
PDOUT = 0x00;
PEDIR = 0xFF;
PEOUT = 0x00;
}
void Turning_MECH(void)
{
//Servo motor for rotation minimum value of TB0CCR1 is 500 and maximum value of TB0CCR1 is 3500
TB0CCTL1 = OUTMOD_7; // CCR1 reset/set P1.6
TB0CCTL2 = OUTMOD_7; // CCR2 reset/set
TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR; // SMCLK, up mode, clear TBR
if(ADC_Result == 0)
{
TB0CCR0 = 20000-1; // PWM Period
TB0CCR1 = 500; // CCR1 PWM duty cycle
TB0CCR2 = 500; // CCR2 PWN duty cycle
}
else if(ADC_Result == 100)
{
TB0CCR0 = 20000-1; // PWM Period
TB0CCR1 = 1700; // CCR1 PWM duty cycle
TB0CCR2 = 1700; // CCR2 PWN duty cycle
}
else if(ADC_Result >= 250)
{
TB0CCR0 = 20000-1; // PWM Period
TB0CCR1 = 3500; // CCR1 PWM duty cycle
TB0CCR2 = 3500; // CCR2 PWN duty cycle
}
}
void Dipping_SYS(void)
{
/*
* Pin2.2 is connected to main headlight and control its auto dip mechanism
*/
if(lux > 2000)
{
P2DIR |= BIT2;
P2OUT |= BIT2;
}
else
{
P2OUT = 0X00;
}
}
void ADC_CONFIG(void)
{
// Configure ADC
ADCCTL0 |= ADCON | ADCMSC; // ADCON
ADCCTL1 |= ADCSHS_2 | ADCCONSEQ_2; // repeat single channel; TB1.1 trig sample start
ADCCTL2 &= ~ADCRES; // clear ADCRES in ADCCTL
ADCCTL2 |= ADCRES_2; // 12-bit conversion results
ADCMCTL0 |= ADCINCH_1 | ADCSREF_1; // A1 ADC input select; Vref=1.5V
ADCIE |= ADCIE0; // Enable ADC conv complete interrupt
// Configure reference
PMMCTL0_H = PMMPW_H; // Unlock the PMM registers
PMMCTL2 |= INTREFEN | REFVSEL_0; // Enable internal 1.5V reference
__delay_cycles(400); // Delay for reference settling
do{
CSCTL7 &= ~(XT1OFFG | DCOFFG); // Clear XT1 and DCO fault flag
SFRIFG1 &= ~OFIFG;
}while (SFRIFG1 & OFIFG); // Test oscillator fault flag
}
void ADC_capture(void)
{
ADCCTL0 |= ADCENC; // ADC Enable
// ADC conversion trigger signal - TimerB1.1 (32ms ON-period)
TB1CCR0 = 1024-1; // PWM Period
TB1CCR1 = 512-1; // TB1.1 ADC trigger
TB1CCTL1 = OUTMOD_4; // TB1CCR0 toggle
TB1CTL = TBSSEL__ACLK | MC_1 | TBCLR; // ACLK, up mode
__bis_SR_register(LPM0 | GIE); // Enter LPM3 w/ interrupts
}