Part Number:MSP430FR5994
Hello everyone,
I am coming up the learning curve on the
MSP430FR5994 and ran into two problems neither of which I can explain and need some help to understand. The code is rather simple, it simply uses the BCL UART to respond with " hello world " whenever a character "a" is typed on the CCS's terminal (any character other than "a" is ignored). This code works (with many thanks to Bruce and Matt). However, I am puzzled that the code stops functioning when I comment out a P5IFG = 0x00; statement inside the initGPIO function. I highlighted the problem statement in yellow. As is, the code works. Comment out the statement and it stops. Moving the statement outside of the function and into the main function doesn't change the behavior. The statement needs to be in the initGPIO function for some reason. Any ideas as to what's happening?
1) The second problem is that Port5 interrupts from the two button on the Launchpad (P5.6 and P5.5) aren't being recognized when pressed. Did I lock up the port somehow? . Any help here would also be greatly appreciated.
#include "driverlib.h"
uint32_t myMCLK = 0;
uint32_t mySMCLK = 0;
uint32_t myACLK = 0;
volatile uint8_t i;
volatile uint8_t j;
const char UCA0_string[] = {" Hello World "};
extern int mode;
extern int pingHost;
uint8_t RXData = 0; // UART Receive byte
int mode = 0; // mode selection variable
int pingHost = 0; // ping request from PC GUI
int noSDCard = 0;
Calendar calendar; // Calendar used for RTC
void initClocks (void){
// Set DCO frequency to 8 MHz
CS_setDCOFreq(CS_DCORSEL_0, CS_DCOFSEL_6);
//Set external clock frequency to 32.768 KHz
CS_setExternalClockSource(32768, 0);
//Set ACLK=LFXT
CS_initClockSignal(CS_ACLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
// Set SMCLK = DCO with frequency divider of 1
CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
// Set MCLK = DCO with frequency divider of 1
CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
//Start XT1 with no time out
CS_turnOnLFXT(CS_LFXT_DRIVE_3);
myACLK=CS_getACLK();
mySMCLK=CS_getSMCLK(); //8MHz
myMCLK=CS_getMCLK(); //16MHz
}
initTimers(void){
myACLK=CS_getACLK(); //10KHZ
Timer_A_initContinuousModeParam initA0 = {0}; //initializer selects TB1
initA0.clockSource=TIMER_A_CLOCKSOURCE_ACLK;
initA0.clockSourceDivider=TIMER_A_CLOCKSOURCE_DIVIDER_1;
initA0.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
initA0.timerClear=TIMER_A_DO_CLEAR;
initA0.startTimer=false;
Timer_A_initContinuousMode(TIMER_A0_BASE,&initA0);
__bis_SR_register(GIE);
}
void Init_BCL_UART()
{
// Configure UART
EUSCI_A_UART_initParam param = {};
param.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_ACLK;
param.clockPrescalar = 3; //set for 32.768KHz
param.firstModReg = 0;
param.secondModReg = 0x92; //3;//0x92;
param.parity = EUSCI_A_UART_NO_PARITY;
param.msborLsbFirst = EUSCI_A_UART_LSB_FIRST;
param.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT;
param.uartMode = EUSCI_A_UART_MODE;
param.overSampling = EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;
if(STATUS_FAIL == EUSCI_A_UART_init(EUSCI_A0_BASE, ¶m))
return;
EUSCI_A_UART_enable(EUSCI_A0_BASE);
EUSCI_A_UART_clearInterrupt(EUSCI_A0_BASE,EUSCI_A_UART_RECEIVE_INTERRUPT);
// Enable USCI_A0 RX interrupt
EUSCI_A_UART_enableInterrupt(EUSCI_A0_BASE,
EUSCI_A_UART_RECEIVE_INTERRUPT); // Enable interrupt
myACLK=CS_getACLK();
mySMCLK=CS_getSMCLK(); //8MHz
myMCLK=CS_getMCLK(); //16MHz
}
void initGPIO()
{
// Set all GPIO pins to output low for low power
GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4| GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_P7, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_P8, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setOutputLowOnPin(GPIO_PORT_PJ, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10|GPIO_PIN11|GPIO_PIN12|GPIO_PIN13|GPIO_PIN14|GPIO_PIN15);
GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4| GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_P7, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_P8, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
GPIO_setAsOutputPin(GPIO_PORT_PJ, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10|GPIO_PIN11|GPIO_PIN12|GPIO_PIN13|GPIO_PIN14|GPIO_PIN15);
// Set PJ.4 and PJ.5 as Primary Module Function Input, LFXT.
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_PJ,GPIO_PIN4 + GPIO_PIN5,GPIO_PRIMARY_MODULE_FUNCTION);
// Setup P1.0 and P1.1 LED
GPIO_setAsOutputPin(GPIO_PORT_P1,GPIO_PIN0);
GPIO_setAsOutputPin(GPIO_PORT_P1,GPIO_PIN1);
//turn off leds
GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN1);
// Setup P5.5 and P5.6 as input buttons
GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5,GPIO_PIN5);
GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5,GPIO_PIN6);
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5,GPIO_PRIMARY_MODULE_FUNCTION);
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);
GPIO_selectInterruptEdge(GPIO_PORT_P5,GPIO_PIN5,GPIO_HIGH_TO_LOW_TRANSITION);
GPIO_selectInterruptEdge(GPIO_PORT_P5,GPIO_PIN6,GPIO_HIGH_TO_LOW_TRANSITION);
//P5IE = 0x60; //enable interrupts on P5.5 and P5.6
GPIO_enableInterrupt(GPIO_PORT_P5,GPIO_PIN5);
GPIO_enableInterrupt(GPIO_PORT_P5,GPIO_PIN6);
//setup BCL UART Pins
// Configure P2.0 - UCA0TXD and P2.1 - UCA0RXD
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN0, GPIO_SECONDARY_MODULE_FUNCTION);
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN1, GPIO_SECONDARY_MODULE_FUNCTION);
//enable interrupts
// commenting out the function below causes the EUSCI_A_UART to stop working.EUSCI_A_UART uses P2.0 & P2.1
P5IFG = 0x00; //clear all Port 5 interrupt flags
// Disable the GPIO power-on default high-impedance mode
// to activate previously configured port settings
//PMM_unlockLPM5();
}
void Init_RTC()
{
//Setup Current Time for Calendar
calendar.Seconds = 0x55;
calendar.Minutes = 0x30;
calendar.Hours = 0x04;
calendar.DayOfWeek = 0x01;
calendar.DayOfMonth = 0x30;
calendar.Month = 0x04;
calendar.Year = 0x2014;
// Initialize RTC with the specified Calendar above
RTC_C_initCalendar(RTC_C_BASE,&calendar,RTC_C_FORMAT_BCD);
RTC_C_setCalendarEvent(RTC_C_BASE,RTC_C_CALENDAREVENT_MINUTECHANGE);
RTC_C_clearInterrupt(RTC_C_BASE,RTC_C_TIME_EVENT_INTERRUPT);
RTC_C_enableInterrupt(RTC_C_BASE,RTC_C_TIME_EVENT_INTERRUPT);
//Start RTC Clock
RTC_C_startClock(RTC_C_BASE);
}
int main(void) {
WDT_A_hold(WDT_A_BASE);
initGPIO();
initClocks();
initTimers();
Init_BCL_UART();
//P5IFG = 0x00;
/*
SDCardLib_setRTCTime(SDCardLib * lib, Calendar *curTime);
SDCardLib_detectCard(SDCardLib * lib);
SDCardLib_createDirectory(SDCardLib * lib, char * directoryName);
SDCardLib_writeFile(SDCardLib * lib,
char * fileName, char *buffer, uint16_t bufsize,
uint16_t *actualsize);
return (0);
*/
PMM_unlockLPM5(); // Enable output pin settings - disable the GPIO power-on default high-impedance mode
// PM5CTL0 &= ~LOCKLPM5;
//start timer B1 and its interrupt
Timer_A_startCounter(TIMER_A0_BASE,TIMER_A_CONTINUOUS_MODE);
Timer_A_enableInterrupt(TIMER_A0_BASE);
UCA0IE |= UCRXIE; //enable only receive interrupts
//__bis_SR_register(GIE);//enable interrupts
__enable_interrupt();
while(1)
{
volatile uint8_t k;
//EUSCI_A_UART_transmitData(EUSCI_A0_BASE,'K');
}
}
#pragma vector = USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
switch(__even_in_range(UCA0IV,18))
{
case 0x00: // Vector 0: No interrupts
break;
case 0x02: // Vector 2: UCRXIFG
if (UCA0RXBUF =='a'){
i=0;
UCA0IE |= UCTXIE; //received "a", enable transmit response
UCA0TXBUF = UCA0_string[j];
}
break;
case 0x04: // Vector 4: UCTXIFG
UCA0TXBUF = UCA0_string[j++];
if (j== sizeof(UCA0_string) - 1) {
UCA0IE &= ~UCTXIE;
}
if(j>= sizeof(UCA0_string))j=0;
break;
case 0x06: // Vector 6: UCSTTIFG
break;
case 0x08: // Vector 8: UCTXCPTIFG
break;
default: break;
}
}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER_A0_ISR(void)
{
switch(__even_in_range(TA0IV, 14))
{
case 0: // none
break;
case 2: // CCR1 IFG
break;
case 4: // CCR2 IFG
break;
case 6: // CCR3 IFG
break;
case 8: // CCR4 IFG
break;
case 10: // CCR5 IFG
break;
case 12: // CCR6 IFG
break;
case 14: // TAOIFG
GPIO_toggleOutputOnPin(GPIO_PORT_P1,GPIO_PIN0);
Timer_A_clearTimerInterrupt(TIMER_A0_BASE);
break;
default: // never executed
break;
}
}
#pragma vector=PORT5_VECTOR
__interrupt void ISR_P5_Handler (void){
switch (P5IFG)
{
case 0x20: //P5.5 interrupt
P5IFG &= ~BIT5; //clear IFG
P1OUT |= BIT1; //Grn LED port 1.1
_delay_cycles(80000); //wait
P1OUT &= ~BIT1; //Turn Off LED
break;
case 0x40: //P5.6 interrupts
P5IFG &= ~BIT6; //clear IFG
int i;
for (i=3;i>0;i-- ){ //flash 3 times
P1OUT |= BIT1; //Grn LED port 1.1
_delay_cycles(80000);
P1OUT ^= BIT1;
_delay_cycles(80000);
}
break;
default: //Never executed
break;
}
}
/*
#pragma vector=PORT5_VECTOR
__interrupt void ISR_BUTTON_P55(void){
_delay_cycles(1000); //wait for debounce
//P1OUT &= ~BIT0;
P5IFG = 0x00; //clear Interrupt flag
P5OUT |= BIT5;
_delay_cycles(800000);
P1OUT &= ~BIT0;
}
#pragma vector=PORT5_VECTOR
__interrupt void ISR_BUTTON_P56(void)
{
_delay_cycles(10); //wait for debounce
P1IFG = 0x00;//clear Interrupt flag
P6OUT &= ~BIT6;
for (j=6; j>0; j--) //three flashes - cycle through code twice per flash
{
P6OUT ^= BIT6;
_delay_cycles(200000);//replace with timer
}
P5OUT &= ~BIT6;
//test uart pragma
//UCA1IE |= UCTXIE; //enable txie
}
*/
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
{
switch(__even_in_range(RTCIV, 16))
{
case RTCIV_NONE: break; //No interrupts
case RTCIV_RTCOFIFG: break; //RTCOFIFG
case RTCIV_RTCRDYIFG: break; //RTCRDYIFG
case RTCIV_RTCTEVIFG: //RTCEVIFG
//Interrupts every 5 seconds
__no_operation(); //for debugging
__bic_SR_register_on_exit(LPM3_bits); // exit LPM3
break;
case RTCIV_RTCAIFG: break; //RTCAIFG
case RTCIV_RT0PSIFG: break; //RT0PSIFG
case RTCIV_RT1PSIFG: break; //RT1PSIFG
default: break;
}
}