0
\$\begingroup\$

I have written a C program for the PIC18F4620. My PIC works as an encoder, which encodes a data stream in Manchester code. My output is rd7, where it should appear the Manchester code, but only appears 0 to 1 transitions. Can anybody help me? Here is my code:

#define MAX_BITS 12
#define MANCHESTER_BIT 1



sbit ENCODER_OUT at RD7_bit;

sbit DATA_OUT at RD6_bit;

sbit LED1 at RD0_bit;
sbit LED2 at RD1_bit;

unsigned int Encode_val;
unsigned char Encode_State;

unsigned int Encode_Count;

const unsigned char START_SYNCH = 0;
const unsigned char SYNCH = 0;
const unsigned char END_SYNCH = 0;
const unsigned char SETUP = 0 ;
const unsigned char TRANSITION = 0  ;
const unsigned char COMPLETE = 0 ;
const unsigned char IDLE = 0;
void Start_Transmission(unsigned int ) ;


void InitTimer0(){
  T0CON         = 0x88;
  TMR0H         = 0xFE;
  TMR0L         = 0x0C;
  GIE_bit         = 1;
  TMR0IE_bit         = 1;
  TMR0IF_bit = 0;
}

void InitTimer1()
{
  T1CON  = 0x01;
  TMR1IF_bit     = 0;
  TMR1H  = 0xFF;
  TMR1L  = 0x06;
  TMR1IE_bit     = 1;
  INTCON     = 0xC0;
}

void Interrupt(){

  if (TMR1IF_bit)
  {
      TMR1IF_bit = 0;
      TMR1H  = 0xFF;
      TMR1L  = 0x06;
      DATA_OUT = ~DATA_OUT;

  }


  if (TMR0IF_bit){
    TMR0IF_bit = 0;
    TMR0H      = 0xFE;    //5 Khz interrupts   0.2 ms  
    TMR0L      = 0x0C;
    LED2 = ~LED2;


 switch(Encode_State){

        case START_SYNCH:
            ENCODER_OUT ^= MANCHESTER_BIT; //bring line low, start synch pulse
            Encode_State = SYNCH;
            break;
        case SYNCH:
            Encode_State = END_SYNCH; // synch pulse needs to be twice the interrupt rate
            break;
        case END_SYNCH:
            ENCODER_OUT |= MANCHESTER_BIT; //bring the line high, end synch pulse
            Encode_Count =0;
            Encode_State = SETUP;
            break;
        case SETUP:
            if((Encode_val & 0x01))
                ENCODER_OUT = ((Encode_val & 0x01) | (ENCODER_OUT & MANCHESTER_BIT)); //next bit to transmit "1"
            else
                ENCODER_OUT = ((Encode_val & 0x01) & (ENCODER_OUT & MANCHESTER_BIT)); //next bit to transmit "0"
            Encode_State = TRANSITION;
            break;
        case TRANSITION:
            ENCODER_OUT = (Encode_val & 0x01) ^ MANCHESTER_BIT; //set the line for transition
            if(Encode_Count++ < MAX_BITS){
                Encode_val = (Encode_val >> 1);
                Encode_State = SETUP;
            }
            else
                Encode_State = COMPLETE;
            break;
        case COMPLETE:
            ENCODER_OUT |= MANCHESTER_BIT; //transition done, bring the line high
            Encode_state = IDLE;
        case IDLE:
        default:
            break;
 }
 }
}




void Start_Transmission(unsigned int val)
{
   int i, parity_bit_count =0;

    for(i=0; i < MAX_BITS; i++)
        if(((val >> i) & 0x0001) == 1)
            parity_bit_count++;

    if((parity_bit_count & 0x0001) == 1)
        val |= 0x8000;

    Encode_val = val;
    Encode_State = START_SYNCH;
}


void main() {
  TRISD = 0;         
  PORTD = 0;
  LED1 = 1;

  Start_Transmission(0);
  InitTimer0();
  InitTimer1();
}
\$\endgroup\$
  • 2
    \$\begingroup\$ It would be best if you were clearer about exactly what output signal is being produced vs. the one expected. Consider porting the core of your algorithm into a program which you can build for a PC and run to print output on the terminal and see if it does what you expect. If not, it will likely be easier to debug there. \$\endgroup\$ – Chris Stratton Jun 8 '16 at 19:01
2
\$\begingroup\$

You need to recheck your logic operations.
Your code:

if((Encode_val & 0x01))
  ENCODER_OUT = ((Encode_val & 0x01) | (ENCODER_OUT & MANCHESTER_BIT)); //next bit to transmit "1"
else
  ENCODER_OUT = ((Encode_val & 0x01) & (ENCODER_OUT & MANCHESTER_BIT)); //next bit to transmit "0"  

will evaluate to:

if(Encode_val & 0x01)
  ENCODER_OUT = 1;
else
  ENCODER_OUT = 0;  

because, if (Encode_val & 0x01) is true,
then ENCODER_OUT = ((Encode_val & 0x01) | (ENCODER_OUT & MANCHESTER_BIT))
becomes ENCODER_OUT = (1 | (ENCODER_OUT & MANCHESTER_BIT))
and (1 | anything) == 1
similarly, if (Encode_val & 0x01) is false,
then ENCODER_OUT = ((Encode_val & 0x01) & (ENCODER_OUT & MANCHESTER_BIT))
becomes (0 & (ENCODER_OUT & MANCHESTER_BIT))
and (0 & anything) == 0

You're also using an xor function in ENCODER_OUT ^= MANCHESTER_BIT and expecting the result to always be 0, but it will actually depend on the previous value of ENCODER_OUT.
I would rather do something like ENCODER_OUT = !MANCHESTER_BIT there.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.