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.

MSP430FR6989 LCD Segments Ghosting

Other Parts Discussed in Thread: MSP430FR6989, MSP-EXP430FR6989, MSPWARE

Hello everyone!

I have a MSP430FR6989 Launchpad and I'm trying to read the room temperature using the ADC and the temperature sensor and display it on integrated LCD. The only problem is that some segments that should be off are on, but not at full intensity. I have read that this phenomenon is called "ghosting".

How I can turn unwanted segments full off and display only the segments I need?

This is my code : 

#include <msp430.h>

float adc_result=0;
float CAL_ADC_25T30=0;
float CAL_ADC_25T85=0;
float temp=0;
unsigned int temp0=0, temp1=0, temp2=0, temp3=0, temp4=0, temp5=0;

const char digit[10] = {
	0xFC,
	0x60,
	0xDB,
	0xF3,
	0x67,
	0xB7,
	0xBF,
	0xE4,
	0xFF,
	0xF7
};


void init_Clock(void)
{
	CSCTL0 = 0xA500;  // enable
	CSCTL4 &= ~LFXTOFF; // lfxt on
	CSCTL4 |= SMCLKOFF; //smclock off
	CSCTL2 = SELA__LFXTCLK; // aclk = lfxt = 32768 Hz
	CSCTL6 = ACLKREQEN;
}

void init_TimerA0(void)
{
	TA0CTL = TASSEL_1 + ID__8 + MC_1 + TAIE + TAIFG; // aclk = 4096 Hz
	TA0EX0 = TAIDEX_3;									// aclk = 1024 Hz
	TA0CCTL0 = CCIS_0 + CCIE + CCIFG;
	TA0IV = TA0IV_TA0IFG;
	TA0CCR0 = 10240; // 10 s
}

void init_ADC(void)
{
	ADC12CTL0 &= ~ADC12ENC;
	ADC12CTL0 = ADC12ON + ADC12SHT0_7;			// adc_on + 64 clock cycles
	ADC12CTL1 = ADC12SSEL_1 + ADC12SHP; 		// aclk + sample_and_hold enable
	ADC12CTL2 = ADC12RES_2;						// 12 bits
	ADC12CTL3 = ADC12TCMAP + ADC12CSTARTADD_0;  // temp sensor enable + read from mem0
	ADC12MCTL0 = ADC12INCH_30 + ADC12VRSEL_1;	// input channel 30 = temp sensor + internal vref
	ADC12CTL0 |= ADC12ENC;						// enable conversion
}

void init_LCD(void)
{
	LCDCCTL0 &= ~LCDON;									// lcd off
	LCDCCTL0 = LCDDIV_2 + LCDPRE__4 + LCD4MUX + LCDLP;	// Flcd = 512 Hz; Fframe = 64 Hz
	LCDCMEMCTL = LCDCLRM;								// clear memory
	//LCDCVCTL = LCD2B;									// 1/3 bias
	LCDCPCTL0 = 0xFFFF;									// enable Segments
	LCDCPCTL1 = 0xFFFF;									// enable segments
	LCDCPCTL2 = 0x7FFF;									// enable segments
	LCDCCTL0 |= LCDON;									// lcd on
}

void check_value(unsigned int *x)
{
	switch(*x)
	{
		case 0: *x=0xFC; break;
		case 1: *x=0x60; break;
		case 2: *x=0xDB; break;
		case 3: *x=0xF3; break;
		case 4: *x=0x67; break;
		case 5: *x=0xB7; break;
		case 6: *x=0xBF; break;
		case 7: *x=0xE4; break;
		case 8: *x=0xFF; break;
		case 9: *x=0xF7; break;
		default: break;
	}
}

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;					// Stop watchdog timer
    PM5CTL0 &= PMMLPRST;
    REFCTL0 = REFVSEL_2 + REFON;				// vref = 2.5V

    init_Clock();
	init_TimerA0();
	init_ADC();
	init_LCD();

	LCDM10 = digit[4];

	CAL_ADC_25T30 = *(unsigned int*)0x1A22;
	CAL_ADC_25T85 = *(unsigned int*)0x1A24;

	__bis_SR_register(LPM0_bits+GIE);
	while(1)
	{

	}
}

#pragma vector=TIMER0_A0_VECTOR
   __interrupt void Timer_A0(void)
   {

		   ADC12CTL0 |= ADC12SC;
		   adc_result = ADC12MEM0;
		   //temp_oC = (adc_result/4096*2.5-0.7)/0.0025;
		   temp = (adc_result-CAL_ADC_25T30)*((85-30)/(CAL_ADC_25T85-CAL_ADC_25T30))+30.0f;

		   temp0 = temp*1000;
		   temp1 = temp0/10000;
		   temp2 = temp0/1000;
		   temp2 = temp2%10;
		   temp3 = temp0/100;
		   temp3 = temp3%10;
		   temp4 = temp0/10;
		   temp4 = temp4%10;
		   temp5 = temp0%10;

		   check_value(&temp1);
		   check_value(&temp2);
		   check_value(&temp3);
		   check_value(&temp4);
		   check_value(&temp5);



	   LCDM10 = temp1;
	   LCDM6 = temp2;
	   LCDM4 = temp3;
	   LCDM19 = temp4;
	   LCDM15 = temp5;
	   LCDM8 = 0x9C;
	   LCDM7 = 0x01;
	   LCDM16 = 0x04;

	   TA0CTL&= ~(1<<TAIFG);				//disable interrupt flag

       __no_operation();
   }

**Attention** This is a public forum