PDA

View Full Version : RB0 + Internal Pullup + Interrupt



Freman
- 28th July 2009, 05:49
Hi again.

I've got a slight issue with my task.

I need PortB to have internal pullups on because I'm enhancing an existing board design that relied on them, however - I have an issue with implementing interrupts because RB0 is now high all the time and I need it to be low, I can achieve this by using a pulldown on top of the pullup, but my board space is running low :(

Is there a way to set RB0 not to use it's internal pullup?

Archangel
- 28th July 2009, 05:56
Hi again.

I've got a slight issue with my task.

I need PortB to have internal pullups on because I'm enhancing an existing board design that relied on them, however - I have an issue with implementing interrupts because RB0 is now high all the time and I need it to be low, I can achieve this by using a pulldown on top of the pullup, but my board space is running low :(

Is there a way to set RB0 not to use it's internal pullup?
Hi Freman,
Please tell us which PIC you are using . . .and without knowing that or seeing your board I ask if you have room for one of those SIP resistor ladders for pullups ?

Freman
- 28th July 2009, 06:20
Sorry, it was stupid of me to forget the pic - it's a PIC16F628A

And no, I really have no room left for much more on that board, I can probably cram one more resistor in as a pulldown but that's about it.

Archangel
- 28th July 2009, 07:55
Sorry, it was stupid of me to forget the pic - it's a PIC16F628A

And no, I really have no room left for much more on that board, I can probably cram one more resistor in as a pulldown but that's about it.Datasheet PP36 sec. 5.2 . . . "A single control bit can turn on ALL THE PULLUPS. . . . The weak pull up is automatically turned off when the port pin is configured as an output." I think you are stuck using the resistor unless you can flip the port's use in the software I E. instead of, if high then to if low then. I have a blinky running right now which toggles the tris on a port and as soon as it goes back to input the wpu is on.

Freman
- 9th August 2009, 05:42
I think I've found another side effect of using internal pullups...

I always figured if I couldn't get any other method working for this, I'd fallback to serial/uart communications...

I can't get the UART working :(

I'm using a usb>serial chip, but it's no real matter because both pins 7(RB1/RX) and 8(RB2/TX) are always high

Any ideas how I can get this working?

Archangel
- 9th August 2009, 05:46
I think I've found another side effect of using internal pullups...

I always figured if I couldn't get any other method working for this, I'd fallback to serial/uart communications...

I can't get the UART working :(

I'm using a usb>serial chip, but it's no real matter because both pins 7(RB1/RX) and 8(RB2/TX) are always high

Any ideas how I can get this working?Hi Freeman,
Gotta see some code. USART Idles high, in normal operation.

Freman
- 9th August 2009, 05:57
Here's the code



@ device pic16F628A, hs_osc, wdt_off, pwrt_on, lvp_off, protect_off, bod_on, cpd_off, pwrt_off, mclr_off

DEFINE OSC 20
DEFINE PULSIN_MAX 3000

CMCON = 7
VRCON = 0

ALL_DIGITAL

' Alias our pins
BEEP VAR PORTA.0 ' Buzzer
RFIN VAR PORTA.1 ' Remote input
PROXIMITY_DOWN VAR PORTA.2 ' Proximity sensor for DOWN travel
RELAY1 VAR PORTB.4 ' Relay 1 output
RELAY2 VAR PORTB.5 ' Relay 2 output
BUTTONA VAR PORTB.6 ' Primary panel button input
BUTTONB VAR PORTB.7 ' Secondary panel button input

' Define some aliases for USART
OERR VAR RCSTA.1 ' Over-run bit
CREN VAR RCSTA.4 ' Continuous receive enable bit
RCIF VAR PIR1.5 ' Received character interrupt flag bit

DEFINE HSER_RCSTA 90h ' Receive register to receiver enabled
DEFINE HSER_TXSTA 20h ' Transmit register to transmitter enabled
DEFINE HSER_BAUD 9600 ' Set baud rate

' Set the pin directions
INPUT RFIN
INPUT BUTTONA
INPUT BUTTONB

OUTPUT BEEP
OUTPUT RELAY1
OUTPUT RELAY2
OUTPUT PROXIMITY_DOWN

' Configure the output pins as low
LOW BEEP
LOW RELAY1
LOW RELAY2
LOW PROXIMITY_DOWN

' Turn on weak pull-ups
OPTION_REG.7 = 0
' We want to interrupt on the falling edge
OPTION_REG.6 = 0

' Set us up some variables
PBITS VAR BYTE[24] ' The bits we've read
RAW VAR WORD ' The raw pulsin value
ADDRESS VAR WORD ' Storage for the address
DBYTE VAR BYTE ' Storage for the data
LOOPADDRESS VAR WORD ' Second loop storage of first loop addres
LOOPDBYTE VAR BYTE ' Second loop storage of first loop data byte
X VAR BYTE ' Loop/TMP var
Y VAR BYTE ' Loop/TMP var
STATE VAR BYTE ' Current state of the device
serialbyte VAR BYTE

' Default state
STATE = STATE_STOPPED

ON INTERRUPT GOTO sighup
INTCON = %11010000
PIE1 = %00100000

' Reset all the primary RF variables
TOP:
ADDRESS = 0 : RAW = 0 : DBYTE = 0

MAIN:
' Set both buttons for input
INPUT BUTTONA
INPUT BUTTONB
' Check to see if the individual buttons are toggled
IF NOT BUTTONA THEN GOSUB subDown
IF NOT BUTTONB Then GOSUB subUp
' Fiddle with the inputs to see if the middle button is pushed
LOW BUTTONB
X = BUTTONA ' If it's LOW then there's a good chance the middle button is down
HIGH BUTTONB
INPUT BUTTONB
LOW BUTTONA
Y = BUTTONB ' If it's LOW then there's a good chance the middle button is down
HIGH BUTTONA
INPUT BUTTONB
INPUT BUTTONA
IF NOT Y AND NOT X THEN GOSUB subStop ' Both register as LOW then the middle button is down!

' Look for one huge low pulse
PULSIN RFIN, 0, RAW
' 2350 is about mean average
IF RAW < 2340 OR RAW > 2360 THEN MAIN

' Read 16 address bits and 8 data bits
FOR X = 0 TO 23
PULSIN RFIN, 0, RAW
' Check the pulse parameters
if RAW < 30 OR RAW > 240 THEN MAIN
PBITS[x] = NCD RAW
NEXT X

' Gather the address
ADDRESS = 65535 ' Maxmimum known ID
FOR X = 0 to 15
IF PBITS[x] > 7 THEN ADDRESS.0[X] = 0
NEXT X

' Gather the data
DBYTE = 255 ' Maximum known data value
Y=0
FOR X = 16 TO 23
IF PBITS[X] > 7 THEN DBYTE.0[Y] = 0
Y = Y + 1
NEXT X

' If we've done a loop...
IF ADDRESS == LOOPADDRESS AND DBYTE == LOOPDBYTE THEN
SELECT CASE DBYTE
CASE 3
GOSUB subUp
CASE 12
GOSUB subStop
CASE 192
GOSUB subDown
END SELECT
LOOPDBYTE = 0
LOOPADDRESS = 0
ELSE
' Start a loop
LOOPDBYTE = DBYTE
LOOPADDRESS = ADDRESS
ENDIF

GOTO TOP
END

DISABLE

subUp:
IF STATE != STATE_GOING_UP THEN
HIGH BEEP ' Start making noise
LOW RELAY1 ' Make sure the down relay is off (Don't know what happens otherwise, don't want to know!)
LOW PROXIMITY_DOWN ' Turn off the down proximity sensor
PAUSE BEEP_WAIT ' Wait a bit
LOW BEEP ' STFU :)
IF STATE.3 != 1 THEN PAUSE POST_BEEP_WAIT
HIGH RELAY2 ' Turn the up relay on
STATE = STATE_GOING_UP
PAUSE WAIT_WAIT
ENDIF
RETURN

subStop:
IF STATE.3 != 1 THEN
HIGH BEEP ' Start making noise
LOW RELAY1 ' Turn off the down relay
LOW PROXIMITY_DOWN ' Turn off the down proximity sensor
LOW RELAY2 ' Turn off the up relay
PAUSE BEEP_WAIT ' Wait a bit
STATE = STATE_STOPPED
LOW BEEP ' STFU :)
PAUSE WAIT_WAIT
ENDIF
RETURN

subDown:
IF STATE != STATE_GOING_DOWN THEN
HIGH BEEP ' Start making noise
LOW RELAY2 ' Make sure the up relay is off (Don't know what happens otherwise, don't want to know!)
PAUSE BEEP_WAIT ' Wait a bit
LOW BEEP ' STFU :)
IF STATE.3 != 1 THEN PAUSE POST_BEEP_WAIT
HIGH RELAY1 ' Turn the down relay on
HIGH PROXIMITY_DOWN ' Turn on the down proximity sensor
STATE = STATE_GOING_DOWN
PAUSE WAIT_WAIT
ENDIF
RETURN

sighup:
X = STATE
IF INTCON.1 == 1 THEN
GOSUB subStop
INTCON.1 = 0
ENDIF
WHILE RCIF ' While there are bytes to be read
serialByte = RCREG ' Read a byte
HSEROUT [1, serialByte] ' Tell the sender what byte was received
IF serialByte = 117 THEN GOSUB subUp
IF serialByte = 100 THEN GOSUB subDown
WEND
IF OERR = 1 THEN
CREN = 0
CREN = 1
ENDIF
RESUME

ENABLE



Specifically of interest I guess is this bit - the fiddling with buttons bit


' Set both buttons for input
INPUT BUTTONA
INPUT BUTTONB
' Check to see if the individual buttons are toggled
IF NOT BUTTONA THEN GOSUB subDown
IF NOT BUTTONB Then GOSUB subUp
' Fiddle with the inputs to see if the middle button is pushed
LOW BUTTONB
X = BUTTONA ' If it's LOW then there's a good chance the middle button is down
HIGH BUTTONB
INPUT BUTTONB
LOW BUTTONA
Y = BUTTONB ' If it's LOW then there's a good chance the middle button is down
HIGH BUTTONA
INPUT BUTTONB
INPUT BUTTONA
IF NOT Y AND NOT X THEN GOSUB subStop ' Both register as LOW then the middle button is down!



And here is the basic schematic.
http://users.on.net/~freman/images/electronics/input.png



I'm looking for any solution, hardware or software - I can't change the bit in the unchangeable box, that's the existing pcb that I'm upgrading...

mackrackit
- 9th August 2009, 06:55
I do not see the TX or RX connected to anything??

But... using http://www.picbasic.co.uk/forum/showpost.php?p=74024&postcount=4
PIC MULTICALC the setting should be


DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 129 ' 9600 Baud @ 20MHz, 0.16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

Freman
- 9th August 2009, 07:53
No, in that schematic they're not connected to anything - but in reality they're hooked up to tx and rx of a usb-serial adapter. The schematic I posted was more to illustrate the reason behind the pullups being turned on.

The serial values I'm using are ones I've used in another project that's working... but I'll give yours a try.

Edit.

Nope, no change...

I have noticed tho that when I send data over the usb/serial cable that the voltage does in deed dip (drops from 4.95 to 4.60v) which indicates that the signal is being transmitted (my multimeter isn't fast enough to measure the full weight of the dip)

I've also done some testing on the usb/serial cable and have found it goes to 3v when high (again probably more, my multimeter can't keep up)

Freman
- 9th August 2009, 08:22
Oh dear - I feel stupid now...

I souldered the tx wire to dtr...

Never fear tho - I've had my eyesight checked, and the idiot that left me in charge has been taken out the back and flogged

Freman
- 9th August 2009, 08:35
Which has left me with another problem...

The pic isn't recieving my strings right...

d and u are what I'm sending, d consistently returns v... don't know what u returns...

v returns 7, 7 makes the screen work in place of d

mackrackit
- 9th August 2009, 09:04
Never fear tho - I've had my eyesight checked, and the idiot that left me in charge has been taken out the back and flogged
I always blame my bifocals when something like that happens :)

Your other problem... I will assume the 232 chip or equivalent is working and the settings on the machine sending the data are correct? I do not know what would cause the problem...

Archangel
- 9th August 2009, 09:25
@ device pic16F628A, hs_osc, wdt_off, pwrt_on, lvp_off, protect_off, bod_on, cpd_off, pwrt_off, mclr_off

You really want 2 PWRT statements here ?
Shouldn't you clear RCIF in your int handler ?

Freman
- 9th August 2009, 09:42
@ device pic16F628A, hs_osc, wdt_off, pwrt_on, lvp_off, protect_off, bod_on, cpd_off, pwrt_off, mclr_off

You really want 2 PWRT statements here ?
Shouldn't you clear RCIF in your int handler ?

Umm, well... I don't understand the header... I sort of found one that worked and stuck with it ;)

Doesn't reading from RCIF clear it?
Doesn't a while statement read it?


Your other problem... I will assume the 232 chip or equivalent is working and the settings on the machine sending the data are correct? I do not know what would cause the problem...
I'm using a pl2303 chip mounted on a basic board (get them on ebay from china for $6 a pop, strip them down, cheaper then buying the individual components and you get spare parts)

Don't honestly know if they work right, they pass a loop back test - I'd probably need to pay a visit to my local electronics store and grab a null modem or equiv cable (Don't have any female 9pin plugs...) to test them properly - don't have any other serial ports in the house to use...

I've done some more scientific testing then firing random characters at the thing and seeing what it gives me back...




DEBUG: Initializing
DEBUG: Creating lockfile for /dev/ttyUSB2
DEBUG: Opening serial port /dev/ttyUSB2
DEBUG: Setting port configuration
DEBUG: Writing settings
DEBUG: Initialized
DEBUG: Screen up
DEBUG: Transmitting
DEBUG: Sending: 00000001
DEBUG: Sent 1 bytes
DEBUG: Receiving
DEBUG: Waiting for 4 bytes
DEBUG: Received 4 bytes
DEBUG: Received: 00000000,01010101,01010101,01111111
DEBUG: Receive OK
DEBUG: Transmit Failed


So what I've done here is written a script that sends 0x01 to the pic, the pic is supposed to send back 0x55, 0x55, 0x01 0x01

The 0x55, 0x55, 0x01 is hardcoded, the second 0x01 is what it's received from the wire. (the 0x55 was chosen because it represents alternating 0's and 1's helps detect squishing bitrates)

What I'm getting back is 0x00, 0x55, 0x55, 0x7f, and it's consistent...

If I ask my script to read more bytes it reads back a maximum number of 5 - 00000000,01010101,01010101,01111111,01000000

If I send something different say, 0x7F I get back 00000000,01010101,01010101,01111111,00000001

0x02 00000000,01010101,01010101,01111111,01100000
0x03 00000000,01010101,01010101,01111111,00100000
0x04 00000000,01010101,01010101,01111111,01110000

So here, I made it output 0x00 - 0xff, 0x01, 0x04 - which should be 258 bytes, but I got back 252. so there's at least 6 missing bytes, and it appears to be talking to me inverted off by a bit...

00000000,11111101,11111011,11111001,11110111,11110 101,11110011,11110001,11101111,11101101,11101011,1 1101001,11100111,11100101,11100011,11100001,110111 11,11011101,11011011,11011001,11010111,11010101,11 010011,11010001,11001111,11001101,11001011,1100100 1,11000111,11000101,11000011,11000001,10111111,101 11101,10111011,10111001,10110111,10110101,10110011 ,10110001,10101111,10101101,10101011,10101001,1010 0111,10100101,10100011,10100001,10011111,10011101, 10011011,10011001,10010111,10010101,10010011,10010 001,10001111,10001101,10001011,10001001,10000111,1 0000101,10000011,10000001,01111111,01111101,011110 11,01111001,01110111,01110101,01110011,01110001,01 101111,01101101,01101011,01101001,01100111,0110010 1,01100011,01100001,01011111,01011101,01011011,010 11001,01010111,01010101,01010011,01010001,01001111 ,01001101,01001011,01001001,01000111,01000101,0100 0011,01000001,00111111,00111101,00111011,00111001, 00110111,00110101,00110011,00110001,00101111,00101 101,00101011,00101001,00100111,00100101,00100011,0 0100001,00011111,00011101,00011011,00011001,000101 11,00010101,00010011,00010001,00001111,00001101,00 001011,00001001,00000111,00000101,00000011,0000000 1,11111111,00111111,10011111,11101110,11101010,111 00110,11100010,11011110,11011010,11010110,11010010 ,11001110,11001010,11000110,11000010,10111110,1011 1010,10110110,10110010,10101110,10101010,10100110, 10100010,10011110,10011010,10010110,10010010,10001 110,10001010,10000110,10000010,01111110,01111010,0 1110110,01110010,01101110,01101010,01100110,011000 10,01011110,01011010,01010110,01010010,01001110,01 001010,01000110,01000010,00111110,00111010,0011011 0,00110010,00101110,00101010,00100110,00100010,000 11110,00011010,00010110,00010010,00001110,00001010 ,00000110,00000010,11111110,00011111,10001111,1101 1100,11010100,11001100,11000100,10111100,10110100, 10101100,10100100,10011100,10010100,10001100,10000 100,01111100,01110100,01101100,01100100,01011100,0 1010100,01001100,01000100,00111100,00110100,001011 00,00100100,00011100,00010100,00001100,00000100,11 111100,00001111,10000111,10111000,10101000,1001100 0,10001000,01111000,01101000,01011000,01001000,001 11000,00101000,00011000,00001000,11111000,00000111 ,10000011,01110000,01010000,00110000,00010000,1111 0000,00000011,10000001,11100000,00000001,10000000, 01111111,01110000

Archangel
- 9th August 2009, 17:43
Umm, well... I don't understand the header... I sort of found one that worked and stuck with it ;)

That's a honest answer!


Doesn't reading from RCIF clear it?
Doesn't a while statement read it?

Here is My honest answer, probably does, I do not know for sure if it does, or not, that is why I said it as a question :D

Freman
- 10th August 2009, 00:08
That's a honest answer!

Here is My honest answer, probably does, I do not know for sure if it does, or not, that is why I said it as a question :D

I've had a look at the datasheet for the pic, and it states

"Flag bit RCIF is a read-only bit, which is cleared by the hardware. It is cleared when the RCREG register has been read and is empty."

So the WHILE isn't actually resetting it, reading RCREG is.

I also found the datasheet for the PL-2303, it rx's at TTL (5v levels) and tx's at 3.3v - so that's some concrete information, but doesn't really help with what seems like inversion...

Freman
- 10th August 2009, 02:38
I've just finished testing the USB-Serial cable, and it appears to be working.

I've hooked it up TX-RX, RX-TX, GND-GND to a PC serial port (Real hardware kind) and I can send and recieve data to and from the device without any form of corruption.

Which brings me back to my original query... are the pullup's in the PIC breaking my serial communications?

If so, can anyone come up with a simple way to re-do the input detection of the buttons? (I have spare pins on the pic if that helps ;))

Edit:

Actually I think I found the answer to my problem "The HW USART output is inverted as it is designed to work with an RS232 driver." that means I must have built my FT232 circuit to use the inverted output/input (the FT232 chip is very smart, I just don't remember doing that...) I haven't been using a max232 chip on this project because the voltages were within tolerance, and I just don't have the room... maybe I'll have to build an external serial adapter...

Archangel
- 10th August 2009, 06:37
I've just finished testing the USB-Serial cable, and it appears to be working.

I've hooked it up TX-RX, RX-TX, GND-GND to a PC serial port (Real hardware kind) and I can send and recieve data to and from the device without any form of corruption.

Which brings me back to my original query... are the pullup's in the PIC breaking my serial communications?

If so, can anyone come up with a simple way to re-do the input detection of the buttons? (I have spare pins on the pic if that helps ;))

Edit:

Actually I think I found the answer to my problem "The HW USART output is inverted as it is designed to work with an RS232 driver." that means I must have built my FT232 circuit to use the inverted output/input (the FT232 chip is very smart, I just don't remember doing that...) I haven't been using a max232 chip on this project because the voltages were within tolerance, and I just don't have the room... maybe I'll have to build an external serial adapter...
Hi Freman,
I have never used HSEROUT . HSERIN requires you to send data to it TRUE, and idles in the HIGH state. This from the data sheet . . . <b>
"The USART’s transmitter and receiver are functionally
independent but use the same data format and baud rate." </b>
and this:
<b> "Clearing enable bit TXEN during a transmission will cause the
transmission to be aborted and will Reset the
transmitter. As a result the RB2/TX/CK pin will revert to
hi-impedance."</b>
This suggests to me it transmits TRUE too. Fact is I do not know, but the evidence suggests it.

mackrackit
- 10th August 2009, 06:49
I haven't been using a max232 chip on this project because the voltages were within tolerance, and I just don't have the room... maybe I'll have to build an external serial adapter...
I think that solves it. Look at the PBP manual.
Install an inverter as the manual states when using hardware serial or change your code to software, SERIN2/SEROUT2, and get back with us.

Freman
- 10th August 2009, 09:43
*sigh* Just another one of the things that leave me asking WTF were they thinking when they designed these chips... oh well..

mackrackit
- 10th August 2009, 11:11
*sigh* Just another one of the things that leave me asking WTF were they thinking when they designed these chips... oh well..
I bet they had a good reason.... Who knows what it was. Might be that a 232 type chip can bring the levels up to true RS232 levels that a micro can not because of the voltage they run at.

Most times the software solution will work and you then have the benifit of using most any pin. About the only time I use hardware (HSERIN/OUT) is if I need it running in the background as in an interrupt. Of course if something else triggers the interrupt then you can have the software routine in that interrupt.

All kinds of possibilities.