Project Objective: Develop an open source AIS Alarm that alerts sailors that a new marine vessel with AIS is within range
In this post I will start development of the firmware for the prototype by setting up the microcontroller's clock, setting up a timer that can be used for counting time elapsed in milliseconds, and use GPIO to confirm the timing.
I have started a spreadsheet to document what peripherals I will be using as shown below.
At this point I just want to make sure the clocks are running the way I want and that the GPIO is working. The master clock will be set at 8 MHz and I will run the sub master at the same speed. The lower frequency / low power ACLK will be set to 32768 Hz. I will be using the internal oscillator since I don't expect to need high accuracy. I can always add an external crystal to the final product if needed.
I am setting up functions that initialize the various peripherals and then testing them as I go along. I've also written a function milliSecs() that returns the number of milliseconds since the start. Timer B0 is used to increment a global variable MILLIS in an ISR.
/* * dAISy_Alarm_V001 - implements millisecond timer and blinks LED * * MCLK, SCLK set to 8 MHz * Milliseconds counted on timer B0 * * Frank Milburn 29 December 2017 * Developed on MSP430FR2111 with CCS V7.2, compiler TIv17.9.0.STS */ #include "driverlib.h" // Miscellaneous #define DEBUG 2 // 0 = no debug, 1...3 is increasing debug // Clock and Timer related definitions #define TIMER_UP_COUNT 8000 // approximately 1 millisecond @ 8 MHz // GPIO related definitions #define LED_WARN GPIO_PORT_P1,GPIO_PIN0 // warning LED // Function prototypes void initClocks(void); // initialize clocks void initGPIO(void); // initialize GPIO void initTimerB0(void); // initialize timer B0 unsigned long milliSecs(void); // returns milliseconds since counter started // Global variable declarations const unsigned long BEEP_LEN = 10; // beep length in milliseconds volatile unsigned long MILLIS = 0; // running count of milliseconds int main(void) { WDT_A_hold(WDT_A_BASE); // stop the watch dog PMM_unlockLPM5(); // activate port settings after power on initClocks(); initGPIO(); initTimerB0(); __bis_SR_register(GIE); // globally enable interrupts unsigned long startTime = milliSecs(); for(;;){ // run forever } } // ------------------------------------------------------------------------------------- void initClocks(void){ __bis_SR_register(SCG0); // disable FLL CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3; // DCOFTRIM=3, DCO Range = 8MHz CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz __delay_cycles(3); __bic_SR_register(SCG0); // enable FLL CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as // ACLK source, ACLK = 32768Hz // default DCODIV as MCLK, SMCLK source } // ------------------------------------------------------------------------------------- void initGPIO(void){ GPIO_setAsOutputPin(LED_WARN); GPIO_setOutputLowOnPin(LED_WARN); } // ------------------------------------------------------------------------------------- unsigned long milliSecs(void){ return MILLIS; // return milliseconds } // ------------------------------------------------------------------------------------- void initTimerB0(void){ TB0CCTL0 |= CCIE; // TBCCR0 interrupt enabled TB0CCR0 = TIMER_UP_COUNT; // approx 1 millisecond TB0CTL |= TBSSEL__SMCLK | MC__UP; // SMCLK, Up mode } // Timer B0 interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = TIMER0_B0_VECTOR __interrupt void Timer_B (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMER0_B0_VECTOR))) Timer_B (void) #else #error Compiler not supported! #endif { MILLIS++; GPIO_toggleOutputOnPin(LED_WARN); // remove this after testing accuracy REMOVE }
I need to clean this up and set up an h file :-). Let's test and see how accurate the timer is by putting an oscilloscope on P1.0 which is being toggled in the ISR that is counting milliseconds.
It is running within 0.5 percent which is what the datasheet shows so good to go.
By the way, I am skipping through this fairly fast now (depending on whether you are familiar with the MSP430 or not) but if there are questions I am happy to attempt an answer. As must be obvious by now I am a hobbyist level programmer so if someone more knowledgeable has a better way to do things or just a different way please comment.
Past Posts on this Project:
AIS Alarm - Prototype Hardware
References and Links:
WEGMATT LLC - dAISy AIS Receiver - low cost AIS receiver
Texas Instruments MSP430FR2xx FRAM Microcontrollers - Post No. 4