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.

New using PIC18F4520 with C Programming

Status
Not open for further replies.

mrfunkyjay

New Member
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();
}
}

}
 
im sorry but i dont really understand what are you trying to say. care to explain it more? thanks!
 
mrfunkyjay said:
Here are my codes. The LED is not even turned on when I pressed the S3 button (RB0 pin).

RB0 is an analog channel. You have to configure the ADCON1 to make it digital.
Code:
ADCON1 = 0x0F;

Also consider using a debounce routine when you read a switch.
 
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.
 
blueroomelectronics said:
I don't see any CONFIG statements. How are you setting the fuses?
mrfunkyjay said:
im sorry but i dont really understand what are you trying to say. care to explain it more? thanks!
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 **broken link removed**. 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:
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:
 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
 
This is an example of the pragma config lines:

Code:
#pragma CONFIG OSC = INTIO2
#pragma CONFIG WDT = OFF
#pragma CONFIG LVP = OFF
#pragma CONFIG DEBUG = ON
 
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:
#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:
#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:
#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:
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:
#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
 
mrfunkyjay said:
"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:
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:
mrfunkyjay said:
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?"
You can control the direction of each bit of a PORT by setting or clearing the corresponding TRIS bit: 0=output, 1=input
Code:
TRISA = 0b10000000;   // set RA7 to input; set RA0/6 to output
 
eng1 said:
You can control the direction of each bit of a PORT by setting or clearing the corresponding TRIS bit: 0=output, 1=input
Code:
TRISA = 0b10000000;   // set RA7 to input; set RA0/6 to output

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:
 
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 :)
 
A simple way to debounce a switch is,
Code:
    Previous=PORTAbits.RA4;
    DelaymS(10);
    if(PORTAbits.RA4==0 && Previous==1){	//New key press?

and to toggle a port pin,
Code:
    PORTDbits.RD1 = ~PORTDbits.RD1;

HTH

Mike.
 
@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!
 
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???
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top