-
Notifications
You must be signed in to change notification settings - Fork 0
/
msp430f5310_extra.c
150 lines (133 loc) · 5.9 KB
/
msp430f5310_extra.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
* Written by Tim Johns.
*
* The function bodies in this file are specific to the MSP430F5310 MCU.
*/
#ifndef _MSPLIB_C
#define _MSPLIB_C
#include <msp430f5310.h>
#include <stdint.h>
#include "msp430f5310_extra.h"
/*----------------------------------------------------------------------------*/
/* Enter Low Power Mode */
/*----------------------------------------------------------------------------*/
void enter_LPM(void) {
PMMCTL0_H = PMMPW_H; // Open PMM (Power Management Module)
PMMCTL0_L |= PMMREGOFF; // Set flag to enter LPM4.5 with LPM4 request
//LPM4; // Now enter LPM4.5
// (Device does not wake up from LPM4)
LPM3; // Enter Low Power Mode 3
_NOP();
}
/*----------------------------------------------------------------------------*/
/* Change from Low Power Mode to normal operation */
/*----------------------------------------------------------------------------*/
void exit_LPM(void) {
PMMCTL0_H = PMMPW_H; // Open PMM
PM5CTL0 &= ~LOCKIO; // Clear LOCKIO and enable ports
PMMCTL0_H = 0x00; // Close PMM
P1IFG = 0x0000; // Clear all pending interrupt flags
}
/*----------------------------------------------------------------------------*/
/* Configure watchdog timer (also used to feed watchdog) */
/*----------------------------------------------------------------------------*/
void wdt_config(void) {
// Select ACLK source, clear timer, timer interval = clock / 32k (1 s at 32 kHz)
WDTCTL = WDTPW | WDTSSEL__ACLK | WDTCNTCL | WDTIS__32K;
}
/*----------------------------------------------------------------------------*/
/* Stop watchdog timer */
/*----------------------------------------------------------------------------*/
void wdt_stop(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
}
/*----------------------------------------------------------------------------*/
/* Set up and configure ADC (10 bit) */
/*----------------------------------------------------------------------------*/
void adc_config(void) {
// REF Master Control, Voltage Level Select 2.5 V (VREF+), Temp.Sensor off,
// Reference On
REFCTL0 = REFMSTR | REFVSEL_3 | REFTCOFF | REFON;
ADC10CTL0 &= ~ADC10ENC; // Disable ADC
ADC10CTL0 = ADC10SHT_15 | ADC10ON; // 1024 clock cycles, ADC on
ADC10MCTL0 = ADC10SREF_1 | ADC10INCH_3; // VR+ = VREF+ and VR- = AVSS
// CLK/1, MODCLK source, single-channel
ADC10CTL1 = ADC10SHP | ADC10DIV_0 | ADC10SSEL_0 | ADC10CONSEQ_0;
ADC10CTL2 = ADC10RES; // 10 bit resolution
ADC10IFG = 0x0000; // Clear interrupt flags
ADC10CTL0 |= ADC10ENC | ADC10SC; // Enable and read once
while (!(ADC10IFG & ADC10IFG0)); // Wait for ready flag
}
/*----------------------------------------------------------------------------*/
/* Read and return voltage with ADC (10 bit) */
/*----------------------------------------------------------------------------*/
uint16_t adc_read(void) {
// Actual voltage = (ADC10MEM0 / 1024) * 2.5 * 2
// Half voltage due to resistor divider
ADC10IFG = 0x0000; // Clear interrupt flags
ADC10CTL0 &= ~ADC10ENC; // Disable ADC
ADC10CTL0 |= ADC10ENC | ADC10SC; // Enable and read once
while (!(ADC10IFG & ADC10IFG0)); // Wait for ready flag
return ADC10MEM0;
}
/*----------------------------------------------------------------------------*/
/* Set up and configure clock */
/*----------------------------------------------------------------------------*/
void clock_config(void) {
// Set DCO range to 4.6 - 39.0 MHz
UCSCTL1 = DCORSEL1 | DCORSEL2;
// Set DCOCLKDIV to (32768 kHz / 1) * 366 =~ 12 MHz
// (Set DCOCLK to 24 MHz)
UCSCTL2 = FLLN1 | FLLN2 | FLLN3 | FLLN5 | FLLN6 | FLLN8 | FLLD0;
// Set ACLK source = REFOCLK (32 kHz), SMCLK source = DCOCLKDIV,
// MCLK source = DCOCLKDIV
UCSCTL4 = SELA__REFOCLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV;
// Set SMCLKREQEN = 0, MCLKREQEN = 0 so that SMCLK and MCLK are off during LPM3
UCSCTL8 &= (~BIT1 & ~BIT2);
///TEST crystal
// UCSCTL6 &= (~BIT0); // Set XT1OFF = 0
// UCSCTL6 &= (~BIT2);
}
/*----------------------------------------------------------------------------*/
/* Restart Real-Time Clock A in calendar mode */
/*----------------------------------------------------------------------------*/
void rtc_restart(void) {
/* Switching between counter mode and calendar mode resets the clock/counter
registers */
RTCCTL01 &= ~RTCMODE;
RTCCTL01 = RTCMODE; // Calendar mode
}
/*----------------------------------------------------------------------------*/
/* Return true iff RTC time values are safe for reading (not in transition) */
/*----------------------------------------------------------------------------*/
uint8_t rtc_rdy(void) {
return (RTCCTL01 & RTCRDY) > 0;
}
/*----------------------------------------------------------------------------*/
/* Enable interrupts. Doesn't work in interrupt service routine. */
/*----------------------------------------------------------------------------*/
void enable_interrupts(void) {
__enable_interrupt();
}
/*----------------------------------------------------------------------------*/
/* Disable interrupts. Doesn't work in interrupt service routine. */
/*----------------------------------------------------------------------------*/
void disable_interrupts(void) {
__disable_interrupt();
}
/*----------------------------------------------------------------------------*/
/* Trigger brownout reset */
/*----------------------------------------------------------------------------*/
void brownout_reset(void) {
PMMCTL0 = PMMPW | PMMSWBOR;
}
/*----------------------------------------------------------------------------*/
/* Set up Timer0_A5 */
/*----------------------------------------------------------------------------*/
void timer_config(void) {
TA0CCR0 = 0xFFFF; // Count up to 0xFFFF
TA0CCTL0 = CCIE; // Enable interrupt for CCR0
// SMCLK source, f/1, count up to CCR0, Timer_A clear
TA0CTL = TASSEL_2 | ID_0 | MC_1 | TACLR;
}
#endif