PDA

View Full Version : Serial Question + General Review



Freman
- 20th June 2008, 18:58
Hey guys.

Once again I re-iterate my thanks for the assistance you've been able to supply with my projects (I have several going - they're just beginning to merge, which leads me to the following)

I've built and tested various parts of this - except the serial stuff

2685

Everything I've tested is working fine (or close enough) - again with the exception of the serial.

I want to use the hwuart for the interrupt and buffer, this pic will never initiate communication only respond to otherwise initiated communication - the other pic has no available hwuart and I'd like to wire it to one pin if possible (ie: send a command, and wait for a command).

What I have to ask is - will my serial work in that configuration (tx + rx -> single pin)?

The second favor I ask is that you look over everything (including the code if it's not to much trouble) and tell me what (if anything) you'd do different - I know that some of you would rather not use gosub's in an interrupt but there'd be so much duplicated code without it.

I only ask this second favor, because I'd rather not be back into it every other day trying to debug something once I put it together :)



' Configure the FUSE options for the compiler
@ device pic16F628A, hs_osc, wdt_off, pwrt_on, lvp_off, protect_off, bod_on, cpd_off, pwrt_off, mclr_off

' Running a 20Mhz clock
DEFINE OSC 20
DEFINE PULSIN_MAX 3000

CMCON = 7
VRCON = 0

ALL_DIGITAL

' Setup the USART
DEFINE HSER_RCSTA 90h ' Receive register to receiver enabled
DEFINE HSER_TXSTA 20h ' Transmit register to transmitter enabled
DEFINE HSER_BAUD 19200 ' Set baud rate

' Alias our pins
BEEP VAR PORTA.0 ' Buzzer
RFIN VAR PORTA.1 ' Remote input
PROXIMITY_UP VAR PORTA.3 ' Proximity sensor for UP travel
PROXIMITY_DOWN VAR PORTA.4 ' 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

' Set the pin directions
INPUT RFIN
INPUT BUTTONA
INPUT BUTTONB

OUTPUT BEEP
OUTPUT RELAY1
OUTPUT RELAY2
OUTPUT PROXIMITY_DOWN
OUTPUT PROXIMITY_UP

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

' Turn on weak pull-ups - IMPORTANT: After making relays and beepers low...
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

' Constants
STATE_GOING_UP CON 1 ' Screen is going up
STATE_GOING_DOWN CON 2 ' Screen is going down
STATE_STOPPED CON 8 ' Screen is stopped
STATE_UP CON 9 ' Stopped + UP
STATE_DOWN CON 10 ' Stopped + Down
BEEP_WAIT CON 100 ' Wait 100 MS for the beep
POST_BEEP_WAIT CON 100 ' Wait 100 MS after the beep to reverse direction

' 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

' This is the real main - almost all the looping comes back here
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
INTCON = 0 ' Turn off interrupts
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
HIGH PROXIMITY_UP ' Turn on the up proximity sensor
STATE = STATE_GOING_UP
INTCON = %11010000 ' Turn the interrupts on
ENDIF
RETURN

subStop:
IF STATE.3 != 1 THEN
INTCON = 0 ' Turn off interrupts
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
LOW PROXIMITY_UP ' Turn off the up proximity sensor
PAUSE BEEP_WAIT ' Wait a bit
LOW BEEP ' STFU :)
STATE = STATE_STOPPED
INTCON = %11010000 ' Turn the interrupts on
ENDIF
RETURN

subDown:
IF STATE != STATE_GOING_DOWN THEN
INTCON = 0 ' Turn off interrupts
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!)
LOW PROXIMITY_UP ' Turn off the up proximity sensor
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
INTCON = %11010000 ' Turn the interrupts on
ENDIF
RETURN

sighup:
X = STATE
IF INTCON.1 == 1 THEN
GOSUB subStop
IF STATE == STATE_GOING_DOWN THEN STATE = STATE_DOWN
IF STATE == STATE_GOING_UP THEN STATE = STATE_UP
INTCON.1 = 0
ENDIF
WHILE RCIF
' Don't use 1-10 this makes it easier to eliminate "echo" noise from tx
SELECT CASE RCREG
CASE 127
GOSUB subUp
CASE 128
GOSUB subDown
CASE 129
GOSUB subStop
CASE 130
HSEROUT [STATE]
END SELECT
WEND
IF OERR = 1 THEN
CREN = 0
CREN = 1
ENDIF
RESUME

ENABLE


Thanks :)

Edit: I can't work out how ya'll attach and make a nice preview image...

skimask
- 20th June 2008, 21:57
What I have to ask is - will my serial work in that configuration (tx + rx -> single pin)?
It can work just fine using serial communications over a single pin.......provided you use the software serial commmands (i.e. SERIN/SERIN2/SEROUT/SEROUT2/DEBUGIN/DEBUG, etc.) and not the hardware or it's commands (i.e. HSERIN/HSERIN2/HSEROUT/HSEROUT2). PBP should/will automatically set the pin to input and/or output as required...should that is.

Freman
- 20th June 2008, 22:27
It can work just fine using serial communications over a single pin.......provided you use the software serial commmands (i.e. SERIN/SERIN2/SEROUT/SEROUT2/DEBUGIN/DEBUG, etc.) and not the hardware or it's commands (i.e. HSERIN/HSERIN2/HSEROUT/HSEROUT2). PBP should/will automatically set the pin to input and/or output as required...should that is.

I'd rather not use the software equiv in this case as it's quite a busy little chip and I'd really like to have the interrupt and buffering. I know I can use interrupts on portb, but portb is quite busy - especially with constantly turning the WPU on and off :)