Moving from assembly to C PIC microprocessors

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
I have been writing asm in MPLab for a few years and want to move over to C. I have a good background in asm and also wrote an iPhone app a few years ago in Objective C 2.0.

I have had a scan through the Microchip C Compiler user guide but wanted to know of any good information on starting programming in C for the PIC.

I know ErnieM will have an answer :)
 

John P

Joined Oct 14, 2008
2,026
Get a compiler and MPLab and get to work!

Personally I prefer BoostC. I can't stand the way Microchip's compiler functions as sneerware, always reminding you how much better your program would be if you had the paid-for version.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
I've been using mplab for a few years now programming in assembly.

As you say, I should just get a compiler and have a go. It's just that I know all the different ways if doing stuff in assembly, and there seems like hundreds if different commands in C to get to know. I suppose I just have to use Google when I need to know how to do something at see what commands are available.
 

enggricha

Joined May 17, 2014
89
Been programming PICs for almost 10 years now, have used HiTech Compilers all along you could give them a try, lots of documentation online for a starter.

I know migration from assembly to C can be slightly intimidating, but then you dont have a choice...sooner the better.
 

MrChips

Joined Oct 2, 2009
30,808
Ask the question, which is more difficult, ASM or C?

After you have learned C, please come back and give us your answer.

Fortunately for you, you are learning about microcontrollers in the proper progression. Most would have great difficulty and perhaps no desire to go from C to ASM.
 

ErnieM

Joined Apr 24, 2011
8,377
Whatever compiler you pick is just fine. I would tend to stay with microchip compilers since their libraries are quite inclusive (for my needs anyway).

Whatever compiler you choose find tutorials written FOR that compiler; there are subtle differences between C here and C there so best you stick with one thing for now.

Microchip seems to have finally updated their intro tutorials. Sorry no link I am out of town for the weekend.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Right. I had a quick play today with XC8. I have a issues which are bugging me.

First off I wanted to get an LED to flash (after recently programming an i2c interface in assembly this feels like I'm back at school). I have a header file which I produced using the "Window, PIC memory views, configuration bits" and c main file. The program compiles and it runs on the PIC (sort of), but the red underlined words and the error saying "Unable to resolve identifier" is killing me.




Right, onto the problem with the actual PIC.

Here is the config from my header file:

Rich (BB code):
// CONFIG
#pragma config FOSC = INTRCCLK  // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Selection bits (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
Please can someone tell me why even though MCLRE is set to OFF, if I ground that pin, it resets the program.

And lastly, In the main program, I have RC0 on for 250ms then off for 250ms which is looped. When I run this in real life, the led connected to RC0 goes on and off 3 times at the correct 250ms pauses, but after the 4th time on, it flicks off for a very short amount of time and the sequence start again.

I tried changing the delays to 500ms, and when I do that, every second time the LED is on, it stays on a little longer than it should.

I also tried using a __delay_ms(25) looping it 20 times, but this also gives the same result.


Any help on anything I've written here will be great. It would be nice to start using C, but already these timing issues are a bit worrying.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Ok. I got a few things sorted now.

I moved all of the #pragma lines into the main c file and the LED blinks as it should and also the MCLR is disabled as I want.

I had the #include <pic16f690.h> in the main c file, but after adding that line to the header file, the red underlines are gone apart from the ones under the __delay_ms.


Surely if I have included xc.h in my project and the delay works when my PIC is programmed, why is it still underlined in red?

Also, what stuff should go in the header file, all that I seem to need in there is the include for xc.h and for pic16f690.h?


Thanks again :)


Edit:

I spoke too soon. After shutting down MPLab and then a bit later deciding to do a bit more work on it, I opened up my project file and the stupid red underlines were back, not just under the __delay_ms, but also under RC0, where I have the statement: PORTCbits.RC0 = 1

I haven't changed anything, so why is MPLab X behaving like this? I also noticed that if I type PORTCbits. sometimes it had a drop down list containing RC0, RC1 etc. but this isn't there now either. What is going on?
 
Last edited:

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Hi The_RB. I just loaded MPLab again this morning and the red underlines under RC0 are gone and also the ones on the OSCCONbits.IRCF0 etc.

Also, when I type OSCCONbits. a drop down appears with the various options in that particular register, like you would expect.

I really don't understand why sometimes the compiler recognises the endings, sometimes it doesn't. But as I said before, it does compile even if the red underline is there.

Oh, I still have the red underline under __delay_ms, I haven't found any soultion for that yet.
 

THE_RB

Joined Feb 11, 2008
5,438
Check the help file language reference for "functions" and find the delay functions. The function names should all be shown along with examples.

You may need to change __delay_ms() to delay_ms() or something as simple as that.
:)
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Thanks for the reply. I have tried everything and visiet many sites on the net where people have the same issue. The thing is __delay_ms() does actually work, it seems the XC8 compiler is red lining it for some reason.
 

ErnieM

Joined Apr 24, 2011
8,377
Oh, I still have the red underline under __delay_ms, I haven't found any soultion for that yet.
From what I've read MPLAB X still has issues such as this. I'm finally using it for the first time and beyond issues (now resolved) with it seeing PICkits I've not had these issues.

The real test for code is if the code compiles. If so, ignore the auto hint stuff.

The built in delay functions for XC8 are described in Appendix A of the "MPLAB XC8 C Compiler User’s Guide" which is on your hard drive; it installs along with and along side XC8.

Short version of the delays are:

Rich (BB code):
    __delay_ms(x) // request a delay in milliseconds
    __delay_us(x) // request a delay in microseconds
    __delaywdt_ms(x) // request a delay in milliseconds
    __delaywdt_us(x) // request a delay in microseconds
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Cheers ErnieM. The code does compile correctly and works, so I'll just ignore the red underline.

I've managed to get i2c working in C now, reading and writing to a DS3231 real time clock module. I'm still finding C a bit tricky, but I think in the long run it'll be easier and quicker than using assembly.

I did find setting and clearing bits in an 'unsigned char' a bit tricky until I stumbled upon these few #define instructions::

Rich (BB code):
// testing and setting individual bits
#define testbit(var, bit) ((var) & (1 <<(bit)))
#define setbit(var, bit) ((var) |= (1 << (bit)))
#define clrbit(var, bit) ((var) &= ~(1 << (bit)))
It's going OK so far, but there's lots to learn :)

Could you explain how the 3 statements work please
 

MrChips

Joined Oct 2, 2009
30,808
The three statements behave like "macros".

Whenever you use the statement, for example,

testbit(PORTC, 3)

the preprocessor replaces the statement with:

( (PORTC) & (1 << (3)))

I will leave it as an exercise for you to figure out how this works.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Cheers Mr. Chips.

OK. I've been trying something for hours but I can't get it to work.

I have a file called i2c_C.h and a file called i2c_C.c
These 2 files have code etc. in them to read and write to the i2c data bus which I have tested and work. I then created a new project and wanted to include the functions that I built into i2c project.

So, I created a new project called Test. Went to the XC8 compile options and set the 'Include directory' to where i2c_C.c and i2c_C.h are located.

In the Test.c file of my new project I used #include <i2c_C.h>

Now in my new project I call a function which is on i2c_C project. The function call is 'wait'. I have the line wait(); It isn't underlined in red, so I assume the compiler knows where the function is. But when I come to compile it, I get the error:

:0: error: (499) undefined symbol:
_wait(dist/default/production/Test.X.production.obj)

What am I doing wrong? I can't find anything about this anywhere
 
Last edited:

MrChips

Joined Oct 2, 2009
30,808
You are beginning to run into problems associated with project organization. This is typical with first time users. It takes awhile getting the hang of it.

Organize your code in .c files.
Do not put code in .h files.
Use .h files for declaring constants, data types, and function prototypes that are needed by the .c file.

Reserve the #include <filename> for system files
Use #include "filename.h" for your headers and keep the files in your own folder
then you don't have to change the include directory.

The bottom line is:

declare the prototype with void wait(void); in the .h file.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Hi,

I tried what you said but I still get the error.

OK,

In the i2c_C.h file, I have declared the functions I use in my i2c_C.c file.
In the i2c_C.c file, I have the actual code, the includes for xc.h etc. and my #define statements.

The project compiles and works, but shouldn't the #defines be in the .h file? If I put them there and not in the .c file it fails to compile. What am I doing wrong?

On a few tutorials, they also put the #pragma config statements in the .h file, again, they only seem to work if I put the, in the C file.


I wrote an iPhone app a few years ago in Objective C 2.0, but XC8 seems to work a lot differently to that.
 
Last edited:

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
OK. I just put the include i2c_C.h in the .c file and now I can compile with all of my define statements and #pragma statements in the .h file. Right that bit is sorted and it still compiles.

Now, when I come to my new project 'Test', and I include i2c_C.h I still get the error, even after making the function wait 'void wait(void)'

What am I missing?


In Microchip's XC8 Getting started guide, it seem to put everything in the .c file
 
Last edited:
Top