• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

16F88 port B UART assembly

Status
Not open for further replies.

ttbuddy

New Member
As depicted in the 16F88 data sheet, port B 5 have the built in hardware UART function which made serial transmission easier.



However I am new to assembly language. To have RB5 send serial data, I am trying to modify the code shown as below:

I declare the variable for settling time for start up:
Code:
;----------------------
; DECLARE VARIABLES
;----------------------

cblock         0x20
tmp1
endc
and the serial transmission is called:

Code:
Ser_sent:
   banksel      SPBRG
   movlw      2580            ; 9.6kbps
   movwf      SPBRG
   movlw      b'00100000'         ; brgh = high (2)
   movwf      TXSTA            ; enable Async Transmission, set brgh

   ; Provide a settling time for startup
   banksel      tmp1
   clrf       tmp1
   settle
   decfsz       tmp1, f
   goto       settle


   ; Send a character through the UART
loop
   movlw      AmpHours
   call      send
   goto      $

;----------------------
; SEND function
;----------------------
send
   banksel      TXREG
   movwf       TXREG            ; Send data which has been stored in W

trans_wt
   banksel      TXSTA
   btfss       TXSTA, TRMT         ; Loop until data is sent
   goto      trans_wt      
   return

   end
The AmpHour is stored previously as:

Code:
store_Ah:
    mov16    dd+2,AmpHours
How about the tem1 timing for a baud rate of 9.6kbps suggested? Thanks
 

ericgibbs

Well-Known Member
Most Helpful Member
hi tt,

Code:
movlw      [COLOR="Red"]2580    [/COLOR]        ; 9.6kbps
movwf      SPBRG
You cannot load a value greater than 255 decimal into 'W'.

Look at the 16F88 datasheet tables for the UART values, it depends upon the crystal freq and baud rate.
 

geko

Active Member
Code:
Ser_sent:
   banksel      SPBRG
   movlw      2580            ; 9.6kbps
   movwf      SPBRG
   movlw      b'00100000'         ; brgh = high (2)
   movwf      TXSTA            ; enable Async Transmission, set brgh
Code:
   movlw      2580            ; 9.6kbps
The W register is only 8 bits wide so you can only load it with a value between 0 and 255 (0x00 to 0xFF hex).

No idea where the value 2580 has come from but it won't work


Code:
   movlw      b'00100000'         ; brgh = high (2)
This says it sets brgh = high but it is actually setting brgh == 0 which is low speed.

The baud rate is a function of the 16F88 clock speed. If it's running from the internal oscillator at the POR (power on reset) default speed of 4Mhz then you would use:

Code:
Ser_sent:
   banksel      SPBRG
   movlw      .25                  ; 9.6kbps
   movwf      SPBRG
   movlw      b'00100100'      ; brgh = high (2)
   movwf      TXSTA            ; enable Async Transmission, set brgh
 

ttbuddy

New Member
hi tt,

Code:
movlw      [COLOR="Red"]2580    [/COLOR]        ; 9.6kbps
movwf      SPBRG
You cannot load a value greater than 255 decimal into 'W'.

Look at the 16F88 datasheet tables for the UART values, it depends upon the crystal freq and baud rate.
You are right. Thanks.

Code:
Ser_sent:
   banksel      SPBRG
   movlw      2580            ; 9.6kbps
   movwf      SPBRG
   movlw      b'00100000'         ; brgh = high (2)
   movwf      TXSTA            ; enable Async Transmission, set brgh
Code:
   movlw      2580            ; 9.6kbps
The W register is only 8 bits wide so you can only load it with a value between 0 and 255 (0x00 to 0xFF hex).

No idea where the value 2580 has come from but it won't work


Code:
   movlw      b'00100000'         ; brgh = high (2)
This says it sets brgh = high but it is actually setting brgh == 0 which is low speed.

The baud rate is a function of the 16F88 clock speed. If it's running from the internal oscillator at the POR (power on reset) default speed of 4Mhz then you would use:

Code:
Ser_sent:
   banksel      SPBRG
   movlw      .25                  ; 9.6kbps
   movwf      SPBRG
   movlw      b'00100100'      ; brgh = high (2)
   movwf      TXSTA            ; enable Async Transmission, set brgh
How about the temp for starts up? Is it needed for the UART as well? Can I just call the AmpHour just like that? Thanks.
 

geko

Active Member
You are right. Thanks.



How about the temp for starts up? Is it needed for the UART as well? Can I just call the AmpHour just like that? Thanks.

Well I can't see all your code so I don't know what your doing but I don't think it's doing what you intended.

You are not loading the contents of AmpHour into the W register, you are loading the literal value of AmpHour into W.

Since I can't see where you have defined AmpHour I don't know what you are trying to do with it, neither will the assembler so it will probably give an error when you to assemble the code.
 

ttbuddy

New Member
Well I can't see all your code so I don't know what your doing but I don't think it's doing what you intended.

You are not loading the contents of AmpHour into the W register, you are loading the literal value of AmpHour into W.

Since I can't see where you have defined AmpHour I don't know what you are trying to do with it, neither will the assembler so it will probably give an error when you to assemble the code.
AmpHour is declared as below:
Code:
; Amps Accumulated
	LONG	AmpSum   ; addition of all Amp readings
While the code below shows how it is being calculated:
Code:
calc_Ah:
	add1632	Amps,AmpSum	; AmpSum = accumulated Amps
	mov32	AmpSum,dd
	movi16	3600*3,aa	; 3 reads per second, 3600 seconds per hour
	call	Div32		; AmpHours = AmpSum  / (reads per hour)
store_Ah:
	mov16	dd+2,AmpHours
 

geko

Active Member
AmpHour is declared as below:
Code:
; Amps Accumulated
    LONG    AmpSum   ; addition of all Amp readings
While the code below shows how it is being calculated:
Code:
calc_Ah:
    add1632    Amps,AmpSum    ; AmpSum = accumulated Amps
    mov32    AmpSum,dd
    movi16    3600*3,aa    ; 3 reads per second, 3600 seconds per hour
    call    Div32        ; AmpHours = AmpSum  / (reads per hour)
store_Ah:
    mov16    dd+2,AmpHours

That's not PIC assembler.

Maybe someone has written some macro instructions but what you show above is meaningless.
 

ttbuddy

New Member
That's not PIC assembler.

Maybe someone has written some macro instructions but what you show above is meaningless.
I see. Most of them are actually defined here for the macro:
Code:
;====================================================================
;             Macros to create variables in RAM
;

ByteAddr	SET 32     ; user RAM starts here

BYTE		MACRO	ByteName
ByteName	EQU	ByteAddr
ByteAddr	SET	ByteAddr+1
		ENDM

WORD		MACRO	WordName
WordName	EQU	ByteAddr
ByteAddr	SET	ByteAddr+2
		ENDM

LONG		MACRO	LongName
LongName	EQU	ByteAddr
ByteAddr	SET	ByteAddr+4
		ENDM


;====================================================================
;               16 bit macros (Big-Endian)
;
mov16	MACRO	src,dst
	movf	src,w
	movwf	dst
	movf	src+1,w
	movwf	dst+1
	ENDM

movi16	MACRO	lit,dst
	movlw	HIGH(lit)
	movwf	dst
	movlw	LOW(lit)
	movwf	dst+1
	ENDM

tst16	MACRO	src
	tstf	src+1
	skpz
	goto	$+1
	tstf	src
	ENDM

cmpi16	MACRO	src,lit
	movlw	(lit>>8)&0xff
	subwf	src,w
	skpz
	goto	$+3
	movlw	lit&0xff
	subwf	src+1,w
	ENDM

clr16	MACRO	dst
	clrf	dst
	clrf	dst+1
	ENDM

inc16	MACRO	dst
	incf	dst+1
	skpnz
	incf	dst
	ENDM

dec16	MACRO	dst
	decf	dst+1
	skpnz
	decf	dst
	ENDM

add16	MACRO	src,dst
	movf	src+1,w
	addwf	dst+1
	skpnc
	incf	dst
	movf	src,w
	addwf	dst
	ENDM

addi16	MACRO	lit,dst
	movf	LOW(lit),w
	addwf	dst+1
	skpnc
	incf	dst
	movf	HIGH(lit),w
	addwf	dst
	ENDM

sub16	MACRO   src,dst
	movf    src+1,w
	subwf   dst+1
	movf    src,w
	skpc
	incf    src,w
	subwf   dst
	ENDM

subi16	MACRO   lit,dst
	movlw   LOW(lit)
	subwf   dst+1
	movlw   HIGH(lit)
	skpc
	movlw   (HIGH(lit))+1
	subwf   dst
	ENDM

rr16	MACRO	dst
	rrf	dst
	rrf	dst+1
	ENDM

rl16	MACRO	dst
	rlf	dst+1
	rlf	dst
	ENDM

com16	MACRO	dst
	comf	dst+1
	comf	dst
	ENDM


;---------------------------------------------
;    16->32 bit macros	(Big-Endian)
;

; move 16 bit to 32 bit

mov1632	MACRO	src,dst
	clrf	dst
	clrf	dst+1
	movf	src,w
	movwf	dst+2
	movf	src+1,w
	movwf	dst+3
	ENDM

; add 16 bit to 32 bit

add1632	MACRO	src,dst ; src(15:0), dst(31:0)
	movf	src+1,w
	addwf	dst+3	; dst = dst + src(7:0)
	skpc
	goto	$+6
	incf	dst+2
	skpnz
	incf	dst+1
	skpnz
	incf	dst
	movf	src,w
	addwf	dst+2	; dst = dst + src (15:8)
	skpc
	goto	$+4
	incf	dst+1
	skpnz
	incf	dst
	ENDM

;---------------------------------------------------
;      32 bit macros (Big-Endian)

clr32	MACRO	dst
	clrf	dst
	clrf	dst+1
	clrf	dst+2
	clrf	dst+3
	ENDM

mov32	MACRO	src,dst
	movf	src,w
	movwf	dst
	movf	src+1,w
	movwf	dst+1
	movf	src+2,w
	movwf	dst+2
	movf	src+3,w
	movwf	dst+3
	ENDM


movi32	MACRO	lit,dst
	movlw	lit>>24
	movwf	dst
	movlw	(lit>>16)&0xff
	movwf	dst+1
	movlw	(lit>>8)&0xff
	movwf	dst+2
	movlw	lit&0xff
	movwf	dst+3
	ENDM

; 32 bit left shift

rr32	MACRO	dst
	rrf	dst
	rrf	dst+1
	rrf	dst+2
	rrf	dst+3
	ENDM

; 32 bit right shift

rl32	MACRO	dst
	rlf	dst+3
	rlf	dst+2
	rlf	dst+1
	rlf	dst
	ENDM

; 32 bit 1's complememt

com32	MACRO	dst
	comf	dst+3
	comf	dst+2
	comf	dst+1
	comf	dst
	ENDM

; test 32 bit for zero

tst32	MACRO	src
	tstf	src+3
	skpz
	goto	$+8
	tstf	src+2
	skpz
	goto	$+5
	tstf	src+1
	skpz
	goto	$+1
	tstf	src
	ENDM

; add 32 bit to 32 bit

add32	MACRO	src,dst
	movf	src+3,w
	addwf	dst+3
	skpc
	goto	$+6
	incf	dst+2
	skpnz
	incf	dst+1
	skpnz
	incf	dst
	movf	src+2,w
	addwf	dst+2
	skpc
	goto	$+4
	incf	dst+1
	skpnz
	incf	dst
	movf	src+1,w
	addwf	dst+1
	skpnc
	incf	dst
	movf	src,w
	addwf	dst
	ENDM

; compare 32 bit to literal

cmpi32	MACRO	src,lit
	movlw	(lit>>24)&0xff
	subwf	src,w
	skpz
	goto	$+11
	movlw	(lit>>16)&0xff
	subwf	src+1,w
	skpz
	goto	$+7
	movlw	(lit>>8)&0xff
	subwf	src+2,w
	skpz
	goto	$+3
	movlw	lit&0xff
	subwf	src+3,w
	ENDM

;====================================================================
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top