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