I'm using the MSP430FR6989 launchpad, with LCD. I'm trying to to utilize the RTC, LCD and IR-KEYPAD Boosterpack.
I cannot get the input to detect a state change, I set up as Input, with a pull up resistor, and used another pin as output Low, to use to drive the input low. I used a DVM I can measure the input dropping to 0, but when I look at the registrars, it show High even though I see 0 V on the input.
I wrote a routine before the LCD was initialized and it works, but when I initialize the LCD the input is not read.
What am I missing?
This is the program attached, note it's in it's imfancy
Thanks
Roman
/*
* make a light that appears as the sun is rising in the morning
* starts off with dull red to orange to yellow to green yellow blue
* light blue to blue
*
*
*/
/*
* J1 J3 J4 J2
* 1 3.3v 5.0v P2.7 GND
* 2 *P9.2 GND P2.6 P2.1
* 3 *P4.3 P8.4 P3.3 P1.5
* 4 P4.2 P8.5 P3.6 P9.4
* 5 @P3.2 P8.6 P3.7 RST
* 6 *P9.3 P8.7 P2.2 P1.6
* 7 P1.4 P9.0 P1.3 P1.7
* 8 *P2.0 P9.1 P3.0 @P2.5
* 9 P4.1 P9.5 P3.1 @P2.4
* 10 P4.0 P9.6 P2.3 @P4.7
*
* LED1 P1.0 Red
* LED2 P9.7 Green
* S1 P1.1 Mode
* S2 P1.2
*
* S3 P1.3 J4.7 Next
* S4 P1.4 J1.7 Up
* S5 P1.5 J2.3 Down
* S6 P1.6 J2.6 Select
* S7 P1.7 J2.7 alarm Off
*
*
* Out In
* P9.2 P2.5
* P4.3 P2.4
* P9.3 P4.7
* P2.0 P3.2
*
* Out Out Out Out
* In P2.0 P9.3 P4.3 P9.2
* P2.5 OK cool 0 pwr
* P2.4 copy 9 8 7
* P4.7 temp- 6 5 4
* P3.2 temp+ 3 2 1
*
*/
//******************************************************************************
// MSP430FR69x Demo - LCD_C, RTC_C, Display real time clock on LCD in LPM3 mode.
//
// Description: This examples configures the LCD in 4-Mux mode and displays
// "430" on a TI LCD and blinks it at 1Hz interval. This example was tested
// on MSP-EXP430FR6989 Launchpad. This example would need to be modified based
// on the final LCD and GPIO routing where lcd_num[] would need to be modified.
// The internal voltage is sourced to v2 through v4 and v5 is connected to
// ground. Charge pump is enabled.
//
// It uses LCD pin L0~L21 and L26~L43 as segment pins.
// f(LCD) = 32768Hz/((1+1)*2^4) = 1024Hz, ACLK = ~32768Hz,
// MCLK = SMCLK = default DCODIV ~1MHz.
//
// MSP430FR6989 / MSP-EXP430FR6989 Launchpad
// -----------------
// /|\| |
// | | XIN|--
// GND --|RST | 32768Hz
// | | XOUT|--
// | | |
// | | COM3|----------------|
// | | COM2|---------------||
// |--4.7uF -|LCDCAP COM1|--------------|||
// | COM0|-------------||||
// | | -------------
// | Sx~Sxx|---| 1 2 3 4 5 6 |
// | | -------------
// | | TI LCD
// (See MSP-EXP430FR6989 Schematic)
//
// William Goh
// Texas Instruments Inc.
// May 2015
// Built with IAR Embedded Workbench V6.30 & Code Composer Studio V6.1
//*****************************************************************************
#include <msp430fr6989.h>
#define pos1 9 /* Digit A1 begins at S18 */
#define pos2 5 /* Digit A2 begins at S10 */
#define pos3 3 /* Digit A3 begins at S6 */
#define pos4 18 /* Digit A4 begins at S36 */
#define pos5 14 /* Digit A5 begins at S28 */
#define pos6 7 /* Digit A6 begins at S14 */
const unsigned int lcd_num[10] =
{
0x00FC, // 0
0x0060, // 1
0x00DB, // 2
0x00F3, // 3
0x0067, // 4
0x00B7, // 5
0x00BF, // 6
0x00E4, // 7
0x00FF, // 8
0x00F7, // 9
};
// LCD memory map for uppercase letters
const unsigned int alphabet_Big[27] =
{
0x00EF, /* 0= "A" LCD segments a+b+c+e+f+g+m */
0x00F1, /* 1= "B" */
0x009C, /* 2= "C" */
0x00F0, /* 3= "D" */
0x009F, /* 4= "E" */
0x008F, /* 5= "F" */
0x00BD, /* 6= "G" */
0x006F, /* 7= "H" */
0x0090, /* 8= "I" */
0x0078, /* 9= "J" */
0x000E, /* 10= "K" */
0x001C, /* 11= "L" */
0x006C, /* 12= "M" */
0x006C, /* 13= "N" */
0x00FC, /* 14= "O" */
0x00CF, /* 15= "P" */
0x00FC, /* 16= "Q" */
0xFFCF, /* 17= "R" */
0x00B7, /* 18= "S" */
0x0080, /* 19= "T" */
0x007C, /* 20= "U" */
0x000C, /* 21= "V" */
0x006C, /* 22= "W" */
0x0000, /* 23= "X" */
0x0000, /* 24= "Y" */
0x0090, /* 25= "Z" */
0x0000, /* 26= " " */
};
unsigned int mode = 0xFF;
unsigned int alarm_time[8][4]; //day of week, hour, min, enable;
unsigned int delay1;
unsigned int delay2;
unsigned int kb = 0xFF;
void updateLcd(void);
void AlarmSet(void);
void updateMode(void);
void delay(void);
unsigned KeyPad(void);
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
// ###############################################################
// Configure GPIO
P1DIR |= BIT0; // Clear P1.0 output latch for a defined power-on state
P1OUT |= BIT0; // Set P1.0 to output direction
// ==================================
P9DIR |= BIT2;
P9OUT &= ~BIT2;
P4DIR |= BIT3;
P4OUT &= ~BIT3;
P9DIR |= BIT3;
P9OUT &= ~BIT3;
P2DIR |= BIT0;
P2OUT &= ~BIT0;
// =====================================
P2DIR &= ~BIT5; // input
P2REN |= BIT5; // en resistor
P2OUT |= BIT5; // pull up resistor
P2DIR &= ~BIT4; // input
P2REN |= BIT4; // en resistor
P2OUT |= BIT4; // pull up resistor
P4DIR &= ~BIT7; // input
P4REN |= BIT7; // en resistor
P4OUT |= BIT7; // pull up resistor
P3DIR &= ~BIT2; // input
P3REN |= BIT2; // en resistor
P3OUT |= BIT2; // pull up resistor
// =========================================
P9OUT |= BIT2;
P4OUT |= BIT3;
P9OUT |= BIT3;
P2OUT |= BIT0;
// =========================================
// this works when I run this portion or the program
// don't know why the main program does not work
//
// PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode
// // to activate previously configured port settings
// P9OUT &= ~BIT2;
// while(1)
// {
// if( (P2IN & BIT5) == 0 )
// {
// P1OUT |= BIT0; // LED on
// }
// else
// {
// P1OUT &= ~BIT0; // LED off
// }
// __delay_cycles(100000);
// }
// ###############################################################
PJSEL0 = BIT4 | BIT5; // For LFXT
// Initialize LCD segments 0 - 21; 26 - 43
LCDCPCTL0 = 0xFFFF;
LCDCPCTL1 = 0xFC3F;
LCDCPCTL2 = 0x0FFF;
// PM5CTL0 &= ~LOCKLPM5;
// Configure LFXT 32kHz crystal
CSCTL0_H = CSKEY >> 8; // Unlock CS registers
CSCTL4 &= ~LFXTOFF; // Enable LFXT
do
{
CSCTL5 &= ~LFXTOFFG; // Clear LFXT fault flag
SFRIFG1 &= ~OFIFG;
} while (SFRIFG1 & OFIFG); // Test oscillator fault flag
CSCTL0_H = 0; // Lock CS registers
// Configure RTC_C
// RTCCTL0_H = RTCKEY_H; // Unlock RTC
// RTCCTL0_L = RTCTEVIE | RTCRDYIE; // enable RTC read ready interrupt
// enable RTC time event interrupt Min event | sec event
RTCCTL0 |= RTCKEY |RTCRDYIE; // Unlock RTC & enable RTC time event interrupt
// RTCCTL0_L = RTCRDYIE; // enable RTC time event interrupt sec event
RTCCTL1 = RTCBCD | RTCHOLD | RTCMODE; // RTC enable, BCD mode, RTC hold
P1IES &= ~BIT1; // P1.1 Hi/Lo edge
P1IFG = 0; // Clear all P1 interrupt flags
PM5CTL0 &= ~LOCKLPM5;
// preset the clock
RTCYEAR = 0x2015; // Year = 0x2010
RTCMON = 0x7; // Month = 0x04 = April
RTCDAY = 0x29; // Day = 0x05 = 5th
RTCDOW = 0x07; // Day of week = 0x01 = Monday
RTCHOUR = 0x22; // Hour = 0x04
RTCMIN = 0x52; // Minute = 0x30
RTCSEC = 0x00; // Seconds = 0x45
// Initialize LCD_C
// ACLK, Divider = 1, Pre-divider = 16; 4-pin MUX
LCDCCTL0 = LCDDIV__1 | LCDPRE__16 | LCD4MUX | LCDLP;
// VLCD generated internally,
// V2-V4 generated internally, v5 to ground
// Set VLCD voltage to 2.60v
// Enable charge pump and select internal reference for it
LCDCVCTL = VLCD_1 | VLCDREF_0 | LCDCPEN;
LCDCCPCTL = LCDCPCLKSYNC; // Clock synchronization enabled
LCDCMEMCTL = LCDCLRM; // Clear LCD memory
// Display time
updateLcd();
// Display the 2 colons
LCDMEM[6] = 0x04;
LCDMEM[19] = 0x04;
//Turn LCD on
LCDCCTL0 |= LCDON;
RTCCTL1 &= ~(RTCHOLD); // Start RTC
__bis_SR_register(GIE);
P1OUT &= ~BIT0; // turn red led off
while(1)
{
if (KeyPad() != 0xFF) // check if the Keypad is used ?
{
RTCCTL0 &= ~(RTCKEY | RTCRDYIE); // Unlock RTC & DISABLE Interrupt
// do stuff here to check the keypad touches
do
{
kb = KeyPad();
}
while (kb != 0x12);
RTCCTL0 |= RTCKEY | RTCRDYIE; // Unlock RTC & ENABLE Interrupt
updateLcd();
// Display the 2 colons
LCDMEM[6] = 0x04;
LCDMEM[19] = 0x04;
//Turn LCD on
LCDCCTL0 |= LCDON;
}
}
// return 0;
}
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
{
switch(__even_in_range(RTCIV, RTCIV_RT1PSIFG))
{
case RTCIV_NONE: break; // No interrupts
case RTCIV_RTCOFIFG: break; // RTCOFIFG
case RTCIV_RTCRDYIFG: // RTCRDYIFG
// P1OUT ^= BIT0; // Toggles P1.0 every second
if(mode == 0xFF)
{
updateLcd(); // Update the segmented LCD
}
break;
case RTCIV_RTCTEVIFG: // RTCEVIFG
__no_operation(); // Interrupts every minute
break;
case RTCIV_RTCAIFG: break; // RTCAIFG clock alarm
// when alarm is set do stuff here
case RTCIV_RT0PSIFG: break; // RT0PSIFG
case RTCIV_RT1PSIFG: break; // RT1PSIFG
default: break;
}
}
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
updateMode();
P1IES ^= BIT1; // Toggle interrupt edge
P1IFG &= ~BIT1; // Clear P1.1 IFG
}
void updateLcd(void) // update the time
{
P1OUT &= ~BIT0;
LCDMEM[pos1] = lcd_num[(RTCHOUR & 0xF0) >> 4];
LCDMEM[pos2] = lcd_num[(RTCHOUR & 0x0F)];
LCDMEM[pos3] = lcd_num[(RTCMIN & 0xF0) >> 4];
LCDMEM[pos4] = lcd_num[(RTCMIN & 0x0F)];
LCDMEM[pos5] = lcd_num[(RTCSEC & 0xF0) >> 4];
LCDMEM[pos6] = lcd_num[(RTCSEC & 0x0F)];
}
void updateMode(void) // update the time
{
P1OUT |= BIT0;
RTCCTL0 &= ~(RTCKEY | RTCRDYIE); // Unlock RTC & DISABLE Interrupt
LCDMEM[pos1] = alphabet_Big[2];
LCDMEM[pos2] = alphabet_Big[11];
LCDMEM[pos3] = alphabet_Big[26];
LCDMEM[pos4] = alphabet_Big[26];
LCDMEM[pos5] = alphabet_Big[26];
LCDMEM[pos6] = alphabet_Big[26];
mode = 1;
if(P1IN & BIT2 != 0) // look for P1.2 next
{
delay();
}
LCDMEM[pos1] = alphabet_Big[2];
LCDMEM[pos2] = alphabet_Big[11];
LCDMEM[pos3] = alphabet_Big[26];
LCDMEM[pos4] = alphabet_Big[26];
LCDMEM[pos5] = alphabet_Big[26];
LCDMEM[pos6] = alphabet_Big[26];
mode = 1;
if(P1IN & BIT2 != 0) // look for P1.2 next
{
}
RTCCTL0 |= RTCKEY | RTCRDYIE; // Unlock RTC & ENABLE Interrupt
}
void AlarmSet(void)
{
RTCAMIN = 0x00; // RTCAE = alarm enable
RTCAHOUR = 0x00;
}
void delay(void)
{
for (delay1=32000; delay1 ==0; delay1--)
{
}
}
unsigned int KeyPad(void)
{
// RTCCTL0_L &= ~RTCRDYIE;
unsigned int db_ctr = 0x04;
unsigned int debounce = 0xFFFF;
unsigned int kp = 0xFF;
unsigned int kp_ctr = 0x00;
/* Out Out Out Out
* In P2.0 P9.3 P4.3 P9.2
* P2.5 OK cool 0 pwr
* P2.4 copy 9 8 7
* P4.7 temp- 6 5 4
* P3.2 temp+ 3 2 1
*/
/*
* Why doesn't this work, I placed a DVM on P2.5 I can see the voltage drop
* when the " OK " button is pressed on the IR Keypad booster pack, but
* when I look at the Debug info for P2.5, still shows a High, even though
* I measured 0 volts on the I/O pin. what am I missing
*
* It works when I run the test program in the very beginning.
*
*
*/
for(db_ctr=0x04; db_ctr > 0; db_ctr--)
{
P1OUT |= BIT0; // turn red led on
P9OUT &= ~BIT2; // ko1
if((P2IN & BIT5) == 0)
{kp = 0x14;} // pwr
if((P2IN & BIT4) == 0)
{kp = 0x07;} // 7
if((P4IN & BIT7) == 0)
{kp = 0x04;} // 4
if((P3IN & BIT2) == 0)
{kp = 0x01;} // 1
P9OUT |= BIT2;
P4OUT &= ~BIT3; // ko2
if((P2IN & BIT5) == 0)
{kp = 0x00;} // 0
if((P2IN & BIT4) == 0)
{kp = 0x08;} // 8
if((P4IN & BIT7) == 0)
{kp = 0x05;} // 5
if((P3IN & BIT2) == 0)
{kp = 0x02;} // 2
P4OUT |= BIT3;
P9OUT &= ~BIT3; // ko3
if((P2IN & BIT5) == 0)
{kp = 0x12;} // cool
if((P2IN & BIT4) == 0)
{kp = 0x09;} // 9
if((P4IN & BIT7) == 0)
{kp = 0x06;} // 6
if((P3IN & BIT2) == 0)
{kp = 0x03;} // 3
P9OUT |= BIT3;
P2OUT &= ~BIT0; // ko
if((P2IN & BIT5) == 0)
{kp = 0x11;} // ok
if((P2IN & BIT4) == 0)
{kp = 0x12;} // copy
if((P4IN & BIT7) == 0)
{kp = 0x13;} // temp-
if((P3IN & BIT2) == 0)
{kp = 0x14;} // temp+
P2OUT |= BIT0;
for(debounce=0x00FF; debounce > 0; debounce--)
{
P1OUT |= BIT0; // turn red led on
}
}
P1OUT &= ~BIT0; // turn red led off
return(kp);
}