Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
MSP430 IR Serial Demo
// 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;
}
// 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;
}
@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Jan 30, 2013

hi,
i have a problem in your code:
TAIV &= ~(0x02); - Error[Pe137]: expression must be a modifiable lvalue.
can you help me?
i'm using IAR.
Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.