1. 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.
    Dismiss Notice

New using PIC18F4520 with C Programming

Discussion in 'Microcontrollers' started by mrfunkyjay, Apr 22, 2008.

  1. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    Hi all!

    I am facing difficulties in learning PIC18F4520 microcontroller with C Language programming. I have found several tuts but it seems I can't even turn on LED using Push Button on my PICDEM 2 PLUS Demo Board from Microchip.

    Does anyone use the same tools like mine?

    Here are my codes. The LED is not even turned on when I pressed the S3 button (RB0 pin).

    #include <p18f4520.h>
    #include <delays.h>

    #define LED1 LATDbits.LATD1 /*Green LED1*/
    #define LED2 LATDbits.LATD3 /*Green LED2*/
    #define LED3 LATDbits.LATD5 /*Green LED3*/
    #define LED4 LATDbits.LATD4 /*Red LED4*/
    #define LED5 LATDbits.LATD2 /*Green LED5*/

    #define ON 1
    #define OFF 0

    #define mLED1_Off() LED1 = OFF;
    #define mLED1_On() LED1 = ON;
    #define mLED1_Toggle() LED1 = !LED1;
    #define mLED2_Off() LED2 = OFF;
    #define mLED2_On() LED2 = ON;
    #define mLED2_Toggle() LED2 = !LED2;
    #define mLED3_Off() LED3 = OFF;
    #define mLED3_On() LED3 = ON;
    #define mLED3_Toggle() LED3 = !LED3;
    #define mLED4_Off() LED4 = OFF;
    #define mLED4_On() LED4 = ON;
    #define mLED4_Toggle() LED4 = !LED4;
    #define mLED5_Off() LED5 = OFF;
    #define mLED5_On() LED5 = ON;
    #define mLED5_Toggle() LED5 = !LED5;

    void main()

    {
    /*Setting PORT D as Output*/
    LATD = 0x00;
    TRISD = 0x00;

    /*Setting PORT B as Input*/
    TRISB = 1;

    while(1)
    {
    if (PORTBbits.RB0)
    {
    mLED1_On();
    }
    else
    {
    mLED1_Off();
    }
    }

    }
     
  2. blueroomelectronics

    blueroomelectronics Well-Known Member

    Joined:
    Jan 21, 2007
    Messages:
    12,536
    Likes:
    168
    Location:
    Toronto, Canada
    I don't see any CONFIG statements. How are you setting the fuses?
     
  3. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    im sorry but i dont really understand what are you trying to say. care to explain it more? thanks!
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. eng1

    eng1 New Member

    Joined:
    Apr 7, 2006
    Messages:
    951
    Likes:
    19
    Location:
    Italy

    RB0 is an analog channel. You have to configure the ADCON1 to make it digital.
    Code (text):
    ADCON1 = 0x0F;
    Also consider using a debounce routine when you read a switch.
     
  6. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    How about the other one? there is also another push button located at RA4 while the other is RESET.

    Hmm.. I have no basic, so perhaps you guys would find it difficult to explain to me. I wonder how a microcontroller "read" the status of a push button being pushed or not. How to generate it in C program Language?

    Thanks.
     
  7. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    What Bill means is that somewhere at the beginning of your code there should be some statements (or pragma's) that tell the compiler what type of oscillator you want to use, what speed it is and how other chip config options should be set (on the 18F's there's a LOT of them). Turn off the WDT and LVP. Enable MCLR. Stuff like that.

    For details see Chapter 23 of the datasheet. You do have a copy of the datasheet, don't you? If you intend to get anywhere with this stuff, that's the first place to look.

    Second place to look is the Midrange Manual. This set of docs covers the same material as the datasheet, but in more detail. Sometimes things get inadvertantly left out of the datasheet and you need to refer to the MRM to get the info you need.

    You should also refer to the manual for the compiler you're using. That will tell you how to do the config statements. Different compilers have different ways of doing it.
     
    Last edited: Apr 22, 2008
  8. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    And another thing! When you post code here, be sure to put it inside Code tags. Easiest way is to click the # in the menu just before pasting your code. Alternately, you can type in
    Code (text):
     before your code and [/co de] (without the space) after your code. This forces the web-site to keep your formatting so people can actually read your code. When you don't do this, it turns into the unreadable lump in your original post.

    It should look like this:
    [CODE]#include <p18f4520.h>
    #include <delays.h>

    #define LED1 LATDbits.LATD1 /*Green LED1*/
    #define LED2 LATDbits.LATD3 /*Green LED2*/
    #define LED3 LATDbits.LATD5 /*Green LED3*/
    #define LED4 LATDbits.LATD4 /*Red LED4*/
    #define LED5 LATDbits.LATD2 /*Green LED5*/

    #define ON 1
    #define OFF 0

    #define mLED1_Off() LED1 = OFF;
    #define mLED1_On() LED1 = ON;
    #define mLED1_Toggle() LED1 = !LED1;
    #define mLED2_Off() LED2 = OFF;
    #define mLED2_On() LED2 = ON;
    #define mLED2_Toggle() LED2 = !LED2;
    #define mLED3_Off() LED3 = OFF;
    #define mLED3_On() LED3 = ON;
    #define mLED3_Toggle() LED3 = !LED3;
    #define mLED4_Off() LED4 = OFF;
    #define mLED4_On() LED4 = ON;
    #define mLED4_Toggle() LED4 = !LED4;
    #define mLED5_Off() LED5 = OFF;
    #define mLED5_On() LED5 = ON;
    #define mLED5_Toggle() LED5 = !LED5;

    void main()
    {
        /*Setting PORT D as Output*/
        LATD = 0x00;
        TRISD = 0x00;

        /*Setting PORT B as Input*/
        TRISB = 1;

        while(1)
        {
            if (PORTBbits.RB0)
            {
                mLED1_On();
            }
            else
            {
                mLED1_Off();
            }
        }
    }
    Unfortunately you can't change the default tab width on this website. It assumes 8 space tabs, which works fine with assembler code, but badly with C code. C code typically has 4 or fewer space tabs. But still it's better than the lump. :p
     
  9. Krumlink

    Krumlink New Member

    Joined:
    Aug 10, 2007
    Messages:
    2,080
    Likes:
    20
    Location:
    Michigan, USA
    This is an example of the pragma config lines:

    Code (text):


    #pragma CONFIG OSC = INTIO2
    #pragma CONFIG WDT = OFF
    #pragma CONFIG LVP = OFF
    #pragma CONFIG DEBUG = ON


     
     
  10. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Here's yet another tip. :p You have so many #defines cluttering up the top of your code. Since you don't need to see them all the time, just put them in a header file with the same name as your C file, but with an H suffix. Put your function prototypes in there too. No point in seeing those things very often either.

    For instance, I'm working on a file called bleh.c. I make a file called bleh.h and put all the clutter in there. The file should be in the same dir as your C file. Put an include at the top of your C file like this:
    Code (text):
    #include "bleh.h"
    An include in quotation marks like that tells the compiler to look in the current directory for the file.

    An include inside these marks <> tells the compiler to look in the compiler's library dir.

    Here's a simple example. First, a little Junebug blinky program called blinky2.c:
    Code (text):
    #include "blinky2.h"

    void main(){
        int length=250;
        osccon = 0x72;
        trisa = trisb = 0;
        lata = latb = 0;
       
        while(1){
            led0();
            delay_ms(length);
            led_off();
            delay_ms(length);
            led1();
            delay_ms(length);
            led_off();
            delay_ms(length);
            led2();
            delay_ms(length);
            led_off();
            delay_ms(length);
            led3();
            delay_ms(length);
            led_off();
            delay_ms(length);
            led4();
            delay_ms(length);
            led_off();
            delay_ms(length);
            led5();
            delay_ms(length);
            led_off();
            delay_ms(length);
        }
    }

    void led0(void){
        trisa = 0b10111110;
        lata.0 = 1;
        lata.6 = 0;
    }
    void led1(void){
        trisa = 0b10111110;
        lata.0 = 0;
        lata.6 = 1;
    }
    void led2(void){
        trisa = 0b00111111;
        lata.6 = 1;
        lata.7 = 0;
    }
    void led3(void){
        trisa = 0b00111111;
        lata.6 = 0;
        lata.7 = 1;
    }
    void led4(void){
        trisa = 0b01111110;
        lata.0 = 0;
        lata.7 = 1;
    }
    void led5(void){
        trisa = 0b01111110;
        lata.0 = 1;
        lata.7 = 0;
    }
    void led_off(void){
        lata.0 = 0;lata.6 = 0;trisa.7 = 0;
    }
    and then the blinky2.h file for it:
    Code (text):
    #include <system.h>
    #pragma CLOCK_FREQ  2000000
    #pragma DATA _CONFIG1H, _INTIO2_OSC_1H
    #pragma DATA _CONFIG2H, _WDT_OFF_2H
    #pragma DATA _CONFIG3H, _MCLRE_ON_3H
    #pragma DATA _CONFIG4L, _LVP_OFF_4L

    void led0(void);
    void led1(void);
    void led2(void);
    void led3(void);
    void led4(void);
    void led5(void);
    void led_off(void);
     
     
    Last edited: Apr 22, 2008
  11. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    Dear futz,

    thanks! your tips are really helping me making things simpler! Yet I have came into a result where I can make series of blinking LEDs (4leds) when S2 is pressed. I recovered from headache and am thinking carefully, so I ended up like:

    Code (text):

    #include <p18f4520.h>
    #include <delays.h>

    void main(void)

    {  
        /*Settings*/
        TRISD=0b00000000;
        TRISA=0b11111111;

        while(1)
        {
            if (PORTAbits.RA4 == 0)
            {
            PORTDbits.RD1 = 1;
            Delay10KTCYx(30);
            PORTDbits.RD1 = 0;
            PORTDbits.RD3 = 1;
            Delay10KTCYx(30);
            PORTDbits.RD3 = 0;
            PORTDbits.RD5 = 1;
            Delay10KTCYx(30);
            PORTDbits.RD5 = 0;
            PORTDbits.RD4 = 1;
            Delay10KTCYx(30);
            PORTDbits.RD4 = 0;
            }
        }
    }
     
    Yes I am setting the PORT D for output as you may see above. The blinking time is controlled by Delays.h included in .h file. So I am excited, very excited. This is the first time I can program a push button to operate my LEDs.


    Human, are never satisfied, me too. :D


    I want to modify my program now. Before I read this forum I have finished the code above so the #pragma variables I haven't touched it yet. So, back to topic.

    I want to make several modifications to the Push button S2 (RA4) on the demo board. I want to program so that when I pressed the button once, the blinky LEDs are looping forever until I pressed the button twice, it stops.

    I am really noob to C programming but my spirit to learn is big. So if you guys would kindly help, I think you can lead my way here by helping me.

    Another things which are questions:

    1. Assigning I/O for TRIS command is kinda amusing for me. I spent like 6 hours looking for hints and tips in writing it onto the C Language. I ended up knowing that

    TRISA is assigned for PORT A, making the value equal to 0b00000000 means you make this PORT A as an output. By making the value to 0b11111111 means you make this PORT B as an input. my question is really simple, but noob like me find it very difficult to understand.

    "How do you assign PORT A in register RA7 for ex as input BUT the other at that PORT are output?"

    2. I tried programming a LED with LAT and PORT command:

    PORTAbits.RA1 = 1; /*Turn on LED at RA1*/
    LATAbits.LATA1 = 1; /*Turn on LED at RA1*/

    Both are equals, LED at RA1 turned on, but Where is the difference??? :confused:

    For your attention, I would like to say BIG THANKS! Cheers.

    Best regards,

    Kelvin
     
  12. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Normally you should use LATA/B/C/D/E for outputting to ports. It's a "shadow register" or "latch register". Using it avoids a problem that sometimes happens known as the Read/Modify/Write problem that happens if you write directly to one bit of a port like PORTA and immediately write to another different bit of the same port. Sometimes the first bit is still in the process of changing and when you write the second one so quickly the first one gets messed up. Using the latch register fixes that completely.
     
    Last edited: Apr 22, 2008
  13. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    Hmm, what about the first question?? care to answer it? thanks!! :)
     
  14. eng1

    eng1 New Member

    Joined:
    Apr 7, 2006
    Messages:
    951
    Likes:
    19
    Location:
    Italy
    You can control the direction of each bit of a PORT by setting or clearing the corresponding TRIS bit: 0=output, 1=input
    Code (text):
    TRISA = 0b10000000;   // set RA7 to input; set RA0/6 to output
     
  15. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    So, I can conclude that:

    7 6 5 4 3 2 1 0 <<< Bit
    0b 0 0 0 0 0 0 0 0 <<< C Language

    If I want to make the RA4 input and the rest output, hence:

    TRISA = 0b00010000;

    correct??? :rolleyes:
     
  16. eng1

    eng1 New Member

    Joined:
    Apr 7, 2006
    Messages:
    951
    Likes:
    19
    Location:
    Italy
    That's correct.
     
  17. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    I want to make now several modifications to my push button S2 (RA4).

    I want to make it like this.

    When I pressed it once, LEDS switched on forever until I pressed the push button again, then LEDS switched off.

    Could somebody tell me, what variable do I need. Or simply said, make it a puzzle for me to find/dig it out myself. By this, I can learn. Thank you :)
     
  18. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    ONLINE
    A simple way to debounce a switch is,
    Code (text):

        Previous=PORTAbits.RA4;
        DelaymS(10);
        if(PORTAbits.RA4==0 && Previous==1){    //New key press?
     
    and to toggle a port pin,
    Code (text):

        PORTDbits.RD1 = ~PORTDbits.RD1;
     
    HTH

    Mike.
     
  19. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    @Pommie:

    Woah! It is really new to me and I don't get what you mean. Hmm.. I want to ask u 1 thing, what is Previous here means? Is the symbol && equal to LOGIC AND? Is the ~ symbol means negation?

    Thanks!
     
  20. bananasiong

    bananasiong New Member

    Joined:
    Mar 7, 2006
    Messages:
    1,893
    Likes:
    7
    Location:
    Malaysia
    Previous is the temporary storage (10 ms ago) for RA4.

    And you're right about the symbols.
     
  21. mrfunkyjay

    mrfunkyjay New Member

    Joined:
    Mar 26, 2008
    Messages:
    123
    Likes:
    0
    Location:
    Jakarta, Indonesia
    Okay, to make this thing clear... the way I'm thinking is:

    Getting the previous state of PORTAbits.RA4

    and

    if the previous state of PORTAbits.RA4 is 1 and now the PORTAbits.RA4 is 0,

    Do negate the PORTDbits.RD1 which means, LED goes off.

    Am I correct???
     

Share This Page