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.

Need PIC Assembly Help: Changing variable sets to be placed in subroutine "CALL"...

Status
Not open for further replies.
In the summer I plan to get setup and do some beginner programming, I hope it's not going to be this difficult:rolleyes:

Nothing difficult, the problem here 'appears' to be the OP not understanding what he's wanting/trying to do, and also been unable to explain it to others. Unfortunately he's rather 'fallen in the trap' of confusing assembler directives and actual code, and I suspect most of his problems probably stem from that?.
 
I explained how the program works only 6 times. One reading the thread carefully would have a better understanding. That said below is a simplified flowchart for any suggestions:
Simplified Flowchart:
1- Set Values for Color1, Color2, Color3 (variables used by the main program to set colors).
2- Main Program is called. Main sets the bits for PORTB, and places variables above in PORTA one at a time, and does puedo-pwm (modulates). PortB sets the anodes, while PORTA sets R,G,B (Cathodes) in the hardware.
3- Main calls an OUTPUT routine where Bytes in PORTA, and PORTB are pushed out. This completes one entire cycle.
4- Set new values for Color1, Color2, Color3
5- Call Main Program
6- Main calls the Output routine
7- Repeat this process for new values of Color1, Color2, Color3 (25 times)

Still not very clearly written. Does it do this;

1. sets up 3 colour values.
2. does manual PWM on porta/b pins, to make 3 LEDs display a specific colour
2b. it displays that colour for HOW LONG?
3. after that time period, it transmits some data on porta/b (HOW?)
(repeats at 1, but with NEW colour values)

It looks fairly straightforward. There are 3 simple block functions.

As for loading 25 sets of "3 colours" that is easy, you just use a lookup table with 25*3 values, or if you prefer you can use 3 lookup tables, each with 25 values.

I think if you post a scehmatic diagram showing the 3 LEDs and the "data comms" output that will help a lot.
 
To the previous comments, OP knows what he wants and the program works fine. The program has 1300 lines of codes that I did not put up to bore everyone with it. Also I did not wnt to let the cat out of the box until it was completed. The main code is very interesting concept and perhaps a new approach to RGB decoding and multiplexing. So here is the entire concept and then I will address a very simple issue that is bugging me to death.

What is the function of the device: This a 12 RGB color wave improvement on my previous projects using PIC16F628A with all pins used up. 8-bits of PortB along with 4-bits of PortA are used as drivers (source positive) to anodes of 12 RGB LEDs (common anode). All the R,G, and B of 12 LED's are tied together forming 3 bus lines R, G, B. These buses are sunk (to ground) via 3 transistors. Last remaining unused bits of PortA control the bases of these transistors. Software: creates an envelope of R,G,B during which 12 channels are modulated in different values without use of PWM of PIC. This allows for much crisper and more vivid colors with minimum of 33% duty cycle! The main program grabs 8 bits data and places it in PortB. Then it grabs 4 bits of data and places it in first 4 bits of PortA. This completes 12 channels sourcing. During each complete cycle, we call R, G, and B and add these bit values to existing codes already in PortA containing the source bits (4 channels of 12). I was able to decode everything needed to create moving rainbow affect on 12 channels without any issues since I use hard bianary numbers in the code where R, G, and B are used. I wanted to be able to give the program different combination of R, G, B (not just a single color) to create a lot more affects not just limited to normal moving rainbow (Example: Pink, to Green, to Orange). Again if you place hard numbers in the color calls it works perfectly. Now I wanted to be able to create subroutines placing 3 colors in 3 variables and call the main program to morph these colors. This requires 3 color set values to be placed in 3 variables, then ask the main program to place these variable in so called coloring segment of the main program. (replacing plain R, G, B) This simple transfer of data from subroutines to variables in main program is the issue that I can not resolve. I am not sure if it has to do with how the variables are declared or what. It is the very simplest issue that is bugging me down.
 
Last edited:
I am currently reading up examples of table lookups and storing values in EEPROM. I will give it a good try to see if PIC treats those values placed in variables any differently.
 
Maybe I dont understand the situation, my programs use global and local sub variables, all of that is just down to how you adress the variables.

If you define a variable as say 'colour' then that variable will be the same no matter what code is executing, uoi could modify 'colour' in the interrupt routine then access it in the main program and its the same variable.

I had to read the thread heading twice as I thought you were programming in C, this sor of issue would be more likely with a higher level language.
 
I am currently reading up examples of table lookups and storing values in EEPROM. I will give it a good try to see if PIC treats those values placed in variables any differently.

I suspect you might do better if you forget the idea of 'variables'? - there are PIC GPR's (General Purpose Registers) and it's up to you what you do with them, one use is to use them as 'variables', but you need to do so in a consistent manner (as with any programming).

You've still never explained how you trigger the change you want in the 'variables'?, is it from an external stimulus, or simply a timed progression through the program? (like one set of values for x seconds, the second set for y seconds, third set for z seconds etc.)

The advantage of the table method is so you can have much higher numbers of values, for a small number a simple MOVLW/MOVWF is all that's required.

So assuming three GPR's, named VAR1, VAR2, VAR3 - something like this:

movlw 0x23
movwf VAR1
movlw 0x16
movwf VAR2
movlw 0xFB
movwf VAR3

As simple as that.
 
Here is a cross section of the program. It has all the major components based on the working model. Please look at Subroutines labeled Red, Green, Blue at the end of the program. These are the infamous binary numbers that I would like to change over and over. Normally I call Rainbow, Rainbow calls Frames, Frames call Sections, Sections call Output. Notice first line of Output, this is where the address bits from the section call is added to the color bit. To have the program do what I need is to change these bianary numbers in Red, Green, Blue then call the Main Rainbow program to do its thing. That means to change the hard numbers (binary) to varaibles and then in the beging outside the program put values in the variable and call the main program to run with it.

I tried simple routine doing movlw, and movwf as you suggested Nigel. It does something funky with the values. The result is that it grabs the first color as first color, then grabs first color and repeats it for second color, and then sets zero to third color. So I get Red, Red, zero. The second attempt was to create a routine lines: Color1 set b'00010000', Color2 set b'01000000' and so on. Program took it with no problem. Now as we discussed and one of the gents pointed out if I repeat these "set" commands it overwrites the previous. So per your suggestion I removed all the routine with "set" lines. Now back to square one. This is so simple I feel dumb-founded.
 
Rainbow12
call Frame1
call Frame2
call Frame3
call Frame4
call Frame5
call Frame6
call Frame7
call Frame8
call Frame9
call Frame10
call Frame11
call Frame12
call Frame13
call Frame14
call Frame15
call Frame16
call Frame17
call Frame18
call Frame19
call Frame20
call Frame21
call Frame22
call Frame23
call Frame24
Return
;--------------------------------------------------------------
Frame1
movlw d'10'
movwf FrameCount
FR1 call Red
call Sec1
call Blue
call Sec2
call Green
call Sec3
decfsz FrameCount,F
goto FR1
return



;---------------------------------------------
Sec1
movlw d'50'
movwf LoopCount
loop1
movlw b'00001111'
movwf copyPORTB
movlw b'00001110'
call Output
movlw b'00001111'
movwf copyPORTB
movlw b'00001110'
call Output
movlw b'00000111'
movwf copyPORTB
movlw b'00001100'
call Output
movlw b'00000111'
movwf copyPORTB
movlw b'00001100'
call Output
movlw b'00000011'
movwf copyPORTB
movlw b'00001000'
call Output
movlw b'00000011'
movwf copyPORTB
movlw b'00001000'
call Output
movlw b'00000001'
movwf copyPORTB
movlw b'00000000'
call Output
movlw b'00000001'
movwf copyPORTB
movlw b'00000000'
call Output
decfsz LoopCount,F
goto loop1
return
;---------------------------------------------
.
.


;--------------------------------------------
Red
movlw b'00010000'
movwf copyPORTA
return
;---------------------------------------------
Green
movlw b'01010000'
movwf copyPORTA
return
;---------------------------------------------
Blue
movlw b'10010000'
movwf copyPORTA
return
;---------------------------------------------
Output
addwf copyPORTA,0 ;content of w from SEC# is added to copyPORTA which has color (Ex: 10000000 = Blue)
movwf PORTA ;the result of addition is place in w and then transfered to PORTA directly
movfw copyPORTB
movwf PORTB
return
;---------------------------------------------
end
 
This is what I added to the block above that did not work....
Header
Cblock
.
.
.
Color1
Color2

Endc
;----------------------------------------
(Tris and bank setup)
(Initialize all variables)
;------------------------------------
Sequence
call Colorset1
call Rainbow12
call Colorset2
call Rainbow12
goto Sequence
;------------------------------
Colorset1
movlw b'00010000'
movwf Color1
movlw b'10000000'
movwf Color2
movlw b'00010000'
movwf Color3
return
;----------------------------------
Colorset1
movlw b'10010000'
movwf Color1
movlw b'10000000'
movwf Color2
movlw b'01010000'
movwf Color3
return
;----------------------------------
Rainbow12 (Starts here)
.
.
return
 
Last edited:
Color1, Color2, and Color3 are placed in end subroutines: Red, Green, Blue.
Example:
Red
movlw Color1
movwf copyPORTA
return
 
How do you setup the GPRs? Do you need to declare them in Cblock? Do you store them in memory location of GPR? (i.e. 0x20 to 0x7F)
I was reading about Global, Extern, udata, and res in MPASM Assembler and could not make sense of what they were saying and how it was setup. When I tried their instructions I got error level 149: directive only allowed when generating an object code.
 
Last edited:
You're over complicating things - check my tutorials which show how simple things are.

You also need to post your entire code, and to do so within code tags (click on go advanced to get that option) in order to keep the formatting correct.

Like this:

Code:
;Tutorial 2.3 - Nigel Goodwin 2002
	LIST	p=16F628		;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	__config 0x3D18			;sets the configuration settings (oscillator type etc.)

	cblock 	0x20 			;start of general purpose registers
		count			;used in table read routine
		count1 			;used in delay routine
		counta 			;used in delay routine 
		countb 			;used in delay routine
	endc

LEDPORT	Equ	PORTB			;set constant LEDPORT = 'PORTB'
LEDTRIS	Equ	TRISB			;set constant for TRIS register
SWPORT	Equ	PORTA
SWTRIS	Equ	TRISA
SW1	Equ	7			;set constants for the switches
SW2	Equ	6
SW3	Equ	5
SW4	Equ	4
LED1	Equ	3			;and for the LED's
LED2	Equ	2
LED3	Equ	1
LED4	Equ	0
	
	org	0x0000			;org sets the origin, 0x0000 for the 16F628,
					;this is where the program starts running	
	movlw	0x07
	movwf	CMCON			;turn comparators off (make it like a 16F84)

   	bsf 	STATUS,		RP0	;select bank 1
   	movlw 	b'00000000'		;set PortB all outputs
   	movwf 	LEDTRIS
	movlw 	b'11110000'		;set PortA 4 inputs, 4 outputs
   	movwf 	SWTRIS
	bcf	STATUS,		RP0	;select bank 0
	clrf	LEDPORT			;set all outputs low
	clrf	SWPORT
	bsf	SWPORT,	LED1		;set initial pattern


Start	clrf	count			;set counter register to zero
Read	movf	count, w		;put counter value in W
	btfsc	SWPORT,	LED1		;check which LED is lit
	call	Table1			;and read the associated table
	btfsc	SWPORT,	LED2
	call	Table2
	btfsc	SWPORT,	LED3
	call	Table3
	btfsc	SWPORT,	LED4
	call	Table4
	movwf	LEDPORT
	call	Delay
	incf	count,	w
	xorlw	d'14'			;check for last (14th) entry
	btfsc	STATUS,	Z
	goto	Start			;if start from beginning
	incf	count,	f		;else do next
	goto	Read

Table1	ADDWF   PCL, f			;data table for bit pattern
	retlw	b'10000000'
        retlw   b'01000000'
        retlw   b'00100000'
        retlw   b'00010000'
        retlw   b'00001000'
        retlw   b'00000100'
        retlw   b'00000010'
        retlw   b'00000001'
        retlw   b'00000010'
        retlw   b'00000100'
        retlw   b'00001000'
        retlw   b'00010000'
        retlw   b'00100000'
        retlw   b'01000000'

Table2	ADDWF   PCL, f			;data table for bit pattern
	retlw	b'11000000'
        retlw   b'01100000'
        retlw   b'00110000'
        retlw   b'00011000'
        retlw   b'00001100'
        retlw   b'00000110'
        retlw   b'00000011'
        retlw   b'00000011'
        retlw   b'00000110'
        retlw   b'00001100'
        retlw   b'00011000'
        retlw   b'00110000'
        retlw   b'01100000'
        retlw   b'11000000'

Table3	ADDWF   PCL, f			;data table for bit pattern
	retlw	b'01111111'
        retlw   b'10111111'
        retlw   b'11011111'
        retlw   b'11101111'
        retlw   b'11110111'
        retlw   b'11111011'
        retlw   b'11111101'
        retlw   b'11111110'
        retlw   b'11111101'
        retlw   b'11111011'
        retlw   b'11110111'
        retlw   b'11101111'
        retlw   b'11011111'
        retlw   b'10111111'

Table4	ADDWF   PCL, f			;data table for bit pattern
	retlw	b'00111111'
        retlw   b'10011111'
        retlw   b'11001111'
        retlw   b'11100111'
        retlw   b'11110011'
        retlw   b'11111001'
        retlw   b'11111100'
        retlw   b'11111100'
        retlw   b'11111001'
        retlw   b'11110011'
        retlw   b'11100111'
        retlw   b'11001111'
        retlw   b'10011111'
        retlw   b'00111111'

ChkKeys	btfss	SWPORT,	SW1
	call	Switch1
	btfss	SWPORT,	SW2
	call	Switch2
	btfss	SWPORT,	SW3
	call	Switch3
	btfss	SWPORT,	SW4
	call	Switch4
	retlw	0x00

Switch1	clrf	SWPORT			;turn all LED's off
	bsf	SWPORT,	LED1		;turn LED1 on
	retlw	0x00

Switch2	clrf	SWPORT			;turn all LED's off
	bsf	SWPORT,	LED2		;turn LED2 on
	retlw	0x00

Switch3	clrf	SWPORT			;turn all LED's off
	bsf	SWPORT,	LED3		;turn LED3 on
	retlw	0x00

Switch4	clrf	SWPORT			;turn all LED's off
	bsf	SWPORT,	LED4		;turn LED4 on
	retlw	0x00


Delay	movlw	d'250'			;delay 250 ms (4 MHz clock)
	movwf	count1
d1	call	ChkKeys			;check the keys
	movlw	0xC7			;delay 1mS
	movwf	counta
	movlw	0x01
	movwf	countb
Delay_0
	decfsz	counta, f
	goto	$+2
	decfsz	countb, f
	goto	Delay_0

	decfsz	count1	,f
	goto	d1
	retlw	0x00

	end
 
You're over complicating things - check my tutorials which show how simple things are.

You also need to post your entire code, and to do so within code tags (click on go advanced to get that option) in order to keep the formatting correct.

QUOTE]

As for future code posting, duly noted. I was wondering how you guys did that.
As for example code: Good Stuff. I have a few quick questions.
Comment1: If I understand it corectly you have the Table 1 Pattern runing as default.
Comment2: And the SW testing is running in the background. When SW test indicates one of SW's pressed (set to zero), it sends a flag to LED Testing portion that one of the LED's is on hence switching the pattern mode to that specific SW (and associated LED).
Question1: Is that why you did not call "Chkeys" in the main body (LED test portion) as it was not necessary since it is running in the background?
Question2: In SW testing portion (Chkeys) at the end of each test it returns w=0. Where does it return to? (does it set w=0 and continues running SW-test in the background?)
Question3: Why did you choose to do the SW testing after LED testing? Was it because you wanted the default pattern-Table1 to continue to run without any SW's pressed? Does it matter where the SW-Testing (Chkeys) is done?
Thanks for the info.

Regards,
Rom
 
Something interesting and new to me that I noticed you have done Nigel and that is to use RA5 as an input to set an event (SW). I thought RA5's function was limited to MCLR (Clearing all outputs). So if you set all bits in TRISA low except RA5 (TRIS5), all pins will be outputs except RA5 which will act as an input only bypassing the function of master clear, and enables you to read the status of it and do something with it?
And if you set it low, it will act as MCLR?
 
Something interesting and new to me that I noticed you have done Nigel and that is to use RA5 as an input to set an event (SW). I thought RA5's function was limited to MCLR (Clearing all outputs). So if you set all bits in TRISA low except RA5 (TRIS5), all pins will be outputs except RA5 which will act as an input only bypassing the function of master clear, and enables you to read the status of it and do something with it?
And if you set it low, it will act as MCLR?

You can set the config register to use MCLR as an input pin, and my tutorials all do that so as to give an extra pin, they also set the internal oscillator, and allocate the crystal pins as I/O as well.

These functions depend on the PIC you use, and was one of the reasons for choosing the 16F628 at the time.
 
As for future code posting, duly noted. I was wondering how you guys did that.
As for example code: Good Stuff. I have a few quick questions.
Comment1: If I understand it corectly you have the Table 1 Pattern runing as default.
Comment2: And the SW testing is running in the background. When SW test indicates one of SW's pressed (set to zero), it sends a flag to LED Testing portion that one of the LED's is on hence switching the pattern mode to that specific SW (and associated LED).
Question1: Is that why you did not call "Chkeys" in the main body (LED test portion) as it was not necessary since it is running in the background?
Question2: In SW testing portion (Chkeys) at the end of each test it returns w=0. Where does it return to? (does it set w=0 and continues running SW-test in the background?)
Question3: Why did you choose to do the SW testing after LED testing? Was it because you wanted the default pattern-Table1 to continue to run without any SW's pressed? Does it matter where the SW-Testing (Chkeys) is done?
Thanks for the info.

Chkeys is run from within the delay routine, I can't even remember why I did it that way now - I suspect it was carried over from a previous version
 
You can set the config register to use MCLR as an input pin, and my tutorials all do that so as to give an extra pin, they also set the internal oscillator, and allocate the crystal pins as I/O as well.

These functions depend on the PIC you use, and was one of the reasons for choosing the 16F628 at the time.

Excellent. I need to read up on your tutorials to see what other goodies you have.
Assuming that I use RA5 as a SW indicator what is the internal flag for status change of this pin?
I.E.: in your example you forced another pin to go high (LED) and tested that pin. What if I don't have a pin available and want to set some internal flag once status of RA5 goes from high to low by SW press and triggfer the main program to do something?
 
Chkeys is run from within the delay routine, I can't even remember why I did it that way now - I suspect it was carried over from a previous version
I see it now that you pointed it out. I skipped over Delay since I thought it is just a normal delay function. So in the main body of program I could easily call on Chkeys direct in place of your Delay call. Once the status of RA5 changes trigger the main program to read next line of the table lookup. Now it makes perfect sense.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top