Continue to Site

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.

  • 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.

PIC18F458

Status
Not open for further replies.

killivolt

Well-Known Member
Working out of a book; I am at a point the code provided does not seem to work right.

I'm a noob; I'm also using MPLAB's simulator. I run this code; but it skips my "switch" case statements?

What do you think is out of order.


Code:
Write A PIC 18 program to read RB0 and RB1 bits issue ASCII character to PD according to the following table:

RB1                          RB0
0                             0        send '0' to PORTD ( notice ASCII '0' is 0x30) "I got mixed up here."
0                             1         send '1' t0 PORTD
1                             0         send '2' to PORTD
1                             1          send '3' to PORTD


#include <p18f458.h>
void main(void)
  {
     unsigned char z;    
     TRISB = 0xFF;                                          //make Port B an input
     TRISD = 0;                                                //make Port D an output

       {
          z = PORTB;                                           //read Port B
          z = z  & 0x30;                                              //mask the unused bits

          switch (z)
       {
            case (0):                                              // issue ASCII  0
            {
              PORTD = '0';       
              break;
            }
            case (1):                                              //issue ASCII    1
            {
              PORTD = '1';
              break;
            }
            case (2):                                              //issue ASCII   2
            {
              PORTD = '2';
              break;
            }
            case (3):                                              //issue ASCII  3
            {
              PORTD = '3';
              break;
            }
         }
       }
     }

This is EDITED: It should be this z = z & 0x3; Not this z = z &0x30; //mask the unused bits

(I was confused about HEX value in the above statement and wrote the wrong thing for Z =)
 
Last edited:
When you do z = z & 0x30 the result is one of 0, 16, 32 or 48, not 0, 1, 2 or 3. Either change the case statements or change the line to z = (z & 0x30)>>4.

HTH

Mike.

Edit, wrong numbers.
 
When you do z = z & 0x30 the result is one of 0, 16, 32 or 48, not 0, 1, 2 or 3. Either change the case statements or change the line to z = (z & 0x30)>>4.

HTH

Mike.

Edit, wrong numbers.


First off. Thank you for the reply.

( Yes, when I run it in the debugger and select the "special registers" window as I remember it show'd decimal of "48" and character is "0" and the "Hex" value was "0x30")

When I get there I'll edit this post with the correct "Hex" value.

I'll shift it >>4 and find the result.

Thanks, again Pommie

kv
 
Last edited:
Ok, so I ran it again and it's still skipping after accessing case:0 and then moves to case:0's breakpoint line 17 case:0's break point BRA 0xea. Then skips to the end.

Here is the dis-assembly result:

Code:
17:                              break;
  00D6    D009     BRA 0xea
18:                            }
19:                            case (1):
20:                            {
21:                              PORTD = '1';
  00D8    0E31     MOVLW 0x31
  00DA    6E83     MOVWF 0xf83, ACCESS
22:                              break;
  00DC    D006     BRA 0xea
23:                            }
24:                            case (2):
25:                            {
26:                              PORTD = '2';
  00DE    0E32     MOVLW 0x32
  00E0    6E83     MOVWF 0xf83, ACCESS
27:                              break;
  00E2    D003     BRA 0xea
28:                            }
29:                            case (3):
30:                            {
31:                              PORTD = '3';
  00E4    0E33     MOVLW 0x33
  00E6    6E83     MOVWF 0xf83, ACCESS
32:                              break;
  00E8    D000     BRA 0xea
33:                            }
34:                         }
35:                       }
36:                     }


Code:
Here is the new code:


#include <p18f458.h>
void main(void)
  {
     unsigned char z;
     TRISB = 0xFF;
     TRISD = 0;
  
       {
          z = PORTB;
          z = (z & 0x30>>4);
      
          switch (z)
       {
            case (0):
            {
              PORTD = '0';
              break;
            }
            case (1):
            {
              PORTD = '1';
              break;
            }
            case (2):
            {
              PORTD = '2';
              break;
            }
            case (3):
            {
              PORTD = '3';
              break;
            }
         }
       }
     }
 
Hi KV,

For one thing I don't think you're supposed to have brackets around the case statement.

I'm not quite sure what you're saying is going wrong. A switch/case statement will only run one of the case statements, depending on the value of the switch variable. It's basically the same as if/else.

Matt
 
I've had a very pleasant night with friends in the pub so my response may be suspect. However, z=(z & 0x30 >>4) is not the same as z = (z & 0x30)>>4. It's all about priority.

Mike.
 
Hi KV,

For one thing I don't think you're supposed to have brackets around the case statement.

I'm not quite sure what you're saying is going wrong. A switch/case statement will only run one of the case statements, depending on the value of the switch variable. It's basically the same as if/else.

Matt

First off the book is a bit cryptic on this one. Not really diving in to deep; no big deal it was fun to run the code and see the result and toy with it a bit.


Now, it is running only one case no matter what I do the "Special Function Register" will only display PORTD = Hex "0x30", Decimal "48", Character is "0" (You are correct; just running one statement, the first one.)

I've tried several configurations "Pommie's" suggestion and was able to get it to stop on the 3rd case and break before moving to end. Still only with the above as the result in the "Special Function Registers"

I would have thought it would read differently coming out of case: 3 but it only sees the first and won't take the last.
 
You're reading PORTB to create the switch statement, yet PORTB doesn't appear to ever change. Since only the first case statement (z = 0) is the only one being hit, I expect that means PORTB is 0 (0x00) all the time. Try changing the values of PORTB and see if it changes which case statement is hit.
 
I've had a very pleasant night with friends in the pub so my response may be suspect. However, z=(z & 0x30 >>4) is not the same as z = (z & 0x30)>>4. It's all about priority.

Mike.

I did both and receive a different result each time; it was fun to watch. Although it is working as D8 said ( Just running one of the statements) and that's ok. This is all about me learning here so; it's all good:)

Thanks, again.

kv
 
You're reading PORTB to create the switch statement, yet PORTB doesn't appear to ever change. Since only the first case statement (z = 0) is the only one being hit, I expect that means PORTB is 0 (0x00) all the time. Try changing the values of PORTB and see if it changes which case statement is hit.

Ok.
 
Changed it to 0x32 same result.
 
In the watch window, what does it say the value of Z is?
 
Oh, and did you fix the priority of the >>4 as Mike said?
 
Yes, changed it to................ z = (z & 0x32)>>4;

Edit: z = (z & 0x32)>>4;
MOVLW 0x32
 
Last edited:
After changing the value of PORTB (effectively simulating inputs), what is the value of Z? Suppose you set PORTB = 0x02. Does the value of z (monitored in the watch window) change to 2?
 
[
You're reading PORTB to create the switch statement, yet PORTB doesn't appear to ever change. Since only the first case statement (z = 0) is the only one being hit, I expect that means PORTB is 0 (0x00) all the time. Try changing the values of PORTB and see if it changes which case statement is hit.

I didn't get this question you asked or at least the statement. I'm at work and doing this between jobs. Sorry about that....


Post #14 changed the value of z = (z & 0x02)>>4 PORTB is equal to "0x00" and "0" so apparently it's not placing the correct value like you said in post # 8.
 
[


I didn't get this question you asked or at least the statement. I'm at work and doing this between jobs. Sorry about that....


Post #14 changed the value of z = (z & 0x02)>>4 PORTB is equal to "0x00" and "0" so apparently it's not placing the correct value like you said in post # 8.

These lines:

Code:
z = PORTB;
z = (z & 0x30)>>4;

don't make much sense to me. You're setting z to PORTB, and then changing it right away. Did you change the value of PORTB? If not, you're going to get the same result every time.

Also, you have extra brackets in post #4, right after setting TRISTD, that do not belong there. Also, did you remove the brackets from inside the case statements?

I guess updated code would be helpful here :p
 
New code :p

Code:
#include <p18f458.h>
void main(void)
  {
     unsigned char z;
     TRISB = 0xFF;
     TRISD = 0;
   
     
          z = PORTB;
          z = (z & 0x02)>>4;
       
        
         switch (z)
       {
            case 0:
            {
              PORTD = '0';
            
            }
            case 1:
            {
              PORTD = '1';
           
            }
            case 2:
            {
              PORTD = '2';
           
            }
            case 3:
            {
              PORTD = '3';
              break;
            }
         }
       }

Edit: I removed the breaks on 0,1,2 the code is stopping now at those locations no change
 
Ok, once again, remove the brackets inside each case statement. I am pretty sure they don't belong there.

Second, get rid of the ''s around each number when you set PORTD.

Third, I did not mean change the z & ox.... statement to 0x02. I said change PORTB to 0x02 inside the watch window. I am pretty sure you can change register values in there. You must change the actual values of PORTB.

Finally, be careful about how you format your code. Make sure things are lined up properly, otherwise it may be difficult to follow. I am speaking from experience when I say that if you don't format the code properly, and you have an extra bracket somewhere (or are missing one), it's practically impossible to find.

Give these a try and post back (with fixed code) with the results :)

Regards,
Matt

EDIT: I'm actually not sure about the z = (z & 0x30)>>4 line. What is this supposed to accomplish? If you do change the value of PORTB t0 0x02, shifting right 4 bits is going to lop off that entire nybble. I really don't see the point in that entire line of code.
 
Update: When I went to "file Registers" window of the debugger (not) "Special Function Registers" I get 0,1,2,3 ASCII character. Seems to be working in the "File Registers"

I guess I don't know how to change the value of PORTB inside "Special Function Registers" but with this new code it seems to work now. When viewing the "File Registers"


Code:
#include <p18f458.h>
void main(void)
  {
     unsigned char z;
     TRISB = 0xFF;
     TRISD = 0;
  
    
          z = PORTB;
          z = z & 0x30;
      
       
         switch (z)
       {
            case (0):
            {
              PORTD = '0';
           
            }
            case (1):
            {
              PORTD = '1';
          
            }
            case (2):
            {
              PORTD = '2';
          
            }
            case (3):
            {
              PORTD = '3';
              break;
            }
         }
       }


Edit: It doesn't change when I have () or ' ' around case: or PORTD ' ' the "File Registers" show the same result as above.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top