Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

PIC programs can be made in assembly code or C. I think there are special PIC libraries for C which at least limits the requirement of assembly when programming PIC chips. Here's my PIC program for calculating mean averages from a list of inputed numbers:

Code: Select all

; Register Definitions:
These are definitions given to the registers by the PICMicro program for ease of use.
INDF    EQU 00

TMR0    EQU 01

PCL     EQU 02

STATUS  EQU 03

FSR     EQU 04

PORTA   EQU 05

PORTB   EQU 06

EEDATA  EQU 08

EEADR   EQU 09

PCLATH  EQU 0A

INTCON  EQU 0B

OPSHUN  EQU 81

TRISA   EQU 85

TRISB   EQU 86

EECON1  EQU 88

EECON2  EQU 89



TOTALA  EQU 0C
The right (Least significant) byte for the running total
TOTALB  EQU 0D
The left (Most significant) byte for the running total
COUNT   EQU 0E
Stores the number of numbers entered
WORANS  EQU 0F
Stores the count of how many times the count fits into the total. Stands for working answer.
ARITHA  EQU 10
Stores the next value for total A to be used when the count is taken away.


; Constant Definitions:
Put by the PicMicro program. 
W       EQU 00    ; Working

F       EQU 01    ; File





; Program Start:

        ORG 0



        GOTO   004            

        NOP                   

        NOP                   

        NOP                   

        BSF    STATUS,05      
Bit 5 of the STATUS register is set. This applies following commands to page 1 of memory.
        MOVLW  FF             
Move FF to the working register.
        MOVWF  TRISA          
Move the FF value to TRISA. All bits on port A are set to inputs.
        MOVLW  C0             
Move CO to the working register
        MOVWF  TRISB          
Moves the CO value to TRISB. The first two bits on port B are then inputs and the rest are outputs.
        BCF    STATUS,05      
Clear bit 5 on the SATUS register. Following commands apply to page 0 of memory. 


START   CLRF   COUNT          
Clear COUNT to 0
        CLRF   TOTALA         
Clear TOTALA to 0
        CLRF   TOTALB         
Clear TOTALB to 0


ENTRY   BTFSC  PORTB,07       
If bit 7 on port B is clear, skip the next command.
        CALL   ADD            
Bit 7 on port B is set, so call the ADD subroutine which is used to add a new number.
        BTFSS  PORTB,06       
If bit 6 on port B is set, skip the next command.
        GOTO   ENTRY          
Go back to the entry memory address, looping through it when input is needed.


LOOP    BTFSS  PORTB,06       
Bit 6 was set on port B so now skip if it is still set.
        GOTO   CALC           
Bit 6 was unset on port B. Now go to CALC to calculate and display the mean.
        GOTO   LOOP           
Go back to LOOP to check if it’s still set.


ADD     BTFSC  PORTB,07       
Skip if bit 7 on port B is not set.
        GOTO   ADD            
If still set, go back to ADD and loop until it is unset.
        GOTO   ADDCAL         
Go to ADDCAL to determine if another number can be added to COUNT, else calculate the mean since the numbers entered have reached the 255 limit.


ADDCAL  INCFSZ COUNT,F        
Increment COUNT and skip if zero (Hence arithmetic carry occurred)
        GOTO   ALLOW          
No carry, add another number by going to ALLOW.
        GOTO   DCCALC         
Carry occurred go to DCCALC to decrement COUNT back to 255 and then calculate the mean.
        RETURN                
Return to the ENTRY loop


ALLOW   MOVF   PORTA,W        
Move PORTA to the working register. Port A should contain the number that the user wants to add to the list of numbers to calculate the mean for.
        ADDWF  TOTALA,F       
Add this value to TOTALA
        BTFSC  STATUS,00      
If bit 0 on the STATUS register is set there has been a carry. Skip if clear
        INCF   TOTALB,F       
There has been a carry in TOTALA, so increment TOTALB.
        RETURN                
Return to the ENTRY loop


DCCALC  DECF   COUNT,F        
COUNT had been incremented to test for a carry but now need to be decremented to it’s value beforehand to calculate the correct answer
        GOTO   CALC           
Go to CALC to calculate and display the mean.


CALC    CLRF   WORANS         
Clear the WORANS to 0
        DECF   COUNT,F        
Decrement COUNT
        INCF   COUNT,F        
Increment it back
        BTFSS  STATUS,02      
COUNT was decremented and incremented again to test the STATUS register’s bit 2. If it is set COUNT is zero. This command will skip if the bit is set, hence when COUNT is zero.
        GOTO   CALTES         
COUNT was not zero hence, continue with the calculation by going to CALTES
        BSF    PORTB,05       
Set bit 5 on port B. This represents a division by zero error. The mean is total/count. If count is zero, this error should be shown.
        GOTO   ENTRY          
Zero division error. Go back to entry where the user should hopefully add some numbers before applying input to bit 6 on port B.


CALTES  BCF    PORTB,05       
Clear bit 5 on port B because there was no zero division error.
        MOVF   COUNT,W        
Move COUNT to the working register
        SUBWF  TOTALA,W       
Subtract the working register from TOTALA and leave the result in the working register.
        MOVWF  ARITHA         
Move the working register to ARITHA. ARITHA now contains TOTALA - COUNT
        BTFSC  STATUS,00      
Skip if bit 0 on the STATUS register is 0. The bit is set when there was no carry from the prior subtraction.
        GOTO   NUMSUB         
No carry, so go to NUBSUB because the COUNT was able to fit inside TOTALA
        DECF   TOTALB,F       
There was a carry so check TOTALB is zero by first decrementing.
        INCF   TOTALB,F       
Then incrementing back.
        BTFSC  STATUS,02      
If bit 2 on the STATUS register is set, the increment resulted in zero, hence TOTALB is zero. Skip if the bit is 0 (Not set).
        GOTO   EXLOOP         
TOTALB is zero, hence the entire total went below zero and the count could fit inside the total no longer. Go to EXLOOP to finish the calculation by rounding the number to the correct nearest whole number and then display the result.
        DECF   TOTALB,F       
TOTALB was not set so decrement it and continue with NUMSUB.


NUMSUB  INCF   WORANS,F       
Increment WORANS as another count was able to fit inside the total.
        MOVF   ARITHA,W       
Move ARITHA to the working register
        MOVWF  TOTALA         
Move the working register value to TOTALA. TOTALA now contains the result of removing COUNT from TOTALA from previous operations.
        GOTO   CALTES         
Go back to CALTES to continue the processing until the count can no longer fit into the total.


EXLOOP  MOVF   TOTALA,W       
Move TOTALA to the working register.
        SUBWF  COUNT,W        
Subtract the working register from COUNT and leave the result in the working register.
        SUBWF  TOTALA,W       
Subtract the working register from TOTALA and leave the result in the working register. The working register now contains the result of TOTALA – (COUNT - TOTALA) which is  the same as 2*TOTALA - COUNT
        BTFSS  STATUS,00      
Skip if bit 0 on the STATUS register is set, hence a carry.
        INCF   WORANS,F       
Increment WORANS because COUNT was not larger than twice TOTALA hence the result for the remainder division would be 0.5 or more.
        MOVF   WORANS,W       
Move WORANS to the working register
        MOVWF  PORTB          
Move the working register to port B hence displaying the answer.
        GOTO   START          
Goto the start to reset COUNT and the total and then to wait for user input again.


        END


Administrator
Administrator
Posts: 3307
Joined: Thu Dec 24, 2009 2:06 am
Allegiance:: Space Rome
Location: ON, Canada
User avatar
Administrator
Administrator
Re: C++/C programming discussion

Post by Scott »

No chips run C++ eh? That would be ideal but as far as I know it's fantasy. I guess I could take a crack at assembly as I don't really know if I want to learn C but assembly has always interested me because of it's complexity. Hopefully simple math won't be too difficult.
Image
Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

You should learn C in my opinion.
Administrator
Administrator
Posts: 3307
Joined: Thu Dec 24, 2009 2:06 am
Allegiance:: Space Rome
Location: ON, Canada
User avatar
Administrator
Administrator
Re: C++/C programming discussion

Post by Scott »

Matthew wrote:You should learn C in my opinion.
Considering C is so close to C++ could I assume that the chip software would look similar to a beginner math program with a chip library? I don't know anything about chipsets if you haven't already figured out.
Image
Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

What exactly do you mean? The mathematics will be similar as if you were making a normal C program but the IO wont be.
Administrator
Administrator
Posts: 3307
Joined: Thu Dec 24, 2009 2:06 am
Allegiance:: Space Rome
Location: ON, Canada
User avatar
Administrator
Administrator
Re: C++/C programming discussion

Post by Scott »

Matthew wrote:What exactly do you mean? The mathematics will be similar as if you were making a normal C program but the IO wont be.
That's what I meant. So my C knowledge won't have to be that extensive then right? Simply simple arithmetics, and then learn to program the chip, I assume with a library?

EDIT: I've started a tutorial to C and even though it's so similar to C++ it's a blast to learn a new language. It's like the feeling I got when I first started programming. Me thinks it's time to dabble in several more later...
Image
Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

You'll have to see for yourself what the chip holds. I think the C compiler is for the 32-bit PIC chips. I think those have 64 IO pins and I guess they are a bit more expensive,

Going from C++ to C you mostly need to look at the standard C library which isn't too hard to understand. Get used to C memory management with malloc.
Administrator
Administrator
Posts: 3307
Joined: Thu Dec 24, 2009 2:06 am
Allegiance:: Space Rome
Location: ON, Canada
User avatar
Administrator
Administrator
Re: C++/C programming discussion

Post by Scott »

I'm using this tutorial: http://www.cprogramming.com/tutorial.html

I am also looking at some of the more advanced C++ stuff as my book has been getting passed from person to person recently...
Image
Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

That website goes on about pointers far too much. I can explain them very quickly in this post.

A pointer is a reference to a variable, aka it's memory address. A pointer stores the memory address of a variable so you can access the variable by reference and manage the memory.

The compiler needs to know what data you are pointing to so it can dereference the pointer (Give you the variable it points to). To declare a pointer do this:

Code: Select all

datatype * varname;
You simply add an asterisk after the data type. You can add another asterisk to make a pointer to a pointer and so on. A pointer of a pointer will simply hold the address of a pointer. This is sometimes needed for arrays and modifying pointers in functions.

You can assign a reference to a variable to a pointer as follows:

Code: Select all

int * ptr = &integer;

The ampersand is the reference operator and gets the memory address of a variable (Just think it's the reference to the variable). You can now pass this pointer into a function (Make sure you declare the arguments with the asterisks if they are pointers) and you can modify the variable in the function when it's not a local variable. The variable isn't local but the pointer is.

To modify the integer you must dereference the pointer like:

Code: Select all

*ptr = 67;
The asterisk gets the variable from the pointer which it points to. You can do this on the left or right of assignment. On the right you can get the value for expressions:

Code: Select all

int new_int = *ptr + 40
The dereferenced pointer there gives the integer value which it points to.

Char pointers are pointers to characters. These make up strings:

Code: Select all

char * string = "Hello";
Here the pointer is to a char array because there is more than one char in the string. You can apply arithmetic to pointers:

Code: Select all

string++;
The pointer now points to the e and not the H. tHe C standard library uses a lot of pointers for stings because it has to basically as strings in C are pointers to char arrays. IT's not too complicated to think about it.

You should look up malloc which uses pointers. You can create dynamic arrays and data with malloc.

The NULL pointer points to an address which is not used and can therefore be applied to any pointer safely to represent something such as the data where the pointer should point not being initialised.

Code: Select all

char * some_string_not_yet_made = NULL;
Void pointers

Void pointers can point to anything but because the compiler does know what to dereference it to, you have to cast the pointer to something else first.

Code: Select all

void * ptr = &some_var;
int integer = *(int *)ptr; //If the variable is a integer this is fine.
Void pointers can be used to hold references to all types of different data in arrays and to pass different types of data into a function as long as the function can gather what to cast the pointer to.
Administrator
Administrator
Posts: 3307
Joined: Thu Dec 24, 2009 2:06 am
Allegiance:: Space Rome
Location: ON, Canada
User avatar
Administrator
Administrator
Re: C++/C programming discussion

Post by Scott »

I have a tendency (specifically with programming), that I can understand "how" way before I understand "when". More specifically I understand how pointers work but I don't know when to use them. From all the exercises ect, ect, I have never seen one time where I need them. I just recently figured out "when" to use classes.

One question though...

Code: Select all

void * ptr = &some_var;
int integer = *(int *)ptr; //If the variable is a integer this is fine.
What is

Code: Select all

*(int *)ptr;
?
Image
Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

Have you done typecasting before?

Code: Select all

(new_type)var
It converts the variable data type, this includes pointers. Pointers are represented as normal data types with asterisks after them. (int *) is therefore a cast to an integer pointer.

In that example the void pointer is being cast to an int pointer. This is because a compiler can dereference int pointers but not void pointer.

The asterisk at the beginning as with the other examples dereferences the pointer (Into an int).
Administrator
Administrator
Posts: 3307
Joined: Thu Dec 24, 2009 2:06 am
Allegiance:: Space Rome
Location: ON, Canada
User avatar
Administrator
Administrator
Re: C++/C programming discussion

Post by Scott »

Matthew wrote:Have you done typecasting before?

Code: Select all

(new_type)var
It converts the variable data type, this includes pointers. Pointers are represented as normal data types with asterisks after them. (int *) is therefore a cast to an integer pointer.

In that example the void pointer is being cast to an int pointer. This is because a compiler can dereference int pointers but not void pointer.

The asterisk at the beginning as with the other examples dereferences the pointer (Into an int).
Well you've lost me :lol: I have just recently (an hour ago) read up on type casting so the unfamiliarity isn't helping with an already confusing topic.
Image
Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

Type casting just changes the type. Eg. an integer to a float:

Code: Select all

float number = (float)(int1 - int 2)/integer;
Here you change the integer on the left of the division to a float so that the division wont be integer division and give an incorrect answer. You only need to do it on one operand for the division.

You can change void pointers to other pointers with casting just the same.
Administrator
Administrator
Posts: 3307
Joined: Thu Dec 24, 2009 2:06 am
Allegiance:: Space Rome
Location: ON, Canada
User avatar
Administrator
Administrator
Re: C++/C programming discussion

Post by Scott »

Is there a way to prevent unending loops? Ex. asking for an int but receiving a char causing a loop that never ends and usually creates a crash.

Oh, and I learn't C up to structs. I didn't both with them yet but will skim over the differences of C++ in a bit. They are extremely similar languages. So all I would need to learn in the PIC library then? Oh, another burning question, how do you get the code onto the chip?
Image
Jedi Master
Jedi Master
Posts: 336
Joined: Sun Aug 09, 2009 9:16 am
Allegiance:: Jedi
User avatar
Jedi Master
Jedi Master
Re: C++/C programming discussion

Post by Matthew »

I think you just need to know a library. I'm not sure.

You'll need a PIC programmer. They can cost various amounts. I've seem some for hundreds of pounds and others for about £30.

I haven't done proper C console input.... ever. I've done C++ but I forgot. I'll see for you. I believe C uses the function scanf()...

http://www.cplusplus.com/reference/clib ... dio/scanf/

Unlike the C++ rubbish, this nice C function should return 1 if the input is correct and there is one format specifier. It should return 0 if everything failed.
Post Reply