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(); }