Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] PIC bitwise operation

Status
Not open for further replies.

anishpsla

Member level 2
Joined
Dec 15, 2013
Messages
44
Helped
1
Reputation
2
Reaction score
1
Trophy points
8
Activity points
402

Code C - [expand]
1
2
3
4
5
6
7
8
int bump[] = {0,0,-1,1};
 
      state = 0;
      state = state + PORTB.RB0;
      state >> 1;
      state = state + PORTB.RB1;
      level = level + bump[state];
      Display_RPM(state);



The above code not working. I want to work the code something like this. I am using MikroC

consider PORTB.B0 = 1 and PORTB.B1 = 0

so state = 0b000000001 (Which is equal to 1dec)
next state = 0b00000010 + 0 = 0b00000010 (Decimal 2)
so level = 0 + bump[2] which is equal to 0+(-1)

In the above code, all the values are taken as decimal value and I am getting 10 or 20 as output.
 

line 4: state gets 0+1=1
In line 5 you shift it right, so state=0
line 6: 0+0

(And I'm not even sure you've got your TYPES correct)
 
I think the code you want is:

Code:
state = 0;
state = state + PORTB.RB0;
state = state << 1;
state = state + PORTB.RB1;
level = level + bump[state];
Display_RPM(state);

My questions are:
1. Where is level assigned a value?
2. Does this run inside of a loop?
 
the statement
Code:
      state >> 1;
has the result 0 but you do nothing with it (the value of state is not changed)

did you intend
Code:
      state >>= 1;
which shifts state one bit right?
 
Actually, it's a Arduino Rotor encoder library file, I want port it into MikroC for PIC.


Code C++ - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
const byte pinA = 2; 
    //encoder pin A to Arduino pin 2 which is also interrupt pin 0 which we will use
const byte pinB = 3; 
    //encoder pin B to Arduino pin 3 which is also interrupt pin 1 but we won't use it
 
byte state = 0; 
    //will store two bits for pins A & B on the encoder which we will get from the pins above
 
int level = 0; 
    //a value bumped up or down by the encoder
 
    //For demo purposes we will create an array of these binary digits *-
String bits[] = {-00-,-01-,-10-,-11-};
 
    //A truth table of possible moves 1 for clockwise
    //-1 for counter clockwwise 0 for error - keybounce *-
int bump[] = {0,0,-1,1};
 
void setup(){
 pinMode(pinA,INPUT); 
    //reads Pin A of the encoder
 pinMode(pinB,INPUT); 
    //reads Pin B of the encoder -* Writing to an Input pin turns on an internal pull up resistor *-
 digitalWrite(pinA,HIGH);
 digitalWrite(pinB,HIGH); 
    //Set up to call our knob function any time pinA rises *-
 attachInterrupt(0,knobTurned,RISING); 
    //calls our 'knobTurned()' function when pinA goes from LOW to HIGH level = 50; 
    //a value to start with 
    //Set up for using the on-screen monitor *-
 Serial.begin(115200); 
    //make sure your monitor baud rate matches this
 Serial.println(-Encoder Ready-);
 Serial.print(-level = -);
 Serial.println(level); 
    //to remind us where we're starting
}
 
void loop(){
}
void knobTurned(){
    //AH HA! the knob was turned *-
 state = 0; 
    //reset this value each time
 state = state + digitalRead(pinA); 
    //add the state of Pin A
 state --= 1; 
    //shift the bit over one spot
 state = state + digitalRead(pinB); 
    //add the state of Pin B 
    /* now we have a two bit binary number that holds the state of both pins 
        00 - something is wrong we must have got here with a key bounce 
        01 - sames as above - first bit should never be 0 
        10 - knob was turned backwards 
        11 - knob was turned forwards 
        We can pull a value out of our truth table and add it to the current level */
 level = level + bump[state]; 
    // Let's see what happened *-
Serial.print(bits[state] + - -); 
    // show us the two bits
 Serial.print(bump[state],DEC); 
    // show us the direction of the turn
 Serial.print(- -);
 Serial.println(level); 
    //show us the new value
}



https://www.youtube.com/watch?v=FGxLXqzPe3Q is the source for the above code. I saw many codes for MikroC but most are too heavy. I think the above one is light weight and easily port it into MikroC
 

Okay the code that I posted earlier does what you want.

The reason for why the code is increasing unexpectedly is more than likely because you are not waiting for the encoder to turn. The arduino code using an interrupt to detect a change on one of the pins. Only if there is a change does it call the function turn knobTurned. If you call the function in a loop without waiting for a change then the function will always increment or decrement depending on what state it currently stuck in.
 
I am also using interrupt. The code, I posted earlier was the Interrupt handler in MikroC.

I have some other doubt.


Code C - [expand]
1
2
3
4
5
6
state = 0;
 state = state + PORTB.RB0;
 state = state << 1;
 state = state + PORTB.RB1;
 level = level + bump[state];
 Display_RPM(state);



This is the code, you posted earlier. Just think PORTB.RB0 = 1 and PORTB.RB1 = 1 then what is the value of state in 5th line of code ? It's 11 Dec or 11 Hex or 11 Binary ? I declare state as Unsigned int. The result is 10 Dec or 11 Dec added to the current value of state. In the arduino code, state is byte in MikroC, there is no byte type variable.
 

This is the code, you posted earlier. Just think PORTB.RB0 = 1 and PORTB.RB1 = 1 then what is the value of state in 5th line of code ? It's 11 Dec or 11 Hex or 11 Binary ? I declare state as Unsigned int. The result is 10 Dec or 11 Dec added to the current value of state. In the arduino code, state is byte in MikroC, there is no byte type variable.

Yes that is the code you want. What it does is this:
The first line sets state to zero. The second line places a one or a zero in the least significant bit of state depending on the state of the input RB0. The third line shifts that bit that bit over one or multiples it by two. (Note shifting to the left keeps the bit, while shifting to the right removes the bit) The third line places a one or a zero in the least significant bit of state depending on the state of the input RB1.

So after the second line state will be 0 or 1. After the third state will be 0 or 2. After the forth state will be 0, 1, 2, or 3.

This is done using arithmetic and bit wise operations. The calculation is done in such a way that the variable type does not matter. Mainly due to the fact that we are using only the lower two bits. (The sign of the number is determined by the most significant bit.) The data is calculated and read in binary so there is not problem with it indexing outside of the array. The array length is 4 and the max value is 3, which points to the end of the array.

If you need a byte in C you can use any of the following: unsigned char, char, short, or unsigned short. You can always cast the data as one type or another to change the way the compiler reads the bits.
 
In the arduino code, state is byte in MikroC, there is no byte type variable.
In other words, you plan to review the mikroC manual for provided types? There's a table Integral Types in chapter 6 Language Reference.
 

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
unsigned int i,level,state = 0;
int bump[] = {0,0,-1,1};
char *value = "00";
 
void Display_RPM(unsigned int num){
  value[1] = (num/10)%10 + 48;
  value[0] = num%10 + 48;
  UART1_Write_Text(value);
 }
 
void main() {
     TRISB = 1;
     PORTB = 0;
     TRISC = 0;
     ADCON0 = 0;
     
     INTCON.GIE = 1; // Global Interrupt Enable
     INTCON.INTE = 1; // RB0/INT External Interrupt Enable bit
     
     UART1_Init(9600);               // Initialize UART module at 9600 bps
     Delay_ms(100);                  // Wait for UART module to stabilize
 
     while(1)
     {
      PORTC.RC1 = 1;
     }
}
 
void interrupt()       //Interrupt Handler
{
     INTCON.GIE = 0;   //Disable Global Interupt
     if(INTCON.INTF)  //RB0/INT External Interrupt Flag bit is set
     {
      state = 0;
      state = state + PORTB.RB0;
      state << 1;
      state = state + PORTB.RB1;
      level = level + bump[state];
      Display_RPM(state);
     }
     INTCON.INTF = 0; //Clear RB0/INT External Interrupt Flag bit
     INTCON.GIE = 1;  //Enable Global Interrupt
}



This is my test code. But it not working as I want.
 

Thanks for help from everyone. The actual problem was related to the Display_RPM function. The corrected code is posted here. Special thanks for bluelasers for correcting the shift left function.


Code C - [expand]
1
2
3
4
5
void Display_RPM(unsigned int num){
  value[0] = (num/10)%10 + 48;
  value[1] = num%10 + 48;
  UART1_Write_Text(value);
 }

 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top