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

Right, I don't think you want to use the SFR window, you do want the File Register (I think--it's been a while).

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

Just checking, we are talking about {}, not (). Brackets, not parentheses. Instead of

Code:
case (0):
{
       PORTD = '0';          
}

it should be

Code:
case (0):
      PORTD = '0';
      break;

Oh, and you MUST have a "break" statement. I don't know why you took that out.
 
I put the break at case:3 and it will print 0,1,2,3.

With the break; on cases: 0 - 1 - 2 - 3 it will go to 0 and skip 1 - 2 - 3.

I removed {} out of the case and is still the same in FR. So, I think it works fine with your suggestion or the way it was before regardless. Tried both and my problem was the break statements in the middle I think?
 
No, the break is absolutely necessary. What you're seeing is caused by every case statement executing in a row. You only want one to execute per loop.

This actually brings me to something I can't believe I didn't see before--you don't have this in a loop. Of course it's only going to execute once!

Just before the lines:

Code:
z = PORTB;
z = z & 0x30;

you should open a while(1) loop, and the rest of the code should sit inside that loop.

So you're just trying to increase the value of PORTD each iteration of the loop? Then what are you using PORTB for, if you don't have any inputs? I'm not following your logic on this at all, to be honest :p

And you really should not have ''s around the numbers. They should be removed.

EDIT: Also, why did you take out the >>4?

FURTHER EDIT: Ignore what I said about the loop. I wrote that with a misunderstanding of what you were trying to do. I can't really help until you tell us what this code is intended to do.
 
you're just trying to increase the value of PORTD each iteration of the loop? Then what are you using PORTB for, if you don't have any inputs? I'm not following your logic on this at all, to be honest :p



Like I said; my book I'm working out of didn't tell me what this particular piece of code was supposed to do; so I don't either? :confused:

So, that's what I'm currently doing is play around with it:)

and I don't know why I removed >>4 taking it out or putting back in doesn't seem to change anything.


Thanks for your help; I'll keep working on it and testing. I have however been able to get PORTB to register 0x32 in the disassembly listing now; however I can't get it to pass it to PORTD and read it in the SFR.

This is what I wrote recently:


Code:
#include <p18f458.h>
void main(void)
  {
     unsigned char z;
     TRISB = 0xFF;
     TRISD = 0;
  
    
          z = PORTB;
          z = z & 0x32;
      
       
         switch (z)
     
       {
            case (0):
         
              PORTD = '0x30';
             break;
         
            case (1):
         
              PORTD = '0x31';
             break;
         
            case (2):
         
              PORTD = '0x32';
           break;
         
            case (3):
         
              PORTD = '0x33';
              break;
         
         }
       }
 
Last edited:
Maybe an explanation of a few things might help. In C values can be represented in many ways, 48, 0x30, 0b00110000, '0' "01234" (and it seems '01234') will all result in the value 48 decimal. The quotes may confuse people but all they do is single quotes return the ascii value of the (first) character within and double quotes return a zero terminated string. Your compiler is converting (casting) a string to a single character and using it's ascii value. So PORTD = '0x78' (or any other number) will be equivalent to PORTD = 48 (ascii for 0, the first character).

When you AND a value you 'keep' certain bits. z = z & 0x30 will keep bits 4 and 5 as 0x30 = binary 00110000. ANDing with 0x32 (00110010) will also keep bit 1. Is this what you intended?

The >>4 moves the value right 4 binary places and so converts 0x30 (00110000) to 0x03 (00000011).

HTH

Mike.
 
As I read; so much is popping up; making sense. I will look into it tomorrow; our hrs are so different on the other side of the world. Yes your points are spot on; but this is one of those book and MPLAB things. First the book is older and MPLab has updated since then I think? Not sure which though. LOL - I'll dig down tomorrow........if work permits of course:)

Edit: Of course I did find one issue with the book; it was something rather different. But, was of course an issue none the less. If it's also the same of course; it becomes just one those books without a reason. But, you are on a good track with it; I'll look into it tomorrow; I'm just hoping not over the weekend.

Thanks, Pommie.

kv
 
Last edited:
Maybe an explanation of a few things might help. In C values can be represented in many ways, 48, 0x30, 0b00110000, '0' "01234" (and it seems '01234') will all result in the value 48 decimal. The quotes may confuse people but all they do is single quotes return the ascii value of the (first) character within and double quotes return a zero terminated string. Your compiler is converting (casting) a string to a single character and using it's ascii value. So PORTD = '0x78' (or any other number) will be equivalent to PORTD = 48 (ascii for 0, the first character).

When you AND a value you 'keep' certain bits. z = z & 0x30 will keep bits 4 and 5 as 0x30 = binary 00110000. ANDing with 0x32 (00110010) will also keep bit 1. Is this what you intended?

The >>4 moves the value right 4 binary places and so converts 0x30 (00110000) to 0x03 (00000011).

HTH

Mike.

Ok, this is what the book say's at the top. In it is the exact code example.

Code:
      // Write a code PIC C18 program to read the RB0 and RB1 bits and issue a
                   // ASCII character to PD according to the following table.

                                                    // RB1       RB0
                                                   //  0          0         Send  '0' to  PORTD (Notice ASCII '0'is 0x30)
                                                   //  0          1         Send  '1'  to 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 & 0x3;         //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;
            }
         }
       }
     }
 
Last edited:
I'm assuming

Code:
// RB0       RB0

is supposed to be

Code:
// RB0       RB1

I wish you had posted this at the start :p
 
Maybe an explanation of a few things might help. In C values can be represented in many ways, 48, 0x30, 0b00110000, '0' "01234" (and it seems '01234') will all result in the value 48 decimal. The quotes may confuse people but all they do is single quotes return the ascii value of the (first) character within and double quotes return a zero terminated string. Your compiler is converting (casting) a string to a single character and using it's ascii value. So PORTD = '0x78' (or any other number) will be equivalent to PORTD = 48 (ascii for 0, the first character).

When you AND a value you 'keep' certain bits. z = z & 0x30 will keep bits 4 and 5 as 0x30 = binary 00110000. ANDing with 0x32 (00110010) will also keep bit 1. Is this what you intended?

The >>4 moves the value right 4 binary places and so converts 0x30 (00110000) to 0x03 (00000011).

HTH

Mike.

Mike, that is what I intended. z = z & 0x3 or 0x03. I became mixed up and put 0x30.

Once I understood my "MIX UP" I was able to get the code to stop on case: '3'

However, somehow the simulator will not take the value for z and pass it to PORTD; might be something going on with the simulator?

I'm waiting for a PIC18F458 and I'll try it on a real device instead of MPLAB's simulator. For some reason the simulator will not take the value for z and pass it to PORTD?

If I find something else out I will post it here; but for now if someone else tries this they might be fighting the simulator I think?

Thanks, to Mike and D8 as well as a "Special Thanks" to "3v0" who spent a "considerable amount" of time. To help me better understand literals and how to use the "Watch Window" in the Debugger and mashing my code a bit or 2.

I don't want to waist anyone else's time on this; so for me I'm going to get back to dig down in the book. I need to know more assembly and learn how to read the data sheet amongst others.

Cheers:D

kv
 
Last edited:
This code on the other hand runs perfectly displays the Characters in the SFR correctly:

Code:
//Write a C18 program to convert packet BCD 0x29 to ASCII and display the bytes on PORTB and PORTC


//Solution:
#include <p18f458.h>
void main(void)

   {
       unsigned char x, y, z;
       unsigned char mybyte = 0x29;
       TRISB = 0;                  
       TRISC = 0;                         //make Ports B and C  output
       x = mybyte & 0x0F;                //mask upper 4 bits
       PORTB = x | 0x30;                 //make it an ASCII
       y = mybyte & 0xF0;               //mask lower 4 bits
       y = y >>4;                          //shift it to lower 4 bits
       PORTC = y | 0x30;                //make it ASCII
   
   }
 
Update: I was able to get this to work by adding a OR and changing to LATB and LATC; I can't get it to work with the PORTB or PORTD I have to use the Latch.



Code:
#include <p18f4580.h>


void main(void)

   {
     unsigned char z;      
     TRISB = 0xFF;             //make Port B an input

     TRISC = 0;                //make Port C an output


       {
          z = LATB;            //read LATB
          z = z & 0x03;
          LATB = z | 0x03;     //added

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

Edit: Since I have ran the code over and over it's un-predictable the first time through. First time through it will just do "0" or 0x30. But if I run it through again it will take the Value from LATB and pass it to LATC and then push it to PORTC.
 
Last edited:
You shouldn't use the LAT registers to read from the port, only to write to them. They are to prevent Read-Modify-Write errors when writing to the port.
I don't understand why you are writing to the LATB register when PortB is an input. When you are reading LATB, you are reading the value you wrote there last time, not the value on the port. It is being used just like a normal memory location.
You can use a default in your switch statement which will run if none of the cases are true.
When you AND the data with 0x03 and then OR the data with 0x03, the result will always be 0x03.
 
Last edited:
This should work:

Code:
#include <p18f4580.h>


void main(void)
{
   unsigned char z;  
  
   TRISB = 0xFF;  //make Port B an input
   TRISC = 0;  //make Port C an output
  
   while(1){
     z = PORTB & 0x03;  //read LATB

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

If it doesn't work it's because your portb read isn't working or changing.
 
Thank you for your response; if you have MPLAB 8.92 and a C18 Compiler you can run the code and see it for yourself.

PORTB is not reading and been the trouble this hole time. I received information from "3v0" about this 2 days ago. Thats when he suggested looking for the problem using the "Watch Window" and switching to LATB and LATD to see where the problem was; he realized that the simulator is not working as it should and something was wrong either PORTB or PORTD or the Simulator.

I let it go hoping the "Thread" would die. Until yesterday?

I began to think about what "3vo" said; suddenly I thought why not use "LATC" and "LATB" then add an "OR" which was used in "Example of post #31 out of my book?" I can see in the "SFR" that it works; using the above code with PORTB and PORTD does not work.

However, only with the above code in Post #32 with the addition of the OR '|'

I just happened to get lucky with it. But, "3v0" is correct; there is something wrong with PORTB or PORTD or the Simulator that isn't working? I hope no one else's waist any time on this. But, I have received good information I can use in the future. I hope someone else wanting learn "c" like me can benefit from all my mistakes.

Thank you for help and interest but this is just examples for someone wanting to learn "c" programming and toy around a little with MPLAB's program. Hopefully I'll blinking LED's and running more complex programs in the future but for now. It's just all about learning:)

Thanks again, for your input.

Cheers, kv
 
Last edited:
Update, I was able to finally mask the bit on PORTB "3" or "0x03" and send "2" to PORTC with this code. PORTD still refuses to be anything other than 0xFF or "0" or 0x30.

Code:
/
// Write a code PIC C18 program to read the RC0 and RC1 bits and issue a
// ASCII character to PORTC according to the following table.

                       // RC1   RC0
                       //  0     0   Send '0' to PORTC (Notice ASCII '0'is 0x30)
                       //  0     1
                       //  1     0
                       //  1     1
                                  
#include <p18f458.h>


void main(void)


   {
     unsigned char z;             
     TRISB = 1;                           //make Port B an input, I did change this from 0xFF
                                                   //Following the Datasheet not the book. 
     TRISC = 0;                         //make Port C an output; this was changed from PORTD
                                                  //I could never make PORTD work?
     ADCON1 = 0x06;             //I added this and the book I followed did not say I needed PORTS as Digital.
                                                 //I'm not sure I did this correct Datasheet shows 0x07 or 0x06
  

           {
          z = PORTB ;                  //read LATB
          z = z  &  0x03;     
          PORTB = z | 0x03;     //I added an OR that was not in the original from the book.
      
          switch (z)
            {
            case (0):                     //issue ASCII  0
            {
              PORTC = '0';               
              break;
            }
            case (1):                     //issue ASCII  1
            {
              PORTC = '1';
              break;
            }
            case (2):                     //issue ASCII  2
            {
              PORTC = '2';
              break;
            }
            case (3):
            {
              PORTC = '3';           //issue ASCII  3
              break;
            }             
            
            }
         }
       }
 
Last edited:
TRIS is made up of 8 bits, one for each port pin. TRISB=1 only sets the bottom bit and therefore only portb bit 0 (RB0) is an input. Set it back to 0xff and it should work correctly. I don't understand what you are trying to achieve with the 0r 0x03 as that line will always write 3 to portb!

The reason the book didn't mention ADCON1 is because the analogue pins are on ports a and e only and you don't use those.

Mike.
 
Tried it back to 0xFF on TRISB and PORTB remains "0" no input?

I also commented out ADCON1 and with TRISB = 1 it still works.

ADCON1 didn't change anything and I have removed ADCON1.

I commented out PORTB = z | 0x03; and portb will not take an input either.

Only with it included will it take "3" into LATB and then pass "2" to PORTB and then on to PORTC.

However, initially "PROTC" during the first machine cycle will begin 0x30 or ASCII "0" after the second machine cycle changes to 0x32 or ASCII "2"

This of course is not done on a real "PIC" yet; I've yet to run the first code out of the book with one. I'm still learning how to hook it up properly; I'll let you know my progress here.


Thanks, Pommie.

p.s. This is the data sheet I've been working from. https://ww1.microchip.com/downloads/en/DeviceDoc/41159e.pdf


kv
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top