Continue to Site

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.

  • 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.

serial-pic problem

Status
Not open for further replies.

wejos

Member
same old same old problem guys about my 16f84 serial-pic project.

although ive made some progress since the last. leds are turning on now.

but theres a small hitch. leds do not appear on after pressing key in the keyboard, only when i removed the serial cable from the pc (the circuit is still powered) then thats the time the leds would light up.

what seem to be causing this? is this because i was using a 10pf caps instead of 33pf for TX? Or am i using the wrong baud rate? it says 4800 in the tutorial so this is what i'm using.

thanks for your help

link for the source tutorial (thanks to Atom for fixing the html [in zip])

its source code:

Code:
; FILE: rcv1_1.asm
; AUTH: P.Oh
; DATE: 04/27/02 18:00 1.0 - WORKS
;	04/27/02 18:35 1.1
; DESC: 1.0: PC-to-PIC serial communications.  LEDs display binary equivalent
;            of key typed on PC
;       1.1: Same as 1.0 but eliminates need for switch
; REFS: rcv4800.asm in PIC'n Techniques p. 219

;--------------------------------------------------------------------------
	list	p=16f84
	radix	hex
;--------------------------------------------------------------------------
; 	CPU EQUATES

tmr0	equ	0x01	; Timer/counter register
status	equ	0x03	; Status word register. See Easy PIC'n p. 145
portA	equ	0x05	; Port A register
portB	equ	0x06	; Port B register
intCon	equ	0x0b	; Interrupt control register
rcvReg	equ	0x0c	; General purpose register
count	equ	0x0d	; General purpose register
temp	equ	0x0e	; General purpose register
optReg	equ	0x81	; File register in Bank 1
trisA	equ	0x85	; File register in Bank 1. See Easy PIC'n p. 145
trisB	equ	0x86	; File register in Bank 1. See Easy PIC'n p. 145
;--------------------------------------------------------------------------
; 	BIT EQUATES
rp0	equ	5
;--------------------------------------------------------------------------
	org	0x000

start	bsf 	status, rp0	; Switch to Bank 1. See Easy PIC'n p. 145
	movlw	b'00000101'	; A0, A2 are input and the rest are output
	movwf	trisA
	movlw	b'00000000'	; Port B: all output
	movwf	trisB
	bcf	status, rp0	; Switch back to Bank 0
	clrf	portB
	clrf	rcvReg
; switch	btfsc	portA, 2	; Is A2 equal 0? i.e. is switch closed?
; 	goto	switch		; No, so keep checking
doThis	call	rcv4800		; Yes, to serial in subroutine
	movf	rcvReg,  w	; Get byte received
	movwf	portB		; Display byte on the 8 LEDs
circle	goto	doThis		; Done
;--------------------------------------------------------------------------
rcv4800	bcf	intCon, 5	; Disable tmr0 interrupts
	bcf	intCon,	7	; Disable global interrupts
	clrf	tmr0		; Clear timer/counter
	clrwdt			; Clear wdt prep prescaler assign
	bsf	status, rp0	; to page 1	
	movlw	b'11011000'	; set up timer/counter
	movwf	optReg
	bcf	status, rp0	; Back to page 1
	movlw	0x08		; Init shift counter
	movwf	count
sbit	btfsc	portA, 0	; Look for start bit
	goto 	sbit		; For Mark
	movlw	0x98		; 
	movwf	tmr0		; Load and start timer/counter
	bcf	intCon, 2	; Clear tmr0 overflow flag
time1	btfss	intCon, 2	; Has the timer (bit 2) overflowed?  Skip next line if 1
	goto	time1		; No
	btfsc	portA, 0	; Start bit still low?
	goto 	sbit		; False start, go back
	movlw	0x30		; real, define N for timer
	movwf	tmr0		; start timer/counter - bit time
	bcf	intCon, 2	; Clear tmr0 overflow flag
time2	btfss	intCon, 2	; Timer overflow?
	goto	time2		; No
	movlw	0x30		; Yes, define N for timer
	movwf	tmr0		; Start timer/counter
	bcf	intCon, 2;	; Clear tmr0 overflow flah
	movf	portA, w	; Read port A
	movwf	temp		; Store
	rrf	temp, f		; Rotate bit 0 into carry flag
	rrf	rcvReg, f	; Rotate carry into rcvReg bit 7
	decfsz	count, f	; Shifted 8?
	goto	time2		; No
time3	btfss	intCon, 2	; Timer overflow?
	goto	time3		; No
	return			; Yes, byte received
;-----------------------------------------------------------------------
	end
;-----------------------------------------------------------------------
; At blast time, select:
; 	memory unprotected
; 	watchdog timer disabled
;	standard crystal (4 MHz)
; 	power-up timer on
;=======================================================================
 
thanks Nigel. im headed to your tut tomorrow. first thing i do when i wake up.

be80be have helped me to the necessary changes on the part of the code needed to work with 16f84 since the pic used in your tut was of higher one. I am set to try them tomorrow.

be80be's suggestion:

https://www.electro-tech-online.com/threads/more-questions-about-asm-code.92726/


so this is a code issue not hardware issue?

you think if i make RA0 become output for a few sec before changed again to input to receive from serial port would solve this? just a wild guess.
 
Here is a nice piece of code i made but using a PIC16F627A. Which has hardware USART. With the below code you can send data to Terminal Window and send from terminal window to PIC and turn on/off a led by pressing a 1 or 0 on your keyboard.

I commented this code ALOT so enjoy.
Code:
	list      p=16f627A           ; list directive to define processor
	#include <p16F627A.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_OFF & _INTOSC_OSC_NOCLKOUT 



;***** VARIABLE DEFINITIONS
d1		EQU		0x70		;delay variable #1
d2		EQU		0x71		;delay variable #1

count	EQU		0x74		;Our Tx Count Variable
rxTmp	EQU		0x75		;Our Rx Variable


	ORG     0x000				; processor reset vector
	call	MyBank1				;PCON is in bank 0
	BSF 	PCON, OSCF

	call	MyBank0				;CMCON is in bank 0
	MOVLW 	0x07 
	MOVWF 	CMCON 				;Comparators Off
		  
	call	MyBank1				;TRISB and TXSTA is in bank 1
	movlw	b'00000110'
	movwf	TRISB				;Make TRISB, 1 and 2 a INPUT pin (Tx - RB2)(Rx - RB1) It will change when in use.

	movlw   b'00000100'         ;BRGH = 1 (High Speed) and SYNC = 0 (Asynchronous Mode)
	movwf   TXSTA                 

	call	MyBank0				;RCSTA is in bank 0
	movlw   b'00010000'			;Enables continuous receive
    movwf   RCSTA				

	call	MyBank1				;SPBRG is in bank 1

	movlw	d'25'
	movwf	SPBRG				;25 and BRGH =1 would make 9600bps

	call	MyBank0				;RCSTA is in bank 0
	bsf		RCSTA, SPEN			;Serial Port Enable bit

	call	MyBank1				;TXSTA is in bank 1
	bsf		TXSTA, TXEN			;Transmit Enable bit

	call	MyBank0				;PORTB is in bank 0 as well as many others. Main Bank
	bcf		PORTB, 4			;Turn off our LED


Main:
	call	Delay			;Start with a small delay to make sure all is ready.
	call	Message1		;Send our Message1 "Press 1=On 0=Off"
	call	RecvRx			;Wait for user input...
	movwf	rxTmp			;Move the input to the rxTmp variable
	movlw	0x30			;move 0x30 which will be used to subtract from inpuut since 
							;the 1 key is a 0x31. if you minus 0x30 you end up with a 1 as the bit.
							;now 0x30 = 0 key minus 0x30 = 0 in the first bit.
	subwf	rxTmp,1			;subtract it from rxTmp and store it in rxTmp

	btfss	rxTmp,0			;Test bit 0 of rxTmp and
	goto	Off				;if its a 0 goto off else skip this line
On:							;if its a 1 do the below
	call 	SendOn			;Send out message "On"
	bsf		PORTB, 4		;Set the LED pin which is PORTB pin 4 to high aka on
	goto	Main			;goto main lol

Off:						;if it was a 0 then you should be here
	call 	SendOff			;Send our message "Off"
	bcf		PORTB, 4		;Clear PortB pin 4 aka off
	goto	Main			;goto main lol

RecvRx:
	btfss   PIR1, RCIF		;Check if data has been recieved
	goto    $-1				;If not then go back 1 instruction
	movf    RCREG,	W		;If so move the data to the W register
	return					;return from where i was called

SendTx:
	btfss	PIR1, TXIF		;Check if we are busy sending something already
	goto	$-1				;If so then go back 1 instruction
	movwf	TXREG			;If ready move W reg into TXREG to send data.	
	return					;Return to where i was called

Message1:
	clrf	count
Message1A:
	movf	count, w		;put counter value in W
	call	Msg01			;get a character from the text table with count in w
	xorlw	0x00			;XOR the data in W with 0x00
	btfsc	STATUS, Z		;is it a zero?
	return					;if so return becuase we are done
	call	SendTx			;if not then call sendTx with the data in W
	incf	count, f		;add 1 to count 
	goto	Message1A		;next character (repeat)

SendOn:
	clrf	count
MessageOn:
	movf	count, w		;put counter value in W
	call	MsgOn			;get a character from the text table
	xorlw	0x00			;XOR the data in W with 0x00
	btfsc	STATUS, Z		;is it a zero?
	return					;if so return becuase we are done
	call	SendTx			;if not then call sendTx with the data in W
	incf	count, f		;add 1 to count 
	goto	MessageOn

SendOff:
	clrf	count
MessageOff:
	movf	count, w		;put counter value in W
	call	MsgOff			;get a character from the text table
	xorlw	0x00			;XOR the data in W with 0x00
	btfsc	STATUS, Z		;is it a zero?
	return					;if so return becuase we are done
	call	SendTx			;if not then call sendTx with the data in W
	incf	count, f		;add 1 to count 
	goto	MessageOff

MsgOn:
	addwf	PCL, f			;add the data in W to the Program Counter (PCL) and return with new data
	retlw	'O'
	retlw	'n'
	retlw	' '
	retlw	0x0A			;send LF
	retlw	0x0D			;send CR
	retlw	0x00			;Send our 0x00 which is the end

MsgOff:
	addwf	PCL, f			;add the data in W to the Program Counter (PCL) and return with new data
	retlw	'O'
	retlw	'f'
	retlw	'f'
	retlw	0x0A			;send LF
	retlw	0x0D			;send CR
	retlw	0x00			;Send our 0x00 which is the end

Msg01:
	addwf	PCL, f			;add the data in W to the Program Counter (PCL) and return with new data
	retlw	'P'
	retlw	'r'
	retlw	'e'
	retlw	's'
	retlw	's'
	retlw	' '
	retlw	'1'
	retlw	'='
	retlw	'O'
	retlw	'N'
	retlw	' '
	retlw	'0'
	retlw	'='
	retlw	'O'
	retlw	'F'
	retlw	'F'
	retlw	0x0A			;send LF
	retlw	0x0D			;send CR
	retlw	0x00			;Send our 0x00 which is the end

MyBank0:					;Datasheet states to goto bank 0 you would:
	bcf		STATUS,RP0		;Clear RP0
	bcf		STATUS,RP1		;Clear RP1
	return					;return back to where i was called

MyBank1:					;Datasheet states to goto bank 1 you would:
	bsf		STATUS,RP0		;Set RP0
	bcf		STATUS,RP1		;Clear RP1
	return					;return back to where i was called

MyBank2:					;Datasheet states to goto bank 2 you would:
	bcf		STATUS,RP0		;Clear RP0
	bsf		STATUS,RP1		;Set RP1
	return					;return back to where i was called

MyBank3:					;Datasheet states to goto bank 3 you would:
	bsf		STATUS,RP0		;Set RP0
	bsf		STATUS,RP1		;Set RP1
	return					;return back to where i was called

Delay						;1mS Delay
	movlw	0xC6
	movwf	d1
	movlw	0x01
	movwf	d2
Delay_0
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	Delay_0
	goto	$+1
	nop
	return
	END
 

Attachments

  • uart01.asm
    5.6 KB · Views: 140
Last edited:
AtomSoft (Jason),

Nice example. Have you ever considered using a simple PutStr subsystem for placing strings in-line with your code?

Regards, Mike

Code:
main
        DelayCy(1*msecs)        ;
        PutStr  "\x1b[2J"       ; home cursor, clear screen
        PutStr  "Press 1=On 0=Off\n\r"
loop
        call    Get232          ; get char
        xorlw   '0'             ; is it '0', Off?
        bz      led_off         ; yes, branch, else
        xorlw   '1'^'0'         ; is it '1', On?
        bnz     main            ; no, branch, else, fall thru'
led_on
        PutStr  "On \n\r"       ;
        bsf     PORTB,4         ; turn on Led on RB4
        goto    loop            ;
led_off
        PutStr  "Off\n\r"       ;
        bcf     PORTB,4         ; turn off Led on RB4
        goto    loop            ;
 
yeah as Nigel stated his tutorials are awesome. I did learn software USART from there but why not just avoid it and buy a $2 PIC with built in hardware like from :

Microchip PIC 8-bit Microcontroller PIC16F627A-I/P - dipmicro electronics
**broken link removed**

Mike, K8LH:

i would love if you could show me a example of PutStr so i could use it. I never learned much asm as i did move to C but im slowly shifting back to ASM now lol as some projects need very precise control.
 
heh even took a few minutes to make a simple visual basic 6 program to control it:
uart-jpg.29226

Full source included!
 

Attachments

  • uart.jpg
    uart.jpg
    10 KB · Views: 463
  • uart.zip
    5.7 KB · Views: 110
New code!:

Code:
	list      p=16f627A           ; list directive to define processor
	#include <p16F627A.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_OFF & _INTOSC_OSC_NOCLKOUT 



;***** VARIABLE DEFINITIONS
d1		EQU		0x70		;delay variable #1
d2		EQU		0x71		;delay variable #1
PTRL	EQU		0x72
PTRH	EQU		0x73
count	EQU		0x74		;Our Tx Count Variable
rxTmp	EQU		0x75		;Our Rx Variable

;THANKS MIKE!
;******************************************************************
;
;  _Print macro - print a string to the RS-232 port
;
_Print  macro   str             ;
        local   String, Print
        movlw   low String      ;
        movwf   PTRL            ;
        movlw   high String     ;
        movwf   PTRH            ;
        goto    Print           ;

String  dt      str,0
Print   call    PutString       ; print string
        endm

	ORG     0x000				; processor reset vector
	call	MyBank1				;PCON is in bank 0
	BSF 	PCON, OSCF

	call	MyBank0				;CMCON is in bank 0
	MOVLW 	0x07 
	MOVWF 	CMCON 				;Comparators Off
		  
	call	MyBank1				;TRISB and TXSTA is in bank 1
	movlw	b'00000110'
	movwf	TRISB				;Make TRISB, 1 and 2 a INPUT pin (Tx - RB2)(Rx - RB1) It will change when in use.

	movlw   b'00000100'         ;BRGH = 1 (High Speed) and SYNC = 0 (Asynchronous Mode)
	movwf   TXSTA                 

	call	MyBank0				;RCSTA is in bank 0
	movlw   b'00010000'			;Enables continuous receive
    movwf   RCSTA				

	call	MyBank1				;SPBRG is in bank 1

	movlw	d'25'
	movwf	SPBRG				;25 and BRGH =1 would make 9600bps

	call	MyBank0				;RCSTA is in bank 0
	bsf		RCSTA, SPEN			;Serial Port Enable bit

	call	MyBank1				;TXSTA is in bank 1
	bsf		TXSTA, TXEN			;Transmit Enable bit

	call	MyBank0				;PORTB is in bank 0 as well as many others. Main Bank
	bcf		PORTB, 4			;Turn off our LED


Main:
	call	Delay			;Start with a small delay to make sure all is ready.
	;call	Message1		;Send our Message1 "Press 1=On 0=Off"
	_Print  "Enter: 0 for OFF, 1 for ON\r\n"
	call	RecvRx			;Wait for user input...
	movwf	rxTmp			;Move the input to the rxTmp variable
	movlw	0x30			;move 0x30 which will be used to subtract from inpuut since 
							;the 1 key is a 0x31. if you minus 0x30 you end up with a 1 as the bit.
							;now 0x30 = 0 key minus 0x30 = 0 in the first bit.
	subwf	rxTmp,1			;subtract it from rxTmp and store it in rxTmp

	btfss	rxTmp,0			;Test bit 0 of rxTmp and
	goto	Off				;if its a 0 goto off else skip this line
On:							;if its a 1 do the below
	_Print  "LED is on.\r\n"	;Thanks MIKE
	bsf		PORTB, 4		;Set the LED pin which is PORTB pin 4 to high aka on
	goto	Main			;goto main lol

Off:						;if it was a 0 then you should be here
	_Print  "LED is off.\r\n"	;Thanks MIKE
	bcf		PORTB, 4		;Clear PortB pin 4 aka off
	goto	Main			;goto main lol

RecvRx:
	btfss   PIR1, RCIF		;Check if data has been recieved
	goto    $-1				;If not then go back 1 instruction
	movf    RCREG,	W		;If so move the data to the W register
	return					;return from where i was called

SendTx:
	btfss	PIR1, TXIF		;Check if we are busy sending something already
	goto	$-1				;If so then go back 1 instruction
	movwf	TXREG			;If ready move W reg into TXREG to send data.	
	return					;Return to where i was called

MyBank0:					;Datasheet states to goto bank 0 you would:
	bcf		STATUS,RP0		;Clear RP0
	bcf		STATUS,RP1		;Clear RP1
	return					;return back to where i was called

MyBank1:					;Datasheet states to goto bank 1 you would:
	bsf		STATUS,RP0		;Set RP0
	bcf		STATUS,RP1		;Clear RP1
	return					;return back to where i was called

MyBank2:					;Datasheet states to goto bank 2 you would:
	bcf		STATUS,RP0		;Clear RP0
	bsf		STATUS,RP1		;Set RP1
	return					;return back to where i was called

MyBank3:					;Datasheet states to goto bank 3 you would:
	bsf		STATUS,RP0		;Set RP0
	bsf		STATUS,RP1		;Set RP1
	return					;return back to where i was called

Delay						;1mS Delay
	movlw	0xC6
	movwf	d1
	movlw	0x01
	movwf	d2
Delay_0
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	Delay_0
	goto	$+1
	nop
	return

;THANKS MIKE!
;******************************************************************
;
;  PutString Subroutine
;
;         - setup PTRL and PTRH to string address before entry
;         - string must be terminated with a 00 byte
;
PutString
        call    GetTable        ; get a table character            |B0
        andlw   b'11111111'     ;                                  |B0
        btfsc   STATUS,Z        ; a 00 byte, last character?       |B0
        return                  ; yes, return, else                |B0
        call    SendTx          ; output character                 |B0
        incfsz  PTRL,F          ; increment pointer                |B0
        goto    PutString       ;                                  |B0
        incf    PTRH,F          ;                                  |B0
        goto    PutString       ;                                  |B0
;
GetTable
        movf    PTRH,W          ;                                  |B0
        movwf   PCLATH          ;                                  |B0
        movf    PTRL,W          ;                                  |B0
        movwf   PCL             ;                                  |B0

;******************************************************************
	END

EDIT: ADDED A CLEAR SCREEN FUNCTION:
Code:
ClearScn:
	movlw 	d'27'
	call	SendTx
	movlw 	'['
	call	SendTx;
	movlw 	'2'
	call	SendTx
	movlw 	'J'
	call	SendTx
	call 	Delay
	return

and added the call to it here:
Code:
RecvRx:
	btfss   PIR1, RCIF		;Check if data has been recieved
	goto    $-1				;If not then go back 1 instruction[b]
	call	ClearScn[/b]
	movf    RCREG,	W		;If so move the data to the W register
	return
 

Attachments

  • uart01.asm
    5.4 KB · Views: 143
Last edited:
Jason,

Looks nice. The clear screen function can be printed as a string too (I showed this in my previous example).

Take care. Mike

Code:
        _Print  "\x1B[2J"       ; home cursor, clear screen
 
*blush* i feel so dumb. Have you ever heard me say i dont remember things easy lol i probably read it all and completely forgot it lol
 
Last edited:
jason do you know any site that convert hex to binary (8 bit). im having trouble on my convertion.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top