PDA

View Full Version : Problem with PortB Tris



timmers
- 28th November 2012, 14:51
I have a funny problem with driving PortB.6 as a digital io. (18LF 44K22 PBP 2.6c)
The first 3 flashes work fine using HIGH PORTB.6, but doing the same again using PORTB.6 = 1 doesn't work though the other pins work as expected.
I have looked through the data sheet and can find no clues. Can anyone point me in the right direction?

Tim.


TEMPB VAR BYTE 'Temporary Byte sized register

STARTUP: ANSELA = 0 'ALL DIGITAL INPUTS
ANSELB = 0
ANSELC = 0
ANSELD = 0
ANSELE = 0

TRISA = %11011100 'PortA ins & outs
TRISB = %00010000 'PortB ins & outs
TRISC = %11011110 'PortC ins & outs
TRISD = %10000000 'PortD ins & outs
TRISE = %00000100 'PortE ins & outs

FOR TEMPB = 1 TO 3 'ALL LED'S FLASH STARTUP SIGNAL
PORTB.5 = 1
HIGH PORTB.6
PORTB.7 = 1
PAUSE 200

PORTB.5 = 0
LOW PORTB.6
PORTB.7 = 0
PAUSE 300
NEXT TEMPB

FOR TEMPB = 1 TO 3 'ALL LED'S FLASH STARTUP SIGNAL
PORTB.5 = 1
PORTB.6 = 1
PORTB.7 = 1
PAUSE 200

PORTB.5 = 0
PORTB.6 = 0
PORTB.7 = 0
PAUSE 300
NEXT TEMPB

GOTO MAIN

SteveB
- 28th November 2012, 15:08
I don't have an answer, just a quick suggestion to trouble shoot. Try putting another TRISB = %00010000 between the FOR...NEXT loops and see what that does. Also, if you use PORTB.6 = 1...PORTB.6 = 0 in the first loop instead of HIGH...LOW, does it work properly?

mackrackit
- 28th November 2012, 15:44
Try LAT
http://www.picbasic.co.uk/forum/showthread.php?t=15836&p=110057#post110057

timmers
- 28th November 2012, 16:54
Adding an extra TRISb.6 = 0 between loops made no difference.
Changing to LATb.6 = 1 works. Thanks for that. Problem solved.

Interestingly, further down the code is ON INTERRUPT. If I put the PORTb.6 = 1 loop after the ON INTERRUPT statement it works fine???

I usually use DT's instant int's (fantastic by the way) but this programme uses I2CREAD and I2cWRITE and so had to go back to ON INTERRUPT to prevent the timing being upset by the ISR.

mackrackit
- 28th November 2012, 17:19
If I put the PORTb.6 = 1 loop after the ON INTERRUPT statement it works fine???

All I can say is sometimes we get lucky....

Like in the beginning of your code

The first 3 flashes work fine using HIGH PORTB.6

the data latch was clear. That evidently is happening in your ISR.

SteveB
- 28th November 2012, 17:35
Glad to see it get fixed!


this programme uses I2CREAD and I2cWRITE and so had to go back to ON INTERRUPT to prevent the timing being upset by the ISR.
You might look into using the hardware I2C. You'd have to write some routines to deal with the data, but it will work well once you do.

timmers
- 29th November 2012, 09:26
I agree, hardware I2c is the way to go, but thats alot of effort to make it work. The I2cREAD/WRITE work so well outside an interrupt environment.

SteveB
- 29th November 2012, 14:41
FWIW, here is an include file I put together (a long time ago) to use the Hardware I2C. It may be useful. It uses arrays as buffers to input and output data.
6749
It uses arrays as buffers to input and output data. This real time clock include shows how the H12C is used.
6748
It's been a while since I've used/looked at it, so there is likely quite a bit that could be improved. But, it worked when I used it. ;) I just can't remember all the details of how. :rolleyes:

timmers
- 30th November 2012, 16:22
Interesting.
I will try and pick it apart to see how you ran the module, then try and write my own interpretation so I will then understand how it works.

Cheers,
Tim.

SteveB
- 30th November 2012, 19:43
Here are some things I’d look into changing or using now that I look at it again. First, some easier changes:

- Not so much a change to the routines, but in how they are called. Use the new (ish) ARRAYWRITE command to load the array buffer, and the ARRAYREAD command to read the array buffer. The nice thing about these is that they use the modifiers for formatting strings, like DEC and HEX
- The routines use 2 array buffers, one for input (I2CRDBuff) and one for output (I2CWRBuff). I think this could be reduced to only one array buffer pretty easily. It would save on RAM (may not be an issue) and likely simplify things a little.

Much bigger changes which would require a more significant amount work:

- Implement interrupts (via DT’s Instant Interrupts) to do the sending/receive of data ‘behind the scenes’. Basically, load up the array, point the I2C to the correct address, and pull the trigger. The rest will take care of itself while your main program goes on its way doing something else.
- Implement an assembly macro to execute the routines (similar to how the LCD bar graph macro works). This would simplify coding in the main program module.

Who knows, maybe I may look into it as well if time permits. Gives me something to stay out of trouble. :rolleyes: