• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Reading Input Pin

Status
Not open for further replies.

Ninacs Gergo

New Member
Hello
I am using an LM3S9B92 microcontroller and i want to connect it with a TSOP31238 IR receiver to do something when i press some buttons on the remote control.
I have been reading the documentation for this mC for hours now and I can't read the signal sent by the receiver.
The output pin of the IR receiver is connected to PA0 pin on the mC
GND of the receiver is connected to the GND pin on the mC
VCC of the receiver is connected to a 5V pin on the mC

I tried this code but it doesn't work



#define TARGET_IS_TEMPEST_RC1

#include "inc/lm3s9b92.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "utils/uartstdio.h"

#define RX_BUFFER_SIZE 16

int
main(void)
{

volatile unsigned long signal;
//
// Set the clocking to run directly from the crystal.
//
ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);

//
// Initialize the UART.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioInit(0);

UARTprintf("Finished initializing!\n");

while(1)
{
UARTprintf("Value: %x\n",ROM_UARTCharGet(UART0_BASE));/*
if (ROM_UARTCharsAvail(UART0_BASE))
{
UARTprintf("There are chars in the FIFO!\n");
UARTprintf("The value read is:%x\n", ROM_UARTCharGetNonBlocking(UART0_BASE));
}
else
{
UARTprintf("There are no chars in the FIFO!\n");
}

}
}

Can someone tell me what am I doing wrong? or How to properly read the signal sent by the IR receiver?

Regards,
Gergo
 

panic mode

Well-Known Member
i would be impressed if you did because i cannot see anything that reads the port...
inside loop there should be something that reads port a. i only see references to UART0_BASE...
 

Ninacs Gergo

New Member
The documentation says:
ROM_UARTCharGet
Waits for a character from the specified port.
Prototype:
long
ROM_UARTCharGet(unsigned long ulBase)
Parameters:
ulBase is the base address of the UART port.
Description:
Gets a character from the receive FIFO for the specified port. If there are no characters avail-
able, this function will wait until a character is received before returning.

same with:
ROM_UARTCharGetNonBlocking
Receives a character from the specified port.
Prototype:
long
ROM_UARTCharGetNonBlocking(unsigned long ulBase)
Parameters:
ulBase is the base address of the UART port.
Description:
Gets a character from the receive FIFO for the specified port.

That is why i tried like this. But it doesn't work, so if you could give me a good solution i would appreciate it
 

panic mode

Well-Known Member
i know and this is why i posted such reply.
i am not familiar with that controller but the idea is still the same:

Code:
main (void){

// initialize things like peripherals etc.
 configure this
 initiate that
 configure some more
 configure all you need

 // done with init, so now we do loop... 

    while (1) {
        value_PA0 = Porta_A & 0x01;  // something like this will read the port, adjust syntax to your platform
        UARTprintf("The value read is:%x\n",value_PA0);  // send value we read from PORTA
        delay(1000); // do not spam.. only send occasional message
   }

}
 

DirtyLude

Well-Known Member
He's thinking that the UART will be receiving a signal from the IR in serial format, not just a single 0 or 1 value. So he's writing on the UART what is received by the UART. I used the Stellaris a long time ago and I never used StellarisWare so I can't comment on whether the code is correct, but remote controls don't send serial data in the format that a UART reads, so your whole premise here is incorrect.

Different remotes send data in different ways and there is code out there for decoding the remotes signals. You would likely have to steal these functions from code for other microcontrollers, though. It would need to be connected to some kind of timer and interrupt to measure the pulse width of each signal so this might be a little advanced for you at this time.
 

panic mode

Well-Known Member
thanks for your reply, i looked over it again and a bit closer this time and what you say makes sense.
i should have some code for that worked for one of old remotes but it is for PIC24...
 

panic mode

Well-Known Member
here it is... copy (possibly newer) should be on Reese's website
Code:
/*
 * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
 * All rights reserved.
 * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
 * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
 * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the authors appear in all copies of this software.
 *
 * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
 * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Please maintain this header in its entirety when copying/modifying
 * these files.
 *
 *
 */
#include "pic24_all.h"

/** \file
 * Decodes bi-phase bitstream from IR remote control as output by IR receiver
 * Protocol is Phillips VCR control, 13 bit command (start bit, toggle bit, 5-bit address, 6-bit data)
 * Timer2 divider must be set such that one bit time does not exceed the timer period.
*/

#define IR_FIFO_SIZE 32
volatile uint8 au8_irFIFO[32];
volatile uint16 u16_irFifoHead = 0;
volatile uint16 u16_irFifoTail = 0;

void irFifoWrite(uint8 u8_x) {
  u16_irFifoHead++;
  if (u16_irFifoHead == IR_FIFO_SIZE) u16_irFifoHead = 0;
  au8_irFIFO[u16_irFifoHead] = u8_x;
}
uint8 irFifoRead() {
  while (u16_irFifoHead == u16_irFifoTail) {
    doHeartbeat();
  }
  u16_irFifoTail++;
  if (u16_irFifoTail == IR_FIFO_SIZE) u16_irFifoTail = 0;
  return au8_irFIFO[u16_irFifoTail];
}

/* no interrupt for Timer2, must be configured so that one bit time does
not exceed the Timer2 period.
*/
void  configTimer2(void) {
  T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF
          | T2_32BIT_MODE_OFF
          | T2_SOURCE_INT
          | T2_PS_1_64 ;   //at 40 MHz, approx 420 ms max, 1 tick = 1.6 us
  PR2 = 0xFFFF;                    //must be long enough so that one bit time does not overflow this
  TMR2  = 0;                       //clear timer2 value
  _T2IF = 0;                        //clear interrupt flag
  T2CONbits.TON = 1;               //turn on the timer
}

#define TWOTHIRDS_PERIOD_US 1100      //two thirds expected bit period, in microseconds
#define COMMAND_LENGTH  13            //number of bits expected in IR command
#define IR_INPUT _RB7                 //using RB9 for IR input

volatile uint16 u16_lastCapture, u16_thisCapture,u16_delta, u16_twoThirdsPeriodTicks;
volatile uint8 u8_bitCount,u8_bitCountTotal,u8_currentByte;
//some one-bit flags
typedef struct tagFLAGBITS {
unsigned u1_bitEdge:
  1;
unsigned u1_bitValue:
  1;
}FLAGBITS;
volatile FLAGBITS flags;

typedef enum  {
  STATE_START_PULSE_FALL = 0,
  STATE_START_PULSE_RISE,
  STATE_BIT_CAPTURE,
  STATE_LAST_EDGE,
} ICSTATE;

ICSTATE e_isrICState;

void _ISRFAST _IC1Interrupt() {
  _IC1IF = 0;
  u16_thisCapture = IC1BUF ;  //always read buffer to prevent overflow
  u16_delta = computeDeltaTicks(u16_lastCapture,u16_thisCapture,PR2);
  u16_lastCapture = u16_thisCapture;
  switch (e_isrICState) {
    case STATE_START_PULSE_FALL:
      e_isrICState = STATE_START_PULSE_RISE;
      break;
    case STATE_START_PULSE_RISE:
      if (u16_delta > u16_twoThirdsPeriodTicks) {
        //error, unexpected long pulse, reset back to start state
        e_isrICState = STATE_START_PULSE_FALL;
      } else {
        //received start pulse, start accumulating bits
        flags.u1_bitEdge = 1;   //next edge contains a bit
        u8_bitCount = 0;
        u8_currentByte = 0;
        flags.u1_bitValue = 1; //first bit is always a '1'
        u8_bitCountTotal = 0;
        e_isrICState = STATE_BIT_CAPTURE;
      }
      break;
    case STATE_BIT_CAPTURE:
      if ((u16_delta > u16_twoThirdsPeriodTicks) || flags.u1_bitEdge) {
        //record this bit
        if ((u16_delta > u16_twoThirdsPeriodTicks)) {
          //bit value has changed if wide pulse
          flags.u1_bitValue = !flags.u1_bitValue;
        }
        if (u8_bitCount != 0)u8_currentByte = u8_currentByte << 1;;
        if (flags.u1_bitValue) u8_currentByte = u8_currentByte | 0x01;
        u8_bitCount++;
        u8_bitCountTotal++;
        flags.u1_bitEdge = 1;  //this was a bit edge
        if (u8_bitCount == 7) {  //received start, toggle, address
          irFifoWrite(u8_currentByte);
          u8_currentByte = 0;
          u8_bitCount = 0;
        }
      }
      flags.u1_bitEdge = !flags.u1_bitEdge;  //next edge is opposite
      if (u8_bitCountTotal == COMMAND_LENGTH) {
        if (u8_bitCount != 0) irFifoWrite(u8_currentByte);  //save last byte
        if (IR_INPUT) e_isrICState = STATE_START_PULSE_FALL;
        else e_isrICState = STATE_LAST_EDGE;   //one more edge to come
      }
      break;
    case STATE_LAST_EDGE:
      e_isrICState = STATE_START_PULSE_FALL;
      break;

    default:
      e_isrICState = STATE_START_PULSE_FALL;
  }
}


//configure input capture.
void configInputCapture1(void) {
  CONFIG_RB7_AS_DIG_INPUT();   //use RB7 for IR Input (must be 5 V tolerant)
  CONFIG_IC1_TO_RP(7);         //map IC1 to RP7/R7
  e_isrICState = STATE_START_PULSE_FALL;
  u16_irFifoHead = 0;
  u16_irFifoTail = 0;
  u16_twoThirdsPeriodTicks = usToU16Ticks(TWOTHIRDS_PERIOD_US, getTimerPrescale(T2CONbits));
  IC1CON = IC_TIMER2_SRC |     //Timer2 source
           IC_INT_1CAPTURE |   //Interrupt every capture
           IC_EVERY_EDGE;      //Interrupt every edge
  _IC1IF = 0;
  _IC1IP = 1;
  _IC1IE = 1;   //enable
}

int main (void) {
  uint8 u8_x, u8_y;
  configBasic(HELLO_MSG);
  configTimer2();
  configInputCapture1();

  while (1) {
    u8_x = irFifoRead();
    u8_y = irFifoRead();
    if (u8_x & 0x20) outString("Toggle = 1, ");
    else outString("Toggle = 0, ");
    outString("Addr: ");
    outUint8(u8_x & 0x1F);
    outString(",Cmd: ");
    outUint8(u8_y);
    outString("\n");
  }
}
 

Ninacs Gergo

New Member
Thank you for your anwers.
DirtyLude thats exactly the case. I honeslty thought that the receiver will output a byte representation of the signal after it demodulates it and stuff.
panic mode I'm checking the code right now. Could you write a few main ideas about it? Just so i know what it does
 

panic mode

Well-Known Member
do you know what remote control you want to use? i guess if you use universal remote you could force it to use any supported format. the code uses interrupt that is triggered by both edges of the source signal (interrupt is triggered on both rising and falling edge). timer (in this case it is Timer2) is configured so that it's period is slightly shorter than duration of one bit received from the remote (they used time that is 2/3 of that incomming pulse). when timer expires bit value is captured, decoded and result is put into FIFO.

main program configures interrupt and timer, then executes loop in which FIFO is read and the values are printed. this is 16bit MCU and timers can be ganged for 32-bit operation (which is not used in this case, we don't need such long time). in 16bit operation and at instruction cycle of 40MHz, max duration of 16-bit timer is about half a second which is much longer than we need.

Time = (preset +1 )*prescaler/Fcy

here prescaler is 64 (T2_PS_1_64 is "timer2 prescaler of 1/64")
preset+1 is 65536 (PR2 = 0xFFFF; )
and MCU runs at 80MHz so instruction clock is Fcy=40MHz (it is divide by two for this family).

that gives time

T= 65536*(1/64)/40000000
T=0.0256ms
which corresponds to frequency of 39.0625 kHz
which is reasonable IR remotes use 38..40kHz.
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top