Hernán Freschi said:
Have you tried adding dec 128 to the base address? In Bank 1, can't
access 0x70, you have to access F0h, to read/write what's on 0x70h --the
common memory.
hjf
Is it april first already? You are joking right?
it is a banked design, one can only address locations between 0 and 7f.
The only (stupid) reason why registes outside of bank 0 are defined with
more than 7 bits is so they can print warnings ( I guess), instead of having
separate table indicating what registers are in what banks.
Before I found the include files I started to write my own and later this was
the first think that struck me.
However I am still not having any luck even after adding a substantial delay.
For a long time I was stuck, untill I realized the problem was with Hyperterm
no longer working ( at 9600). When I finaly tried the serial sample
'
http://www.oz1bxm.dk/PIC/628uart.htm" worked fine even in Hyperterm.
When I set it to 2400 last time I checked I got "?>>>READ" instead of
"?>>>READY." in Hyperterm, what made me believe the frequency is off.
With a MSC++ 5.0 sample terminal program I get the full first message but another
message (9-0) placed in the circular buffer is not comming out.
Here is the full code if anyone wants to try it.
----------------------------------------------------
;**********************************************************************
; This file is a basic code template for object module code *
; generation on the PICmicro PIC16F628A. This file contains the *
; basic code building blocks to build upon. As a project minimum *
; the 16F628A.lkr file will also be required for this file to *
; correctly build. The .lkr files are located in the MPLAB *
; directory. *
; *
; If interrupts are not used all code presented between the *
; code section "INT_VECTOR and code section "MAIN" can be removed. *
; In addition the variable assignments for 'w_temp' and *
; 'status_temp' can be removed. *
; *
; If interrupts are used, as in this template file, the 16F628A.lkr *
; file will need to be modified as follows: Remove the lines *
; CODEPAGE NAME=vectors START=0x0 END=0x4 PROTECTED *
; and *
; SECTION NAME=STARTUP ROM=vectors *
; and change the start address of the page0 section from 0x5 to 0x0 *
; *
; Refer to the MPASM User's Guide for additional information on *
; features of the assembler and linker (Document DS33014). *
; *
; Refer to the respective PICmicro data sheet for additional *
; information on the instruction set. *
; *
;**********************************************************************
; *
; Filename: xxx.asm *
; Date: *
; File Version: *
; *
; Author: *
; Company: *
; *
; *
;**********************************************************************
; *
; Files required: *
; 16F628A.lkr (modified) *
; *
; *
;**********************************************************************
; *
; Notes: *
; *
; *
; *
; *
;**********************************************************************
list p=16F628A ; list directive to define processor
#include <p16F628A.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
;***** VARIABLE DEFINITIONS (examples)
; example of using Shared Uninitialized Data Section
INT_VAR UDATA 0x20
timer1_prescaler res 1 ; /start
PB7_old_val res 1
PB7_new_val res 1
timer_lo res 1
timer_hi res 1
timer1_timeouts res 1
ResultsA res 1 ; port A outputs
; 0 - 0, 1, 2, 3, 4, 6 characters in output buffer
; 1 -
; 2 -
; 3 -
; 4 -
; 5 - VPP/!MCLR always input
; 6 -
; 7 - baud rate input HI/LO (BRGH bit)
ResultsB res 1 ; port B outputs
; 0 - timer read hickup indicator
; 1 - Async RX
; 2 - Async Tx
; 3 - ?IR output? not yet implemented
; 4 - PGM
; 5 - IR input
; 6 - PGC
; 7 - PGD
DD_PA equ 0xa0
DD_PB equ 0xf2
;###################################################################################
; Commands from the serial port precceded by 00 AA sync chars
; Read or write registers
; 101 00001 read register specified in following byte
; 101 00010 write register specified in following byte with data in next additional byte
;
sync_OK res 1 ; set to 0 when 0 received incremented when AA received
Last_command res 1 ; if sync is 1 store bytes
Command_data1 res 1 ; usualy address
Command_data2 res 1 ; usualy data value
Free_ram:
INT_VAR_SHR UDATA_SHR 0x71
w_temp res 1 ; variable used for context saving
status_temp res 1 ; variable used for context saving
temp1 res 1 ; used by place_byte_in_output_buffer
temp2 res 1 ; used by place_byte_in_output_buffer
temp3 res 1
buff_head res 1 ; points to where new data is stored
buff_tail res 1 ; points to which byte is next to be transmited ( read advance )
buff_start res 1 ;
buff_end res 1
new_buff_head res 1
TX_char_count res 1
TX_max_char_count res 1
;**********************************************************************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto main ; go to beginning of program
INT_VECTOR CODE 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
swapf STATUS, w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
; isr code can go here or be located as a call subroutine elsewhere
banksel INTCON
btfss INTCON, 0
goto portB_no_change
movfw PORTB
andlw 0x80
movwf PB7_new_val
subwf PB7_old_val, f
btfsc STATUS, Z
goto int_done
movfw TMR1H
movwf timer_hi
movfw TMR1L
movwf timer_lo
movf TMR1H, w ; Read high byte
SUBWF timer_hi, W ; Sub 1st read with
; 2nd read
BTFSC STATUS, Z ; Is result = 0
GOTO done_reading_timer ; Good 16-bit read
bsf ResultsB, 0
decf timer_hi
done_reading_timer:
clrf TMR1H
clrf TMR1L
clrf timer1_timeouts
; output the data to the Async output buffer
; test if change is L/H or H/L
btfss PB7_new_val, 5
goto bit_end
bsf timer_hi, 7 ; slap the bit start indicator into the highest bit
movfw timer_hi
call place_byte_in_output_buffer
movfw timer_lo
call place_byte_in_output_buffer
goto data_output_complete
bit_end:
bcf timer_hi, 7 ; slap the bit end indicator into the highest bit
movfw timer_hi
call place_byte_in_output_buffer
movfw timer_lo
call place_byte_in_output_buffer
data_output_complete:
portB_no_change:
btfss PIR1, TMR1IF ; did timer 1 overflow?
goto timer1_service_done
bcf PIR1, TMR1IF
; clear a byte somewhere?
incf timer1_timeouts
movlw 14
subwf timer1_timeouts, f
btfss STATUS, C
goto timer1_service_done
clrf timer1_timeouts
incf timer1_timeouts
bcf ResultsB, 0 ; clear timer read faulup indicator
timer1_service_done:
int_done:
swapf status_temp, w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp, f
swapf w_temp, w ; restore pre-isr W register contents
; bsf ResultsB, 3
retfie ; return from interrupt
place_byte_in_output_buffer:
; pointers - test write/read advance
movwf temp1
; test if head + 1 is equal tail , if so buffer is full!!!
; first test if it hits end of buffer
movfw buff_head
addlw 1
movwf new_buff_head
; movwf temp2
subwf buff_end, w
btfsc STATUS, Z
goto head_hit_end
; now test it against the tail pointer
movfw new_buff_head
subwf buff_tail, w
btfsc STATUS, Z
goto buffer_full
goto place_character
head_hit_end:
; head will be pointing to beginning - is tail currently pointing to the beginning?
movfw buff_tail
subwf buff_start, w
btfsc STATUS, Z
goto buffer_full
movfw buff_start
movwf new_buff_head
place_character:
movfw buff_head
movwf FSR
movfw temp1
movwf INDF
movfw new_buff_head
movwf buff_head
character_qued_for_output:
bcf STATUS, C
return
buffer_full:
bsf STATUS, C
return
main
; remaining code goes here
bcf STATUS, RP0 ; RAM PAGE 0
bcf STATUS, RP1 ; RAM PAGE 0
movlw 7 ; turn comparator off
movwf CMCON
movlw 0x00
movwf PORTA
movlw 0x04
movwf PORTB
banksel OPTION_REG
bcf OPTION_REG, NOT_RBPU
bsf STATUS, RP0 ; RAM PAGE 1
movlw 0x0f ; high speed int osc, POR and BOR
movwf PCON
movlw DD_PA
movwf TRISA ; PA5, PA7 inputs
movlw DD_PB ; RB7-RB4 and RB1(RX)=input, others output
movwf TRISB
banksel PORTB
movlw 0x04
movwf PORTB
movwf ResultsB
movwf PORTA
movwf ResultsA
banksel T1CON
movlw 0x21 ; prescale /4, enable timer
movwf T1CON
clrf T1CON
movwf timer1_prescaler
movlw 0x30
andwf timer1_prescaler
;;? movlw 0xc8 ; enable global interrupts, peripheral interrupts, interrupt on change of port B
;;? movwf INTCON
bsf STATUS, RP0 ; RAM PAGE 1
;;? bsf PIE1, TMR1IE ; enable timer 1 interrupts, timeout clears any in-progrees IR character reception??
; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit
;
banksel SPBRG
movlw 0x19 ; 0x19=9600 bps (0x0C=19200 bps)
movwf SPBRG
movlw b'00100000' ; brgh(2) = high
movwf TXSTA ; enable Async Transmission, set brgh
bcf STATUS, RP0 ; RAM PAGE 0
movlw b'10010000' ; enable Async Reception and continuous receive
movwf RCSTA
; bsf PIR1, TXIF ; set tx reg empty interrupt flag
bcf STATUS, RP0 ; RAM PAGE 0
call check_baud_rate_input
clrf temp1
settle decfsz temp1,F
goto settle
; setup the circular buffers
movlw Free_ram
addlw 10
andlw 0f0
movwf buff_start
movwf buff_head
movwf buff_tail
movlw 70
movwf buff_end
bsf ResultsA, 3
bsf PORTA, 3
bcf STATUS, RP0 ; bank 0
movlw 0x23
movwf TXREG
bsf STATUS, RP0 ; bank 1
clrf EEADR
get_next_char
bsf STATUS, RP0 ; Bank1
bsf EECON1, RD ; EE Read
movfw EEDATA
wait_trans_complete:
bcf STATUS, RP0 ; bank 0
btfss PIR1, TXIF ; (1) transmission is complete if hi
goto wait_trans_complete
movwf TXREG ; send data in W
bsf ResultsA, 2
bsf PORTA, 2
sublw 0
btfsc STATUS, Z
goto ready_mess_done
bsf STATUS, RP0 ; Bank1
incf EEADR
goto get_next_char
ready_mess_done:
bcf STATUS, RP0
bcf ResultsA, 4
bcf PORTA, 4
;************************** DEBUG CODE ************************
; setup buffer pointers to point near the end of buffer
movlw -5
addwf buff_end, w
movwf buff_head
movwf buff_tail
send_test_message: ; if baudrate changed, main loop starts here send 9-0 digits
movlw 0x39 ; prepare ASCII of '9'
movwf temp3
send_next_byte:
movfw temp3
call place_byte_in_output_buffer
movlw 0x30
subwf temp3, w
btfsc STATUS, Z
goto main_loop
decf temp3
goto send_next_byte
clrf temp3
;************************ END DEBUG CODE **********************
main_loop:
; first see if there is any data in the transmit buffer
; and calculate the number of bytes in there for performance monitoring
; otherwise it can be all dumped and transmit_data called blindly.
movfw buff_tail
subwf buff_head, w
btfsc STATUS, Z
goto check_for_incoming_data
btfsc STATUS, C
goto was_positive
movwf TX_char_count
movfw buff_end
addwf TX_char_count
movfw buff_start
subwf TX_char_count
goto calc_count_done
was_positive:
movwf TX_char_count
calc_count_done:
movfw TX_max_char_count
subwf TX_char_count, w
btfss STATUS, C
goto new_char_count_max_done
movfw TX_char_count
movwf TX_max_char_count
new_char_count_max_done:
; debug_code: generate inter character spacing
incf temp3
btfss STATUS, Z
goto check_for_incoming_data
movlw 0x80
call transmit_data
; poll async receive for commands
check_for_incoming_data:
check_for_commands:
; if OK to change baudrate ie UART shift reg empty, timer 1 timed out ( at least once )
; command not being received (sync received)
; !!! CURRENTLY just DOIT !!!
call check_baud_rate_input
movfw ResultsB
movwf PORTB
goto main_loop ; loop forever, remove this instruction, for test only
transmit_data:
;********************************************************************
; Transfer byte from cyrcular output buffer into transmit register
; if transmit register flag ( TXIF in PIR1 )indicates it is empty
; inputs: no direct input
; outputs: flag Z= 0 indicates byte was transfered
; 1 uart full/busy or no bytes in output buffer
;********************************************************************
; see if we can transmit
bcf STATUS, RP0 ; RAM PAGE 0
btfss PIR1, TXIF ; is transmit reg empty
goto no_data_to_transmit ; check UART for data
; is there anything in the buffer?
movfw buff_head
subwf buff_tail, w
btfsc STATUS, Z
goto no_data_to_transmit
place_in_TX_REG:
movfw buff_tail
incf buff_tail
movwf FSR
movfw INDF
bsf STATUS, RP0 ; bank 1
movwf TXREG
bcf STATUS, RP0 ; bank 0
movfw buff_end
subwf buff_tail, w
btfss STATUS, Z
goto tail_pointer_OK
movfw buff_start
movwf buff_tail
tail_pointer_OK:
bcf STATUS, Z
return
no_data_to_transmit: ; or chanel not yet free
bsf STATUS, Z
return
check_baud_rate_input:
;*****************************************************
; read external input and reflect it in TXSTA, BRGH
;*****************************************************
bcf STATUS, RP0 ; RAM PAGE 0
btfss PORTA, 7
goto set_low_BRGH
bsf STATUS, RP0 ; RAM PAGE 1
bsf TXSTA, BRGH
goto check_baud_rate_input_done
set_low_BRGH:
bsf STATUS, RP0 ; RAM PAGE 1
bcf TXSTA, BRGH
check_baud_rate_input_done:
bcf STATUS, RP0 ; RAM PAGE 0
return
; initialize eeprom locations
EE CODE 0x2100
DE ">>>READY."
DE 0
END ; directive 'end of program'
-----------------------------------------------------------------
The test circuit
A0 - open
A1 - open
A2 - open
A3 - open
A4 - open
A5 - 2.4K to Vdd
A6 - open
A7 - 20K to Vdd ( baud- select )
B0 - open
B1 - 1.6K to vdd ( AURT input )
B2 - to ttl input of MAX232 CPE
B3 - open
B4 - to b5
B5 - to B6
B6 - to B7
B7 - 10K to Vdd
The only possibly out of spec thing (with the MAX232), I used 10uF caps.
When I used this chip in a circuit over 10 years ago, a circuit I modelled on
used 22uf, while checking recently, various models indicated 100nf or 1uf,
but no specifics for MAX232CPE.
( I should realy hook up for in circuit programming I may even get better than 1 in 10
success rate, lol)
Cheers, Sam