Consideration of a program address
In PIC16F series, the maximum address range which an instruction can operate directly is from 0 to 2047. PIC16F873 has 4K words program memory. Therefore, in order to access the program memory after 2048, it is necessary to set up the contents of the PCLATH register each time.
In PIC16F series, a program memory is managed by 2K words unit. This unit is called a page. The page of a program memory is specified by the 3rd and 4th bit of a PCLATH register.
In order to jump by GOTO or CALL exceeding each page, LGOTO or LCALL is used.
These are called Directive. These are not the instruction of PIC16F. It is automatically changed as follows when assembling a source code with these directions.
This is the example which jumps from page 0 to INIT (the address in the page : h'3FE") of page 1.
Source code
LGOTO INIT Assembling result
158A BSF PCLATH,3
120A BCF PCLATH,4
2BFE GOTO h'3FE'
You can see that it set "1" to the 3rd bit of PCLATH and the page is changed to page 1.
It is automatically processed in LGOTO as mentioned above if jumping only like GOTO.
In case of LCALL, it is necessary to consider
In this case, it is necessary to set PCLATH after returning from the subroutine.
When jumping by LCALL, PCLATH is rewritten automatically like LGOTO.
This is the example which calls the subroutine (the address in a page: h'ED") in page 0 from page 1.
Source code
LCALL GET_TBL_DATA Assembling result
118A BCF PCLATH,3
120A BCF PCLATH,4
20ED CALL h'ED"
3rd bit and 4th bit of PCLATH are cleared and it is changed to page 0.
RETURN is executed at the end of the subroutine to return to the original processing.
RETURN refers to the return address which was written at the stack memory and jumps to the original address. However, PCLATH is NOT rewritten.
Therefore, it is necessary to set up PCLATH at the point which returned. Otherwise, the program of a different page is performed. There is no directive called LRETURN.
In this program, PCLATH is set up with SETPCH macro.
setpch macro
if ($ >= 0) && ($ < 0x800)
bcf PCLATH,3
else
bsf PCLATH,3
endif
endm
"$" shows its address. Only the 3rd bit of PCLATH is set because it is using only page 0 and page 1 in case of PIC16F873.
SETPCH macro is always put after calling a subroutine in LCALL.
An assembly list about LCALL with the 2290th line is shown below.
M-ADR is the machine address of a hexadecimal display, M-CODE is a machine language code and S-ADR is a source code address.
In this case, because the program position is after h'800', it is the position of page 1. Therefore, with SETPCH macro, only the code which sets the 3rd bit of PCLATH as 1 is developed.
Allocation of the program
Fundamentally, a subroutine is allocated to a page 0 and the main routine and the interruption processing routine are allocated to the page 1.
Initial routine
03433 ;####################################################################
03434 ;
03435 ; Initial routine
03436 ;
03437 ;####################################################################
If a power supply is switched on and a program starts from the address 0, it will jump to this processing. The hardware and software environment of PIC is set up by an initialization routine.
The contents of a setting of SFR are made a list below.
|
Register | Initial value | Description |
PORTA
PORTB
PORTC | 00000000 | The contents of each port register are cleared. |
RCSTA | 10010000 | A serial port is used. Continuing reception is set. |
ADCON0 | 00000000 | A/D conversion function isn't used. |
ADCON1 | 00000110 | All ports are used as the digital port. |
TRISA | 00010000 | RA4 is set as input mode. Others are set as output mode. |
TRISB | 00001100 | RB2, RB3 are set as input mode. Others are set as output mode. |
TRISC | 11000000 | RC6, RC7 are set as input mode. Others are set as output mode. |
OPTION_REG | 00000000 |
Inner pull up isn't used. Internal clock is used.
Prescaler is used for the TMR0 timer. Prescaler value is 1:2. |
SPBRG | 01010010 | 9,600 bps is specified. ( Value is 82 ) |
TXSTA | 00100110 |
8 bits communication. Transmit enable. Asynchronous mode. High speed.
"1" is set to the TRMT bit. But it's unnecessary because it's read only. |
T2CON | 00000110 | Postscaler of timer 2 is 1:1. Timer 2 is used. Prescaler is 1:16. |
TMR2 | 00000000 | The value of timer 2 is cleared. |
PR2 | 00010011 |
Timer 2 period is set. Set value is count value (20) - 1.
(1/12.8MHz)*(4cycle/clock)*(20count(PR2))*(16(Prescaler))
0,078125uS*4*20*16=100uS |
PIE1 | 00100010 | USART receive interrupt is used. TMR2 to PR2 match interrupt is used. |
INTCON | 11000000 | Enables all un-masked interrupts. Enables all un-masked peripheral interrupts |
|
The following initialization processings are performed in addition to the above.
Initialization of various work areas
Initialization of time area
Time display mode reading from EEPROM
Initialization of a liquid crystal display
Main routine
03536 ;####################################################################
03537 ;
03538 ; Main routine
03539 ;
03540 ;####################################################################
In the main routine, the following processing is done.
Initial message display Software flow chart (1/11) |
|
Initial message is displayed for 2 seconds immediately after the turning on.
|
Update of the time display Software flow chart (1/11) |
|
A time stamp is updated every second by "clock_main" subroutine. The calling of a subroutine is cyclically done irrespective of 1 second. Update timing in 1 second is judged in the subroutine. The reason for making a subroutine is to update a time stamp while time setting is done. In case of keying-in wait, "clock_main" is always called and a time stamp update is done.
|
Processing of a time setting key Software flow chart (2/11), Software flow chart (3/11) |
|
This processing is processing with most steps in a main routine.
At first, whether or not a menu key was pushed is checked. The key which should be pushed first is a menu key and the other key push is invalid.
In the waiting time of the key operation, it is set to 10 seconds. If 10 seconds pass since the last key operation, the key operation till then will become invalid.
03672 CALL DISP_MAIN ;Time display
Above-mentioned processing is the subroutine calling which is written in the lower right of Software flow chart (1/11). You can think that there is no necessity since "disp_main" subroutine is used also in "clock_main" subroutine. However, "clock_main" subroutine updates a display only every second. Therefore, when escaping from key processing, it is necessary to call "disp_main" subroutine, and it is necessary to display time immediately. At the time of key operation, the message of key operation is displayed on the display, and time is not displayed.
"Time stamp mode changing" or "Setting of a timer" is performed by the key to operate after the first menu key.
|
"clock_main" subroutine Software flow chart (4/11) |
|
The display timing of a display and the timing of decoding are judged in this subroutine. A display is updated by "disp_main" subroutine every 0 second. Moreover, "dec_time" subroutine is executed for every 400 miliseconds. In this subroutine, processing which analyzes the information put on the electric wave and is changed into time information is performed.
|
"disp_main" subroutine Software flow chart (5/11) |
| In this subroutine, processing which displays time or a message on LCD is performed. |
Interruption processing
03973 ;####################################################################
03974 ;
03975 ; Interruption processing
03976 ;
03977 ;#################################################################### With this equipment, two kinds of interruption, "periodic interruption by a timer 2" and "reception interruption of a serial circuit", is used. In interruption of those other than the two above-mentioned kind, the same processing as timer 2 interruption is executed by interruption judgment processing. When assuming extraordinary operation, to have made jump to "End of interruption" is safer.
03979 BTFSC PIR1,TMR2IF ;timer2(100uS) int ?
03980 GOTO TIMER_INT ;Yes.
03981 BTFSC PIR1,RCIF ;RX int ?
03982 GOTO SIO_INT ;Yes.
GOTO INT_VEC1 ;No. Jump to return Periodic interruption in every 100 microseconds by a timer 2
By interruption processing for 100 microseconds, the following processings are executed.
* Subtraction of a 100uS counter ( Every 100uS ) Software flow chart (6/11)
In this software, LCD etc. are controlled per 100uS. ( delay 100u subroutine )
In order to make this time, the counter value is subtracted by interruption processing of 100uS.
* Subtraction of a 10mS counter ( Every 10mS ) Software flow chart (6/11)
Time is measured to 10mS based on 100uS interruption, and the counter of 10mS is subtracted.
* LED lighting time control ( Every 10mS ) Software flow chart (6/11)
The signal of true second, true minute, true hour, true day and true month are outputted only 100mS.
* Information analysis of TCO(Time Code Output) ( Every 10mS ) Software flow chart (7/11), Software flow chart (8/11)
There are three kinds of signals of TCO. They are operating by the following standards and judging standards.
Kind | Standard | Criterion in processing |
Marker | 200mS ± 5mS | 80mS to 280mS |
"1" signal | 500mS ± 5mS | 400mS to 600mS |
"0" signal | 800mS ± 5mS | 700mS to 880mS |
As for a TCO signal, the kind of signal is judged by the time from falling edge to rising edge of the signal.
The detected TCO code is stored in "tco_code" and it is analyzed in the second, the minute, the hour, the week, the day, the month and the year by the time decoding processing. The information on the month and the day are not included in TCO. The leap year and the normalized day information (sum total day from January 1st) are included. The processing which changes into the information the month and the day based on them is executed with this equipment.
* Key push detection ( Every 10mS ) Software flow chart (9/11), Software flow chart (10/11)
The control ports of the keys(F2, F3, F4 and timer-OFF) and the LCD are sharing. Therefore, when detecting a key condition, RB4, RB5, RB6 and RB7 should be changed to the input mode from the output mode. It is again returned to the output mode when the key condition detection ends.
When a key push was detected, the number of the key which was pushed is checked. The number of the key is stored in "key_dat".
When a key is continuously pushed, it does the same operation when operating more than one time like a keyboard operation of the PC. This is for operation to be simplified. This operation is managed using "key_sts". When setting "key_sts" to "1", it becomes a key processing request. Because it is, when detecting continuous key operation, the effect which is the same when operating more than one time is gotten by setting "key_sts" by the specific time. On the flow chart, some of the parts of the set/clear of "key_sts" is shown. It is not all. For details, please refer to the source code.
The update speed by the continuing push time changes as follows.
Continuing push time | Update speed |
to 500mS | no updat automatically |
500mS to 2400mS | every 300mS |
over 2400mS | every 100mS |
The operation of the timer time setting can be done quickly by this function.
However, this function works by all key operation in addition to the time setting. So, when pushing Menu key continuously from the condition of the time display, it repeats the following operation.
Time display screen -> Timer selection screen -> 12H/24H mode selection screen -> Time display screen ... (Repeat)
This prevention processing isn't done.
Character reception interruption with the serial communication circuit Software flow chart (11/11)
Every time the data of 1 character is received with the serial circuit, the interruption occurs.
Reception processing itself is executed with the hardware of PIC. Even if the reception interruption occurs, it isn't always normally received. Therefore, in the beginning of the reception interruption processing, the confirmation whether or not which was normally received is done. In the malfunction in the reception operation, there are following two kinds.
Framing error : When the stop bit can not be detected in the signal from the serial circuit
Overrun error : When the following data is sent from the serial circuit while not reading contents in the reception buffer
When above-mentioned error occurs, a received data is canceled and the initialization of the reception circuit is done.
The framing error occurs with the noise. Also, it occurs to the thing except the above when the speed specification of the sender and receiving end aren't right. The overrun error occurs when the reception processing of software isn't working normally. It's when the data which was received with the hardware isn't read by the software. It doesn't occur if the software doesn't have a bug.
When the result of above-mentioned error checking is normally, received data is stored in the memory address which "rx_ptr" shows. The reception of the command ends when receiving CR(Carriage Return : It returns a print head to the origin) information as the received data. LF(Line Feed) is the signal which proceeds with the paper for 1 line. These signals are a data format from the time when the printer of the typewriter formula was used.
Subroutine
The list of the subroutines currently used by this software is shown below. |
Name | Function |
lcd_init | Initialization of the LCD module |
lcd_e_pulse | Output 0.625uS pulse to E ternminal of LCD |
print | One letter display |
messout | Message display |
cls | Clear display |
locate | Change cursor location |
csr_on | Cursor indication |
csr_off | Cursor non-indication |
lcd_iwr | Write data to LCD instruction register |
lcd_dwr | Write data to LCD data register |
disp_second | Second display |
disp_minute | Minite display |
disp_hour | Hour display |
disp_day | Day display |
disp_month | Month display |
disp_year | Year display |
disp_wday | Week display |
disp_nday | Normalized day display |
disp_time | Time display |
disp_date | Date display |
disp_ok | Normal reception display |
disp_ng | No reception display |
disp_timer | 1st line of timer set display |
disp_tm_set | Time set value display |
| |
sio_job | Serial communication processing |
cmd_check | Command check |
sout_time | Send out Time |
sout_date | Send out Date |
sout_stime | Set time output suspension for synchronizing with second |
sout_status | Send out time adjusted status |
cmd_set_timer | Time setting command |
sout_timer | Send out set time |
sout_decode | Send out decode status |
cmd_timer_on | Timer ON command |
cmd_timer_off | Timer OFF command |
sout_err | Send out error message |
sout | Send out one character to serial port |
ssout | Send out characters to serial port |
sout_second | Send out second |
sout_minute | Send out minute |
sout_hour | Send out hour |
sout_day | Send out day |
sout_month | Send out month |
sout_year | Send out year |
sout_wday | Send out week |
cv_str2num | Change two characters to binary |
sout_num2d | Send out two characters |
|
|
Name | Function |
get_tbl_data | Read data from data table |
| |
inc_time | Increment 1 second |
inc_date | Increment 1 day |
inc_dec_time | Increment backup 1 munite |
cvt_nd2day | Convert normalized day to month and day data |
| |
addw | Addition [ BCCH,BCCL = BCCH,BCCL + ACCH,ACCL ] |
mulib | Multiplication [ BCCH,BCCL = BCCH,BCCL + (ACCL * W) ] |
divb | Division [ ACCH = ACCL / W ] |
us_subw | Subtraction [ ACCH,ACCL = ACCH,ACCL - BCCH,BCCL ( No borrows ) ] |
| |
init_time | Initialization of date and time |
init_dec_time | Initialization of decoded date and time |
init_bk_dec_time | Initialization of decoded backup date and time |
init_tm_chk_cnt | Initialization of decode check counter |
chk_tm_chk_cnt | Check decode check counter |
adjust_0s | Adjustment in 0 seconds |
copy_time | Copy the decoded time to display time |
dec_time | Time decoding |
search_mark | 0 seconds marker detection |
dec_time_m | Minute decoding |
dec_time_h | Hour decoding |
dec_time_nd | Normalized day(ND) decoding |
dec_time_y | Year decoding |
dec_time_wd | Week decoding |
delay100u | 100 microseconds delay |
delay10m | 10 miliseconds delay |
| |
chk_eep_dat | Check EEPROM data |
eeprom_init | Initialize EEPROM |
rd_eeprom | Read EEPROM data |
wr_eeprom | Write EEPROM data |
chk_timer | Check time of Timer |
timer_off | Timer OFF |
comp_timer | Compare Timer time and Present time |
set_tmbf_data | Set timer data to EEPROM |
get_tmbf_data | Read timer data from EEPROM |
get_tm_data | Read designated timer data from EEPROM |
set_tm_data | Write designated timer data to EEPROM |
set_tm_lim | Set upper limit of timer |
|
|