PDA

View Full Version : Setup port pins into an array



longpole001
- 8th April 2013, 10:06
Hi guys , not sure of how to do this correctly . what i want to do is assign ports i/o pins in to an array thought it this would work but no

the complete code complies ok with no errors ( yep !!!)


all pins have been setup as outputs
GPio.3 is always input
test on 12f683
why is the output not happening ??

Cheers

Sheldon





X VAR BYTE ' General loop count
T var byte ' loop Count for LED Array selection
Z Var Byte ' Loop Counter for 100 scan to flash power LED
Cycles var byte ' Number cycles per led
IR_D var byte[4] ' IR Diode array
Pulse_cnt Var byte ' Temp counter Number of pulses per LED

------- Setup port pins for IR Output ----------

PWR_LED var GPIO.0 ' PWR LED - 1 = ON ,0 = OFF

IR_D[1] = GPIO.1 ' IR LED 1 - 1 = ON ,0 = OFF
IR_D[2] = GPIO.2 ' IR LED 2
IR_D[3] = GPIO.4 ' IR LED 3
IR_D[4] = GPIO.5 ' IR LED 4




T = 1 ' Set T to point led 1
Pulse_cnt = 12 ' Set base pulse count cycles for IR lED ( IR LED 1 = 12 pulse , LED 2 = 14 pulses etc to 30 pulses
For T = 1 to 4 ' Select IR LED for Pulses
Cycles = 0 ' Set to 0
for Cycles = 1 to Pulse_cnt ' Each IR led increments the amount of pulses by 2 for IR LED ID use
IR_D[T] = 1 ' Set IR LED High
pauseus 100 ' Remain on for test uS
IR_D[T] = 0 ' Set IR LED Low
pauseus 200 ' remain off for testuS
next Cycles
Pulse_cnt = Pulse_cnt +2 ' increment pulse count by offset of 2 for each IR LED
pauseus 350 ' Wait 350us between pulse bursts and selecting next IR LED
Next T

HenrikOlsson
- 8th April 2013, 11:26
Hi,
First, it's simply doesn't work like that - it just can't.

Second, even if it COULD be made to work that way you have a couple of issues with your code
1) Arrays are indexed starting at 0, you're writing outside of the declared array. An array of 4 elements is indexed from 0 to 3.
2) IR_D[1] = GPIO.1 will READ the state of GPIO.1 and assign the value of it TO IR_D[1] - not what you're after.

You can create aliases to the same register/variable using the VAR statement, it is well explained in the manual. The rule is that there is ONE place to which the alias is pointing, what you're trying to do is to have BOTH a memory location in RAM (the array) AND the GPIO register automatically merged into one single entity - it just doesn't work that way I'm afraid.

Perhaps something like this would do what you want:

PortOffset VAR BYTE
For T = 0 to 3
LOOKUP T, [1,2,4,5], PortOffset
FOR Cycles = 1 TO PulseCnt
GPIO.0[PortOffset] = 1
PAUSEUS 100
GPIO.0[PortOffset] = 0
PAUSEUS 200
NEXT
PAUSEUS 350
NEXT

/Henrik.

longpole001
- 8th April 2013, 22:36
thanks Henrik

If the group of Ports required to send the same output to are not a constant offset value per port , such as

PortA.0
PortA.2
PortA.3

PortB.2
PortB.5

PortC.0
PortC.1
Portc.3
PortC.5

How would the code go ?

Demon
- 9th April 2013, 00:03
Does this help?

http://www.picbasic.co.uk/forum/showthread.php?t=3753

Robert

longpole001
- 9th April 2013, 00:17
using hendric example as base i know repeating the code for each port group and offset it will work , but its not a good way to code for many port groups using the same code , need a nice way to point to the i/o pin groups,



A_PortOffset VAR BYTE
B_PortOffset VAR BYTE
C_PortOffset VAR BYTE

For T = 0 to 2
LOOKUP T, [0,2,3], A_PortOffset
FOR Cycles = 1 TO PulseCnt
PORTA.0 [A_PortOffset] = 1
PAUSEUS 100
PORTA.0 [A_PortOffset] = 0
PAUSEUS 200
NEXT Cycles
PAUSEUS 350
NEXT T

T= 0
For T = 0 to 1
LOOKUP T, [2,5], B_PortOffset
FOR Cycles = 1 TO PulseCnt
PORTB.0 [B_PortOffset] = 1
PAUSEUS 100
PORTB.0 [B_PortOffset] = 0
PAUSEUS 200
NEXT Cycles
PAUSEUS 350
NEXT T

T= 0
For T = 0 to 3
LOOKUP T, [0,1,3,5], C_PortOffset
FOR Cycles = 1 TO PulseCnt
PORTC.0 [C_PortOffset] = 1
PAUSEUS 100
PORTC.0 [C_PortOffset] = 0
PAUSEUS 200
NEXT Cycles
PAUSEUS 350
NEXT T

HenrikOlsson
- 9th April 2013, 06:21
Hi,
Surely THIS can't be for the 12F683 can it?
Anyway, if you open up the datasheet for the actual PIC and look memory map you'll see (always doublecheck !) that all the Port registers are consecutive in memory. This means that if you, for example, do PortA.0[14] = 1 you'll actually set PortB.6 because PortB.6 is 14 bits "away" from PortA.0 - pretty cool.


For i = 0 to 8 ' 9 output
Lookup i, [0, 2, 3, 10, 13, 23, 24, 26, 28], PortOffset
PortA.0[PortOffset] = 1
NEXT


Again, make sure you check the datasheet for the actual PIC!

/Henrik.

longpole001
- 9th April 2013, 10:41
oh hendric , that is very very cool , ill check the sheet of the intended chip ( 16F1825 ), 12f683 was a chip i had available for sim test for a quick test of code ,

i also wondering about if i want to send short time pulse of say 1us on time , using this code , and assuming i switch from the current selected 8mhz clock to the option of 32mhz internal clock , what would be the shortest output time at 32Mhz i could hope for before having to go down the ASM road to generate such a pulse time ?

If looking at ASM road , to do the same thing as the hendric example how would i incorporate it

i found a bit of Mr Houstons code example asm , but ASM code needs define statement that locks in the port and pin ( IRTX, PIN ) ??

Cheers

Sheldon







Pulse: ' Generate "Cycles" number of 40kHz pulses
ASM ; Keep this routine in code page 1, and jump over to Main
BSF IRTX,PIN ; 1 MAKE IR HIGH 35% Duty cycle = 9 uS
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
BCF IRTX,PIN ; 1 MAKE IR LOW 17 uS
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
DECFSZ Cycles,F
GOTO _Pulse ; 2 26 uS
ENDASM
return ' Return to caller

HenrikOlsson
- 9th April 2013, 11:01
Hi,
I'm going to take the easy way out here and simply say I don't know (because I don't know) and I won't bother trying to find out either - you can do that yourself by simply trying it ;-)
I suck at assembly so I'll leave that to someone who doesn't.

/Henrik.

longpole001
- 9th April 2013, 13:14
yep hendric , not good at ASM yet myself , so will up the clock speed to see what i get ,

in relation to mem map to consecutively get to io port , looking at the combined 16F1825/29 data sheet , it lists bank 0 , portA - 000C , Portb- 000D , portc -000E ( each 8 bits wide) ,
chip 1825 has port A( 6 ports - bits 0-5 of TRIS reg) , Port C (6 ports - bits 0-5 of TRIS reg )
chip 1829 has port A( 6 ports - bits 0-5 of TRIS reg), port B (4 ports - bits 4-7 of TRIS reg) , Port C (8 ports - bits 0-7 of TRIS reg )

Now assuming ( hate to ) that i want to use Port c 0 , i would set offset from portA,0 as 16 .cos port c.0 is 16 bits in mem from port a.0 , is that correct ??

i will try and see but , just to get it clear ?

cheers

Sheldon

longpole001
- 9th April 2013, 15:49
yes hendric it works well with the offset for ports , cheers
i will need to find out how to change the code so that it pulses using ASm , cos even at 32mhz the high pulse is still over 7us , with 2 pauseus command

if anyone can advise how to change allow this code to work in ASM to reduce the pulse length , where multi i/o ports are used be great

Cheers

Sheldon



For T = 0 to 9 ' Select IR LED for Pulses
LOOKUP T, [1,2,4,5,16,17,18,19,20,21],PortOffset ' Offsets from Port A to point to port A and port C I/O ports ( number of offset relates to bits offset in mem map of chip)
Cycles = 0 ' Set to 0
for Cycles = 1 to Pulse_cnt ' Each IR led increments the amount of pulses by 2 for IR LED ID use
PORTA.0[PortOffset] = 1 ' Set IR LED High
pauseus 2 ' Remain on for 2uS
PORTA.0[PortOffset] = 0 ' Set IR LED Low
pauseus 9 ' remain off for 9uS
next Cycles


Pulse_cnt = Pulse_cnt +2 ' increment pulse count by offset of 2 for each IR LED
pauseus 320 ' Wait 350us( adj) between pulse bursts and selecting next IR LED
Next T

sayzer
- 10th April 2013, 08:28
Just wondering,

Both 16F1825 and 12F683 have on board PWM module.

Why not use it since it is available?

longpole001
- 11th April 2013, 21:31
not used the PWM on these before as yet , thought a small change to use a variable port and pin in asm would be a easy change to the existing code

longpole001
- 23rd April 2013, 03:56
the code that i have works untill other things are asked of the PIC and the pulses jump around ,

A demo of the how to modify the Assembly code that can change the output pins with the code would be helpfull
or can a HPWM inside the 16F1825 generate a single 38Khz ( 26us ) carrier on each of the output pins ,

If so can someone give me a link or demo of the code required

Cheers

Sheldon

Demon
- 23rd April 2013, 13:21
If adding more code to your ASM program changes the timing, then it's not using interrupts or hardware pwm. Sounds like the timing using that program is not adjustable.

I remember someone here posted about DT-INT and pwm, I'd search for that.

Robert

prstein
- 23rd April 2013, 15:09
What oscillator speed are you using, and is a CCP pin available?

Best Regards,
Paul

longpole001
- 24th April 2013, 00:11
Hi guys ,

well the internal osc is 32Mhz ,

The code that works is here but after this point it jumps a bit cos of other routines that follow , i have manged to get around it in that instead of pausing 350us at the end of each scan it goes and goes do other things so its not as bad .

I guess what i am looking for is Either

A. ASM code example to replace the working code so that it may allow for less time issues for the cpu when doing other things
B. As the CPU has inbuilt PWM , can this be used in place of the ASM , existing code , knowing the a single PWM output is to be sent to all available output pins sequentially


Cheers

Sheldon

Working Code


For T = 0 to 9 ' Select IR LED for Pulses
LOOKUP T, [1,2,4,5,16,17,18,19,20,21],PortOffset ' Offsets from Port A to point to port A and port C I/O ports ( number of offset relates to bits offset in mem map of chip)
Cycles = 0 ' Set to 0
for Cycles = 1 to Pulse_cnt ' Each IR led increments the amount of pulses by 2 for IR LED ID use
PORTA.0[PortOffset] = 1 ' Set IR LED High
pauseus 2 ' Remain on for 2uS
PORTA.0[PortOffset] = 0 ' Set IR LED Low
pauseus 9 ' remain off for 9uS
next Cycles


Pulse_cnt = Pulse_cnt +2 ' increment pulse count by offset of 2 for each IR LED
pauseus 320 ' Wait 350us( adj) between pulse bursts and selecting next IR LED
Next T

longpole001
- 24th April 2013, 00:22
the ASM example i have is one where a set pin is used to output , but i required pins to be multi as per my other code , my asm sucks , another area to get better at :frown:




Pulse: ' Generate "Cycles" number of 40kHz pulses
ASM ; Keep this routine in code page 1, and jump over to Main
BSF IRTX,PIN ; 1 MAKE IR HIGH 35% Duty cycle = 9 uS
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
BCF IRTX,PIN ; 1 MAKE IR LOW 17 uS
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
DECFSZ Cycles,F
GOTO _Pulse ; 2 26 uS
ENDASM
return ' Return to caller

prstein
- 24th April 2013, 01:10
I know effectively nothing about assembly. I don't think HPWM can be used like that on sequential pins. I would try something interrupt based, like this:

'16F1825
Define OSC 32
'32 MHz
'= 8 MHz instruction time
'= 0.000000125 s/instruction
'= 0.000125 ms/instruction
'= 0.125 us/instruction
'So, 320 us = 2560 clocks

'Set up Timer1
T1CON = %00000001
' |||||||1 - TMR1ON
' ||||||0 - Unimplemented
' |||||0 - T1SYNC: 1 = Do not synchronize external clock input
' ||||0 - T1OSCEN: 0 = Dedicated Timer1 oscillator circuit disabled
' ||00 - T1CKPS: 00 = 1:1 Prescale value
' 00 - TMR1CS: 00 = Timer1 clock source is instruction clock (FOSC/4)

PortOffset var byte
Cycles var byte
Pulse_cnt var byte
Pulse_cnt = 0
T var byte
bGo var bit
bGo = 0
T = 0

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _TMR1_Handler, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR1_INT ; enable the interrupt

'Load Timer 1 with value to make it interrupt after 320 us
'for 320 us delay, want 2560 clocks
' 65534 - 2560 = 62974
' subtract ~7 more to account for the time to load the timer = 62967
' in hex, = $F5F7
TMR1H = $F5
TMR1L = $F7

'Main Loop
Main:
if bGo = 1 then
LOOKUP T, [1,2,4,5,16,17,18,19,20,21],PortOffset ' Offsets from Port A to point to port A and port C I/O ports ( number of offset relates to bits offset in mem map of chip)
Cycles = 0 ' Set to 0
for Cycles = 1 to Pulse_cnt ' Each IR led increments the amount of pulses by 2 for IR LED ID use
PORTA.0[PortOffset] = 1 ' Set IR LED High
pauseus 2 ' Remain on for 2uS
PORTA.0[PortOffset] = 0 ' Set IR LED Low
pauseus 9 ' remain off for 9uS
next Cycles

Pulse_cnt = Pulse_cnt + 2 ' increment pulse count by offset of 2 for each IR LED
T = T + 1
if T = 10 then
T = 0
endif
bGo = 0
endif
goto main



TMR1_Handler:
'Re-load Timer1
TMR1H = $F5
TMR1L = $F7
bGo = 1
@ INT_RETURN


Untested but it compiles...

Best Regards,
Paul

longpole001
- 24th April 2013, 05:59
yes i am using the DT int14 for this app so used timer 2 to try ,it ensured that timing is done , but issue still is that the other items need to be completed before the timer expires of 350us. , just the way it is i think for this app

its seems that PWM output on pins other than the pins defined for such output of chip design is not possible ????

The asm option i might give a go by just repeating the my example 10 times with each different output pin , its ugly but it will work , My asm learn curve needs to get better to get the best out of some timing apps on PIC chips i think

Cheers

Sheldon

prstein
- 25th April 2013, 00:54
Hello Sheldon,

I don't have much understanding of what else is going on in the code, but having it work for your needs is far more important than it being pretty. Assembler remains beyond me (that's why I use PBP!) and I am really not even sure what the ASM bit you posted does... I'll have to leave it to others.

Best Regards,
Paul

Demon
- 25th April 2013, 03:13
I was one of top of the class in assembler, back in 1984. :)

Haven't had to touch it since so I'm out too.

Robert

longpole001
- 25th April 2013, 16:24
yes repeating the example code code 10 times works with each pin , just sucks i dont know how to better code in assembler yet , ah well it works , so move on to the next part of the project ,

cheers guys