This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RC5 decoder IR with msp430g2553

Other Parts Discussed in Thread: MSP430G2553

hi,

i am trying with rc5 protocol with msp430g2553 for decoding Ir receive sequence.i have use gpio interrupt for IR output and timer for decoding the sequence. 

but only one cmd is executing when i test by giving TACCR0 = 1778; value i have configured system for 1MHZ

when i try with different value for  TACCR0 different cmds are executing

for example:

          if TACCR0 =2450

           1 and 9 command is working .

am not getting where i went wrong it seems k with the logic part can any one let me know with rc5 protocol fully.

i have gone through the document "slla 175"where they mentioned that 1.78ms for receiving each b it and 25 ms for 14 bit approximately. the code is given below

#include "msp430g2553.h"
#include "string.h"
//function prototype

void send_uart(char *data);
void send_uart1(char data);

#define IRDATA BIT4 // IR receiver on P1.4
#define RED BIT0 // Red LED on P1.0
#define T_INTERVAL 2450 // Timing between IRDATA samples - should be closer to 1778 with 1MHz clock, but mine runs fast. YMMV

int data = 0; // Hold the incoming IRDATA stream
int command = 0; // The command received
int address = 0; // The device address received
int toggle = 0; // The toggle bit from the IRDATA stream
int uiUartTransmitflag=0;
void main( void )
{
char chr[5];
//Initialization

WDTCTL = WDTPW + WDTHOLD; // Stop WDT , not used

//Calibrate DCO
BCSCTL1 = CALBC1_1MHZ; // DCO at 1 MHz
DCOCTL = CALDCO_1MHZ; // DCO at 1 MHz
BCSCTL2 &= ~SELS; // SMCLK source

// UART Set-Up
P1SEL |= 0x06; // Use P1.1 and P1.2 as USCI_A0
P1SEL2|= 0x06; // Use P1.1 and P1.2 as USCI_A0
P1DIR |= 0x04; // Set 1.2 as output
UCA0CTL1 |= UCSSEL_2; // Use SMCLK / DCO
UCA0BR0 = 104; // 1 MHz -> 9600 N=Clock/Baud
UCA0BR1 = 0; // 1 MHz -> 9600
UCA0MCTL = UCBRS1; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI

/*
* Set up the I/O pins
*/
// P1REN |= DEBUG_PIN ; // pullup resistor for timing debug pin
P1OUT |= RED ; // Set all these HIGH
P1DIR |= RED ; // Set all these as outputs
P1DIR &= ~IRDATA; // IRDATA is an input
P1IE = IRDATA; // enable interrupts, watching IRDATA for a change
P1IES = IRDATA; // watch for falling edge change on IRDATA

TACCR0 = T_INTERVAL; // Set the timing interval for TimerA

//General Interrupt Enable
_BIS_SR(GIE);

//Repeat this section

while(1)
{
// send_uart("Hello World\n\r");
// __delay_cycles(500000);
if(uiUartTransmitflag == 1){
uiUartTransmitflag=0;
chr[0]= ( char) command;
chr[1]= (char)address;
chr[2]= (char) toggle;
send_uart("Command,address,toggle\n\r");
send_uart1(chr[0]+0x30);
send_uart1(chr[1]+0x30);
send_uart1(chr[2]+0x30);
send_uart("\n\r");
// __delay_cycles(500000);
}
}
}

#pragma vector = PORT1_VECTOR;
void __interrupt Port_1(void)
{
P1IE &= ~IRDATA; // Turn off P1 interrupts while we work
P1IFG &= ~IRDATA; // clear the P1 interrupt flag for IRDATA
data = 1; // first start bit, inverted from receiver
//TODO: wait for second start bit within T_INTERVAL; abandon if it doesn't come.
// start timer
TACCTL0 |= CCIE; // enable timer interrupts
TACTL = TASSEL_2; // TimerA0 clock selection - SMCLK
TACCR0 &= ~CCIFG; // clear any pending timerA interrrupt flags
TACTL |= MC_1; // start the timer in UP mode
}
#pragma vector = TIMER0_A0_VECTOR
void __interrupt Timer0(void)
{
/*
* Need to track the state of a few things... the last toggle bit, the last command issued,
* the count of how many bits we have parsed.
*/
static int lastToggle;
static int lastCommand;
static char repeat = 0;
static int count = 0; // stop after all the bits have been read in

TACCTL0 &= ~CCIE; // clear the interrupt flag

if (count > 13) { // all bits read in and shifted into the data variable

TACTL &= MC_0; // stop the timer
TACTL |= TACLR; // clear the timer settings to zero it out

command = data & 0x3F;
address = (data >> 6) & 0x1F ;
toggle = (data >> 11) & 1;

P1IE |= IRDATA; // we have our IR command, reset and start listening for the next one
P1IFG &= ~IRDATA;
count = 0;

if (lastCommand == command && lastToggle == toggle) { // if we only want one toggle per keypress
repeat = 1;
// uiUartTransmitflag=1;
} else {
uiUartTransmitflag=1;
lastCommand = command;
lastToggle = toggle;
repeat = 0;
}

} else {
// read IRDATA and store the value in DATA
//P1OUT &= ~DEBUG_PIN; // uncomment this and the one a few lines down to see P1.3 toggle with each sample of IRDATA. Use a two channel oscilloscope to adjust T_INTERVAL as necessary.
if (data > 0) data <<= 1; // shift left one bit
if ((P1IN & IRDATA) != IRDATA) { // invert IRDATA if it is low, because the receiver is active low - append 'data' with a 1
data |= 1;
}
//P1OUT |= DEBUG_PIN; // as above, uncomment for timing debug use
count++;
TACCTL0 |= CCIE; // turn the timer interrupts back on for the next bit
}
}
void send_uart(char *data)
{
// P1OUT ^= BIT6; // Toggle LED

unsigned int i;
unsigned int size = strlen(data); //get length of data to be sent
for (i = 0; i < size; i++) {

while (!(IFG2 & UCA0TXIFG)); //Wait UART to finish before next send
UCA0TXBUF = data[i];
}

}
void send_uart1(char data)
{

while (!(IFG2 & UCA0TXIFG)); //Wait UART to finish before next send
UCA0TXBUF = data;

}

can any one let me know where i went wrong...

thanks & regards,

  • shyam reddy1 said:

    i am trying with rc5 protocol with msp430g2553 for decoding Ir receive sequence.i have use gpio interrupt for IR output and timer for decoding the sequence. 

    but only one cmd is executing when i test by giving TACCR0 = 1778; value i have configured system for 1MHZ

    when i try with different value for  TACCR0 different cmds are executing

    for example:

              if TACCR0 =2450

               1 and 9 command is working .

    am not getting where i went wrong it seems k with the logic part can any one let me know with rc5 protocol fully.

    For MSP430x2xx any RC support, I done it on this way...

    Port interrupter is used for wake-up and starting timer. When port input logic state is changed, timer value is stored in RAM, and timer is restarted. After all samples are collected, stream is compared against commands stored in flash. There is learning option (storing collected samples to flash), and all RC are supported.

  • hi soli,

                i tried in that way but i failed to get the commands,so i done in the above way by going through the datasheet.

    when there is change in the port pin the timer interrupt will be called and by taking the timer value comparison is done.actually this code i got reference from ti website itself.

    could you elaborate and tell me the procedure you followed so that i can proceed in that way.here is the procedure i followed previously.

    in my case the interrupt is generating but value after processing the data which i got is not a valid data.here the procedure of code which i followed.

    #include "msp430G2553.h"
    void Calculate_IR_code(void);


    unsigned int timer0=0, deltat = 0;
    unsigned char IR_Toggle;
    unsigned char result[100];
    unsigned char IR_address;
    unsigned char IR_command;
    unsigned char signal_IR_ready;

    void main(void){
    unsigned char i=0;
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    BCSCTL1 = CALBC1_1MHZ; // Set DCO to calibrated 1 MHz.
    DCOCTL = CALDCO_1MHZ;

    P1OUT = 0;
    P1DIR &= ~(BIT1|BIT2|BIT3);
    P1DIR |= (BIT0|BIT4|BIT5|BIT6|BIT7);

    P1SEL = 0x0;
    P1SEL2 = 0x0;
    P1SEL |= (BIT1|BIT2);

    TA0CCR0 = 0;
    TA0CTL = TASSEL_2 + ID_0 + MC_2 + TACLR;
    TA0CCTL0 = CM_1 + CCIS_0 + SCS + CAP + CCIE;
    TA0CCTL0 &= ~CCIFG;

    _enable_interrupt();

    while(1){
    asm(" NOP");
    if (signal_IR_ready==1){
    Calculate_IR_code();
    // Toggle GPIO11 if ON/OFF IR remote command has been received
    if(IR_command == 12) P1OUT ^= BIT6;
    // Prepare next run
    for(i=0;i<100;i++)result[i] = 0;
    signal_IR_ready=0;
    }
    }
    }

    void Calculate_IR_code(void){
    // compute device address and command code
    unsigned char i,ir_code=0;
    unsigned char current_bit,prev_bit;
    unsigned char error=0;
    if (result[0] != 'P'){
    error = 1; // sequence must start with a 'P'
    }else{
    current_bit = 1;
    ir_code = (ir_code<<1)+current_bit;
    prev_bit = current_bit;
    for(i=1;result[i]!='P';i++) {
    // short duration
    if((result[i] == 'S') && (result[i+1] == 'S')){
    current_bit = prev_bit;
    ir_code = (ir_code <<1)+current_bit;
    prev_bit = current_bit;
    i=i+1;
    }else{
    // long duration duration, toggle bit
    if (result[i] == 'L'){
    current_bit = (~prev_bit) & 0x0001;
    ir_code = (ir_code <<1)+current_bit;
    prev_bit = current_bit;
    }
    }
    }
    }
    IR_Toggle = (ir_code & 0x800)>>11;
    IR_address = (ir_code & 0x7C0) >> 6;
    IR_command = (ir_code & 0x3F);
    return;
    }


    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void CCR0_ISR(void) {
    deltat = TA0CCR0 - timer0;
    timer0 = TA0CCR0;

    static unsigned char begin_of_frame = 0; // switch
    static unsigned char end_of_frame = 0;
    static unsigned char result_idx = 0;

    if (begin_of_frame == 0){ // not yet found
    if (deltat > 5000){ // 5 ms as idle separator (RC-5 : 113ms)
    begin_of_frame = 1;
    result_idx = 0;
    result[result_idx++] = 'P';
    }

    if(deltat < 1250) // 1.25 ms
    result[result_idx++] = 'S'; // short width
    else
    result[result_idx++] = 'L'; // large width

    }else{ // begin_of_frame == 1
    if (end_of_frame == 0){ // not yet received
    if (deltat < 1250){
    result[result_idx++] = 'S';
    }else{
    if (deltat > 5000){
    end_of_frame = 1;
    result[result_idx++] = 'P';
    }else{
    result[result_idx++] = 'L';
    }
    }
    }
    }

    if (end_of_frame == 1){
    signal_IR_ready = 1;
    end_of_frame = 0;
    begin_of_frame = 0;
    result_idx = 0;
    }

    P1OUT ^= BIT0;
    TA0CCTL0 &= ~CCIFG;
    return;

    }

    i have tried this for a day and have gone for another logic which i posted previously.

    thanks & regards,

**Attention** This is a public forum