📄 pic.txt
字号:
Subject: Version 0.21 of pic library
Status: R
Here is a copy of my pic library. Sorry I couldn't respond personally to
each of your kind and encouraging notes, but there have been so many requests.
All the best.
;***************************************
; READ.ME FILE FOR ;
; LIBRARY OF UTILITIES FOR PIC ;
; EDWARD CHEUNG, PH.D. ;
; 14505 DOLBROOK LANE ;
; MITCHELLVILLE, MD 20721 ;
; ebc714@rs710.gsfc.nasa.gov ;
;***************************************
Introduction
This library of utilities was written for the 16C71 microcontroller,
but can be adapted for use on other PIC chips. The library is fully
interrupt based: sending and receiving of data in various formats occurs
in the background using interrupts. The 'main' program just sets some
variables and calls the appropriate routine. The data will be sent
in the background at the proper rate and time.
The included demo.asm program runs a simple RS232 controlled Infra Red
remote with LCD display. See the end if this file for more info.
General Description
The functions that interface to each type of hardware are arranged into
modules. Each of these modules can be disabled or enabled at the top
of the main program (see demo.asm) in order to include only those that
you need for the particular PIC that you are using.
Being a first time assembly programmer, I wrote the code in C, which is
then hand compiled to PIC mnemonics. The C code is included at the end
of each line, allowing me to quickly read a section to find out what the
code does. It also made debugging a lot easier because I could follow
the program flow (if - then - else - else etc.).
My naming convention is to add three common characters to all labels
and function names in a module. For example, all names in the RS232 module
start with R2_, all of those in the IR module starts with IR_. This is in
order to facilitate the reading of my code.
As mentioned above when you want to send data (IR,RS232 etc) you call
the appropriate routine in the associated module. For example, to send
a character down the RS232 line, you call R2_SEND. This is then placed
into a FIFO, and then sent according to the correct timing. If the
FIFO is full, the function will wait until there is a spot open in the
FIFO before returning to the main program.
Whenever new data is received, the function XX_NEW is called (where
XX is the module abbreviation). Look for these functions
in the lib.h file. In these functions is where you add your code to do
the processing of new incoming data.
Currently incoming data is either sent to the LCD display or the RS232
line. Specifically, incoming data is processed as follows:
Incoming data Displayed on Comments
RS232 RS232 Typing characters to PIC causes simple echo
RS422 RS422 Typing characters to PIC causes simple echo
IR LCD Displays device and key code of IR command
X-10 LCD Displays house and unit code of command
By customizing R2_NEW_BYTE, IR_NEW, TW_NEW etc. you can tailor the response
to incoming data.
I have written some memory management routines that automatically
assign register locations to variables. Here is an example. To allocate
a register location to the variable TEMP_W, and TEMP_STAT, you use the
syntax:
ALLOC TEMP_W
ALLOC TEMP_STAT
Since this is the first ALLOC statement, TEMP_W is assigned the register
0CH, and TEMP_STAT is assigned the location 0DH. You can continue to do
this for all your variables until you run out of memory. When this occurs,
the compiler will hit the statement:
CALL OUT_OF_MEMORY
This is a dummy call, and will cause an error message with the words
OUT_OF_MEMORY. When you see this, you know that you have run out of RAM.
The above mechanism allows you to enable and disable modules and have the
memory locations be allocated efficiently. In other words, you can
have a PIC with just the RS232 module enabled, and expand the FIFO to
use as much RAM as possible.
Don't forget to set the variables FXTAL and INTSEC at the top of the
lib.h file. The former is your clock frequency, the latter is the
desired number of interrupts/second.
Bugs
As mentioned above, to send something, you just set some variables,
and call the appropriate routine. If the send queue is full, the routine
has to wait until the interrupt handler empties a spot. The problem occurs
when the interrupt handler itself needs to send data. If the queue is
full, the microprocessor will hang (since the queue will never empty). In
that case, the watchdog timer will timeout, and the chip resets.
The above problem can occur especially with the IR and X-10 modules.
Their send queues are only one command deep (due to limited memory on PICs).
You must be careful not to send too many commands per second.
One way to prevent the watchdog from timing out is to write a second
version of the send initiate routine--one that is called by the interrupt
service routine only. This version does not wait until the queue has an
open spot, but returns immediately. With or without this second version
of the send routine, data is lost anyway. This situation can be properly
remedied by allocated more memory to their send routines and writing
larger FIFOs for them.
Modification History.
See lib.h for mod history.
Circuit Connection for 16C71
I am working on a circuit schematic. In any case, the circuit is simple
enough that you can wire it up with the info below.
1 (X-10) TW523 data output (see Note 1)
2 (IR) input (see Note 4)
3 (IR) output
4 +5 Volt (Mclr)
5 Ground
6 (LCD) DB4 (see Note 2)
7 (LCD) DB5
8 (LCD) DB6
9 (LCD) DB7
10 (LCD) ENABLE
11 (LCD) Register Select
12 (RS232) input (see Note 3
13 (RS232) output
14 +5 Volt
15 crystal
16 crystal
17 (X-10) TW523 zero crossing input
18 (X-10) TW523 data input
Notes.
1) TW523 pin 2 goes to ground.
2) LCD is an Optrex DMC Series 16x1 line display from ALL ELECTRONICS.
Supply power and ground according to spec, add a contrast control
pot. Be sure R/W input of LCD is grounded.
3) Use an RS232 driver such as the Maxim MAX203.
4) IR input is from a 'cube' such as Radio Shack 276-137.
IR output goes to a 40KHz gated IRED flasher. When the output goes
'high', the IRED should flash. I use a 555 oscillator (has high
current sourcing capability) by applying the gate input to pin 4.
Distribution Policy
This software is intended for non commercial use and as shareware. Your
contribution can be anything you wish, but I think that $15 to $30 is a
common shareware fee. Please mail to the address at the top of this file.
The files follow in text format. The top of each file
is marked by a line of asterisks *******.
The following files are in the package:
read.me ;you are reading this file.
irdemo.asm ;assemble this file - starts with some simple demos, and
;continues with an RS232 controlled IR remote. The mapping
;of RS232 characters to IR function is as follows:
;U - Volume Up. D - Volume Down.
;u - Channel Up. d - Channel Down.
;Send the above characters to the chip, and it sends out the
;corresponding IR command. The LCD display shows all received
;IR commands, and characters typed from the RS232 port.
x10demo.asm ;assemble this file - has RS232 controlled X10 interface.
;format of commands is: XC_NN<return>, where NN is the X10
;command. Example 'Et' is Housecode E and Keycode ON.
;Response is CX_NN<return>, format similar to commands.
p16cxx.inc ;file from Microchip, contains defs for P16 family of registers.
lib.h ;pic library.
The last line in this message should be:
;***** END OF FILE *****
Let me know if it isn't. All the best!
;***************************************
TITLE "Library Demo Program"
; Edward Cheung, Ph.D. ;
; Compiled with MPASM 1.20 ;
; Loaded with PICSTART 4.02 ;
;***************************************
;Select library modules. Use 1/0, TRUE/FALSE not defined yet.
CONSTANT AD_ENABLE = 0
CONSTANT R2_ENABLE = 1
CONSTANT R4_ENABLE = 0
CONSTANT LCD_ENABLE = 1
CONSTANT IR_ENABLE = 1
CONSTANT TW_ENABLE = 0
INCLUDE "LIB.H" ;pic library
MAIN
;Initializations
CALL GEN_INIT
;simple module demos
IF LCD_ENABLE == TRUE
MOVLW 'H' ;Print 'Hi' on LCD
CALL LCD_PRINT
MOVLW 'i'
CALL LCD_PRINT
MOVLW H'10' ;Put cursor at start
CALL LCD_PRINT
CLRWDT
ENDIF
IF R2_ENABLE == TRUE ;Print 'Hi' on terminal
MOVLW 'H'
CALL R2_SEND
MOVLW 'i'
CALL R2_SEND
CLRWDT
ENDIF
IF TW_ENABLE == TRUE
MOVLW 'E' ; tw_o_house = E;
MOVWF TW_T_HOUSE
MOVLW '1' ; tw_o_key = 1;
MOVWF TW_T_KEY
CALL TW_SEND
MOVLW 'E' ; tw_o_house = E;
MOVWF TW_T_HOUSE
MOVLW 't' ; tw_o_key = on;
MOVWF TW_T_KEY
CALL TW_SEND ; Send
CLRWDT
ENDIF
IF IR_ENABLE == TRUE
MOVLW D'1' ; TV = 1
MOVWF IR_T_DEV
MOVLW D'19' ; Volume Down = 19
MOVWF IR_T_DATA
CALL IR_SEND ; Send
CLRWDT
ENDIF
;Do some real work with the library
;vars for RS232->IR command interpreter
ALLOC COM_BYTE ;int com_byte; //received byte to interpret
MAIN_LOOP
GOTO MAIN_LOOP ;//do foreground processing here
IF R2_ENABLE == TRUE
;This gets called when there is a new byte from rs232 serial line.
;A 'U' causes a 'Volume Up' command to be sent, a 'D' causes a
;'Volume Down' to be sent, a 'u' causes a Channel Up, and a 'd'
;a Channel Down (in SONY SIRCS format).
R2_NEW_BYTE
MOVWF COM_BYTE ;com_byte = W;
CALL R2_SEND ;//echo to serial out
R2_TEST_VOUP ;if (com_byte == 'U')
MOVFW COM_BYTE
SUBLW 'U'
SKPZ
GOTO R2_TEST_VODN
MOVLW D'1' ; TV = 1
MOVWF IR_T_DEV
MOVLW D'18' ; Volume Up = 18
MOVWF IR_T_DATA
CALL IR_SEND ; // Send IR
GOTO R2_NEW_END
R2_TEST_VODN ;else if (com_byte == 'D')
MOVFW COM_BYTE
SUBLW 'D'
SKPZ
GOTO R2_TEST_CHUP
MOVLW D'1' ; TV = 1
MOVWF IR_T_DEV
MOVLW D'19' ; Volume Down = 19
MOVWF IR_T_DATA
CALL IR_SEND ; // Send IR
GOTO R2_NEW_END
R2_TEST_CHUP
MOVFW COM_BYTE ;if (com_byte == 'u')
SUBLW 'u'
SKPZ
GOTO R2_TEST_CHDN
MOVLW D'1' ; TV = 1
MOVWF IR_T_DEV
MOVLW D'16' ; Channel Up = 16
MOVWF IR_T_DATA
CALL IR_SEND ; // Send IR
GOTO R2_NEW_END
R2_TEST_CHDN ;else if (com_byte == 'd')
MOVFW COM_BYTE
SUBLW 'd'
SKPZ
GOTO R2_PRINT
MOVLW D'1' ; TV = 1
MOVWF IR_T_DEV
MOVLW D'17' ; Channel Down = 17
MOVWF IR_T_DATA
CALL IR_SEND ; // Send IR
GOTO R2_NEW_END
R2_PRINT ;else
MOVFW COM_BYTE
CALL LCD_PRINT ; //display on lcd
R2_NEW_END
RETURN
ENDIF
END
;***************************************
TITLE "Library Demo Program"
; Edward Cheung, Ph.D. ;
; Compiled with MPASM 1.20 ;
; Loaded with PICSTART 4.02 ;
;***************************************
;Select library modules. Use 1/0, TRUE/FALSE not defined yet.
CONSTANT AD_ENABLE = 0
CONSTANT R2_ENABLE = 1
CONSTANT R4_ENABLE = 0
CONSTANT LCD_ENABLE = 0
CONSTANT IR_ENABLE = 0
CONSTANT TW_ENABLE = 1
INCLUDE "LIB.H" ;pic library
MAIN
;Initializations
CALL GEN_INIT
;Do some real work with the library
;vars for RS232->IR command interpreter
ALLOC COM_BYTE ;int com_byte; //received byte to interpret
ALLOC COM_STATE ;int com_state; //state of command state machine
CONSTANT ADDRESS = 'X'
ALLOC TW_P_HOUSE
ALLOC TW_P_KEY
;inits for main program
CLRF COM_STATE ;com_state = 0;
MAIN_LOOP
GOTO MAIN_LOOP ;//do foreground processing here
;This gets called when there is a new byte from rs232 serial line.
R2_NEW_BYTE
MOVWF COM_BYTE ;com_byte = W;
; CALL R2_SEND ;//echo to serial out
R2_STATE0 ;if (com_state == 0)
MOVFW COM_STATE
SUBLW D'0'
SKPZ
GOTO R2_STATE1
MOVFW COM_BYTE ; if (com_byte == address)
SUBLW ADDRESS
SKPNZ
INCF COM_STATE,F ; com_state ++;
GOTO R2_END_NEW
R2_STATE1 ;else if (com_state == 1)
MOVFW COM_STATE
SUBLW D'1'
SKPZ
GOTO R2_STATE2
INCF COM_STATE,F ; com_state ++;
GOTO R2_END_NEW
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -