-
-
Save poundifdef/1191273 to your computer and use it in GitHub Desktop.
MSP430 IR Serial Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple IR Receiver | |
// Kenneth Finnegan, 2011 | |
// kennethfinnegan.blogspot.com | |
// | |
// Pinout: | |
// P1.[0..7] - Common anode 7 segment display w/ decimal | |
// P2.5 - 38kHz IR receiver | |
#include <msp430g2252.h> | |
#define EN_DECIMAL_PT 0x7F | |
#define DIS_DECIMAL_PT 0xFF | |
#define BEAT_FREQ 512 | |
#define BUTDEB_LEN (BEAT_FREQ / 4) | |
#define MAX_STATE 9 | |
#define STATE_LEN 4 | |
#define ERROR_STATE 0x0A | |
// xmit - flag to start 38kHz IR LED modulation | |
// xmitstate - state machine for serial protocol | |
// currstate - currently selected digit [0-9] | |
// decimalmask - mask to set or clear decimal point | |
// butdeb - Button debounce counters | |
volatile unsigned int currstate=ERROR_STATE, rcvrstate = 0, newstate = 0, | |
decimalmask = DIS_DECIMAL_PT, stateage = 0; | |
// Seven segment bit fields. Active low. {[0-9] E(rror)} | |
unsigned const char digits[] = { 0x82, 0xBB, 0xA4, 0xA1, 0x99, | |
0xC1, 0xC0, 0xAB, 0x80, 0x89, 0xC4 }; | |
void main(void) { | |
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer | |
BCSCTL1 = CALBC1_1MHZ; | |
DCOCTL = CALDCO_1MHZ; | |
P1DIR = 0xFF; // Set P1 to output direction | |
P1OUT = 0xFF; // Set the LEDs off | |
P2DIR = 0xDF; // Set P2.5 to input for buttons | |
P2OUT = 0x00; | |
P2IES = 0x20; // Negative edge trigger | |
P2IFG = 0x00; | |
P2IE = 0x20; // Enable button interrupts | |
TACTL = TASSEL_1 | MC_1; // Set the timer A to ACLK, Up mode | |
TACCR0 = (0x8000 / BEAT_FREQ) - 1; // Reset timer at BEAT frequency | |
TACCTL0 = CCIE; // Clear the timer and enable timer interrupt | |
__enable_interrupt(); | |
_BIS_SR(LPM1_bits + GIE); | |
} | |
// Timer A0 interrupt service routine | |
// Heartbeat interrupt | |
#pragma vector=TIMER0_A0_VECTOR | |
__interrupt void Timer0_A0 (void) | |
{ | |
stateage++; | |
// If we haven't seen an update in two cycles, something's wrong | |
if (stateage > 2 * BEAT_FREQ) { | |
currstate = ERROR_STATE; | |
} | |
decimalmask = DIS_DECIMAL_PT; | |
if (rcvrstate > 1) decimalmask = EN_DECIMAL_PT; | |
P1OUT = digits[currstate] & decimalmask; | |
} | |
// Timer A1 interrupt service routine | |
// Sampling pulse for IR data | |
#pragma vector=TIMER0_A1_VECTOR | |
__interrupt void Timer_A1 (void) | |
{ | |
P2OUT ^= 0x01; // Debug tick | |
if (rcvrstate == 1) { // Test for START bit | |
if (P2IN & 0x20) { // No start bit | |
rcvrstate = 0; | |
P2IE |= 0x20; | |
TACCTL1 = 0; | |
} | |
} else if (rcvrstate == STATE_LEN + 2) { // Test for STOP bit | |
if (P2IN & 0x20) { // No stop bit | |
rcvrstate = 0; | |
P2IE |= 0x20; | |
TACCTL1 = 0; | |
} | |
} else if (rcvrstate == STATE_LEN + 3) { // Finish receive | |
rcvrstate = 0; | |
P2IE |= 0x20; | |
TACCTL1 = 0; | |
currstate = newstate; | |
stateage = 0; | |
} else { // State bit | |
newstate = (newstate << 1) | ((P2IN >> 5) & 0x01); | |
} | |
rcvrstate++; | |
TAIV &= ~(0x02); // CLEAR INTERRUPT | |
} | |
#pragma vector=PORT2_VECTOR | |
__interrupt void Port2 (void) { | |
// Start bit edge | |
if (P2IFG & 0x20) { | |
rcvrstate = 1; // Begin receive | |
newstate = 0; | |
// Set Timer0A1 to half a beat later | |
TACCR1 = (TAR + (0x8000 / 2 / BEAT_FREQ)) % (TACCR0 + 1); | |
TACCTL1 = CCIE; | |
// Turn off edge interrupt | |
P2IE &= ~0x20; | |
} | |
P2IFG = 0x00; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple IR Transmitter | |
// Kenneth Finnegan, 2011 | |
// kennethfinnegan.blogspot.com | |
// | |
// Pinout: | |
// P1.[0..7] - Common anode 7 segment display w/ decimal | |
// P2.0 - Increment state button | |
// P2.1 - Decrement state button | |
// P2.5 - IR LED OUTPUT | |
#include <msp430g2252.h> | |
#define EN_DECIMAL_PT 0x7F | |
#define DIS_DECIMAL_PT 0xFF | |
#define BEAT_FREQ 512 | |
#define BUTDEB_LEN (BEAT_FREQ / 4) | |
#define MAX_STATE 9 | |
#define STATE_LEN 4 | |
// xmit - flag to start 38kHz IR LED modulation | |
// xmitstate - state machine for serial protocol | |
// currstate - currently selected digit [0-9] | |
// decimalmask - mask to set or clear decimal point | |
// butdeb - Button debounce counters | |
volatile int xmit=0, xmitstate=0, currstate=0, savestate=0, | |
decimalmask = DIS_DECIMAL_PT, butdeb[2] = {0,0}; | |
// Seven segment bit fields. Active low. {[0-9] E(rror)} | |
unsigned const char digits[] = { 0x82, 0xBB, 0xA4, 0xA1, 0x99, | |
0xC1, 0xC0, 0xAB, 0x80, 0x89, 0xC4 }; | |
void main(void) { | |
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer | |
BCSCTL1 = CALBC1_1MHZ; | |
DCOCTL = CALDCO_1MHZ; | |
P1DIR = 0xFF; // Set P1 to output direction | |
P1OUT = 0xFF; // Set the LEDs off | |
P2DIR = 0xFC; // Set P2.0/1 to input for buttons | |
P2OUT = 0x20; // Set IR LED off | |
P2REN = 0x03; // Enable pulldown resistors | |
P2IES = 0x03; // Positive edge trigger | |
P2IFG = 0x00; // Clear pin change interrupt flags | |
P2IE = 0x03; // Enable button interrupts | |
TACTL = TASSEL_1 | MC_1; // Set the timer A to ACLK, Up mode | |
TACCR0 = (0x8000 / BEAT_FREQ) - 1; // Reset timer at BEAT frequency | |
TACCTL0 = CCIE; // Clear the timer and enable timer interrupt | |
__enable_interrupt(); | |
while(1) { | |
while(xmit) { | |
// Delay some cycles to keep frequency at 38kHz | |
// This is much less than expected due to the | |
// lost time to the while loop's condition test | |
// and the bitwise math on P2OUT | |
// This value was found with an oscilloscope. | |
__delay_cycles(2); | |
P2OUT ^= BIT5; | |
} | |
// Turn off IR LED | |
P2OUT &= ~BIT5; | |
} | |
} | |
// Timer A0 interrupt service routine | |
#pragma vector=TIMER0_A0_VECTOR | |
__interrupt void Timer0_A0 (void) | |
{ | |
xmitstate = (xmitstate + 1) % BEAT_FREQ; | |
// Set transmit flag for START BIT3 BIT2 BIT1 BIT0 STOP | |
if (xmitstate == 0 || xmitstate == (STATE_LEN + 1)) { // START & STOP bits | |
xmit = 1; | |
decimalmask = EN_DECIMAL_PT; | |
savestate = currstate; // Prevent state from changing during xmit | |
} else if (xmitstate < (STATE_LEN + 1)) { // 4 bits of state MSBF | |
xmit = !((savestate >> (STATE_LEN - xmitstate)) & 0x1); | |
} else { | |
xmit = 0; | |
decimalmask = DIS_DECIMAL_PT; | |
} | |
// Update display | |
P1OUT = digits[currstate] & decimalmask; | |
// Decrement debounce counters, but only to zero | |
butdeb[0]?butdeb[0]--:1; | |
butdeb[1]?butdeb[1]--:1; | |
} | |
#pragma vector=PORT2_VECTOR | |
__interrupt void Port2 (void) { | |
// Increment state | |
if ((P2IFG & 0x02) && !butdeb[1]) { | |
butdeb[1] = BUTDEB_LEN; | |
currstate = (currstate+1) % (MAX_STATE + 1); | |
} | |
// Decrement state | |
if ((P2IFG & 0x01) && !butdeb[0]) { | |
butdeb[0] = BUTDEB_LEN; | |
currstate = currstate ? (currstate - 1) : MAX_STATE; | |
} | |
P2IFG = 0x00; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment