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.

**UPDATE/CHANGED**[USART]**Reading analogue value of A/D convertor with PIC 16F877A!

Status
Not open for further replies.

vili.chaudhary

New Member
Hi Mike,

I have finally managed to finish my phase part as well :) .

I was hoping to get some suggestions on my last section. Basically after getting 3 bytes of data [two mag and one phase], I now have to transfer the data to the PC via USB.

My supervisor has already provided me with a USB-PC interfacing board [this -:
https://www.ftdichip.com/Documents/DataSheets/Modules/DS_UM232R.pdf

I have attached a schematic of the USB circuit as well.

He told me that it's very easy to use. It takes the serial input from the PIC [USART] and transfers the data to PC.

So my task is to transfer the two dummy values [any binary/hex values] to the PC using a USART and check the values on PC using "Hyperterminal software".


I have read some information on USART and attempted a simple code. I would really really appreciate it if you could advice me on the code or any changes I need in the code.

Many thanks.
Vili

Code:
;16f877a	USART	test routine
;
;TEST CIRCUIT:


;**********************************************************

   __config _LVP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF & _DEBUG_OFF
        
	list p=16f877a

       include "p16f877a.inc"
		errorlevel -302

  ;******* Start at the reset vector
        org     0x000
        goto    Start
   	
Start	
	org	0x010
	clrf	PORTC
	
        bsf     STATUS,RP0      ;bank 1
        bcf     STATUS,RP1
;****************************************************
        movlw   b'00000011'
        movwf   TRISC             ;portc [5-0] outputs** <6,7> set for RX/TX
 	      
;**********************************************
	movlw	d'25'             ; Set Baud rate
	movwf	SPBRG
	movlw	b'00100100'     ; 8-bit transmit, transmitter enabled,
	movwf	TXSTA 		; asynchronous mode, HIGH speed mode
	

	bcf	STATUS,RP0	 ; Go to Bank 0
	bsf	RCSTA,SPEN	 ;**** Serial ENABLED
	bsf	PIR1,TXIF	;**Set interrupt
    
;**********************************************
Main
	movlw	0x0f
	movwf	TXREG

;********************************************
Wait
        btfsc	PIR1,TXIF
	goto	Wait       ;/**********TXIF will get clear by loading TXREG
	goto	Buffer

;/*********Ready to load another 8-bit value??*****
Buffer
	btfss	TXSTA,TRMT
	goto	Buffer
	goto	Nextvalue

;/********Next value to be transmit*****

Nextvalue
 	movlw	0xff
	movwf	TXREG

Wait1
        btfsc	PIR1,TXIF
	goto	Wait1       ;/******TXIF will get clear by loading TXREG
	goto	Buffer1

;/**************
Buffer1
	btfss	TXSTA,TRMT
	goto	Buffer1
	goto	Main



	END
 

Attachments

  • USBdiagram.pdf
    28.7 KB · Views: 211
You got the hard bit right, setting up the UART. The bit you have wrong if the TXIF bit. When you write a byte to TXREG then TXIF gets cleared and stays clear until the byte has been sent. There is no need to check the TRMT bit. There is also no need to goto the next line, this is where it will go anyway.

Try this,
Code:
Main
	movlw	0x0f
	movwf	TXREG
;********************************************
Wait
        btfs[COLOR="blue"]s[/COLOR]	PIR1,TXIF
	goto	Wait       ;/**********TXIF will get clear by loading TXREG

;/********Next value to be transmit*****

Nextvalue
 	movlw	0xff
	movwf	TXREG
Wait1
        btfs[COLOR="Blue"]s[/COLOR]	PIR1,TXIF
	goto	Wait1       ;/******TXIF will get clear by loading TXREG

	goto	Main

It would be a good idea to change it to send something like A & B so that you can run hyperterminal to see if it's working.

Mike.
 
Dear Mike,

I am always grateful for your valuable replies. It's you who is making it easier to learn. Thank you once again. :)

Mike- I would really like to check whether the USB is working or not by sending characters to Hyperterminal. I have no idea how to send/write characters in asm code??

Please provide any help on this.

Many many thanks Mike.

vili

Ps: Mike- did you have a look at my FTDI chip [USB]? I found the two pins: RTS and CTS confusing so I haven't connected both the pins to PIC and instead connected them with each other [on FTDI chip]. Will it still work?:confused:
 
As the pics dont have the RTS and CTS pins then I'm not sure how you would connect them. Just connect RX, TX and GND and set hyperterminal to handshaking = none and it should work fine.

To send ascii just change your moves to movlw "A" and it will send A.

Mike.
 
Mikeeeeeeeeeeeeee :D

I did it !!! Yayyyy. I am over the moon now. Thanks a trillion for all your valuable help!

I added few 'nop' instructions and it worked! :D

Last thing I forgot to ask was about the receiving data byte. I need to receive one byte of information as well. :( I found a RX code from the microchip website and made a few changes for my PIC.

I haven't got any clue on how to mix my TX code with this RX code. Could you please look at the code and suggest if it looks correct? And how to write both the codes [TX code from the first post and this RX code below] in one asm file.

I will be really grateful if you could have a look at it and advice me on how to use TX and RX both in the same code ,as I am very much struggling and have no idea about how to use the interrupts!

Many many thanks again!
Vili

Code:
;*******************RX


; Set terminal program to 9600 baud, 1 stop bit, no parity

	list p=16f877a	; set processor type

	list n=0		; supress page breaks in list file

	include <P16f877a.INC>
;************************************************************
; Reset and Interrupt Vectors

	org	00000h	; Reset Vector
	goto	Start

	org	00008h	; Interrupt vector
	goto	IntVector
;************************************************************

; Program begins here

	org	00020h	; Beginning of program EPROM

Start
	   bsf     STATUS,RP0      ;bank 1
   	   bcf     STATUS,RP1
;****************************************************
    movlw   b'00000011'
    movwf   TRISC             ;portc [5-0] outputs** <6,7> set for RX/TX

    movlw   b'00000000'
    movwf   PORTB             ; LEDs for RX      
;**********************************************
	movlw	b'00011001'           ; Set Baud rate
	movwf	SPBRG

	movlw	b'00100100'     ; 8-bit transmit, transmitter enabled,
	movwf	TXSTA 		; asynchronous mode, HIGH speed mode
;*****************************************	

	bcf	STATUS,RP0	 ; Go to Bank 0
	movlw   b'10010000'
	movwf   RCSTA	; 8 bit receive, receiver enabled, serial port enabled

		;**Set interrupt
	
       banksel PIR1
	bcf	PIR1,RCIF	; Clear RCIF Interrupt Flag
	
        banksel PIE1
	bsf	PIE1,RCIE	; Set RCIE Interrupt Enable
	
        banksel INTCON
	bsf	INTCON,PEIE	; Enable peripheral interrupts
	bsf	INTCON,GIE	; Enable global interrupts
;************************************************************

; Main loop

Main
	goto	Main	; loop to self doing nothing
;************************************************************

; Interrupt Service Routine

IntVector

	; save context (WREG and STATUS registers) if needed.

	btfss	PIR1,RCIF	; Did USART cause interrupt?
	goto	OtherInt	; No, some other interrupt

	btfss	STATUS,Z	; Was either error status bit set?
	goto	RcvError	; Found error, flag it

	movf	RCREG,W		; Get input data
	movwf	PORTB		; Display on LEDs

	goto	ISREnd		; go to end of ISR, restore context, return

RcvError

	bcf	RCSTA,CREN	; Clear receiver status
	bsf	RCSTA,CREN
	movlw	0FFh		; Light all LEDs
	movwf	PORTB	

	goto	ISREnd	; go to end of ISR, restore context, return

OtherInt

	goto	$   ; Find cause of interrupt and service it before returning from
			; interrupt. If not, the same interrupt will re-occur as soon
			; as execution returns to interrupted program.

ISREnd

	; Restore context if needed.

	retfie

	end
 
The code you posted is for an 18 series chip and also uses interrupts. You don't want the complication of interrupts just yet. The best way to make a pic appear to do lots of things at once is to do them one after another. At this point it would also be a good idea to put some of your code into subroutines. Here is some example code that has two subroutines. One is SendW which send the character that is in W and the second is SendDecimal which converts the value in W into its ascii equivalent and sends it. Note the structure, you call the subroutine and the subroutine returns at the end of it. It's probably better to google subroutine.

To receive a byte from the PC is also fairly easy. You just check if RCIF is set and if it is then read RCREG and you have the byte.
Code:
;This will display "V=123" and move to a new line whenever a key is pressed in hyperterminal.

Main	;do other stuff
	;like getting phase and peak voltage
	;when done, goto continue

Continue	btfss	PIR1,RCIF
		goto	Main
		movfw	RCREG
		movwf	ReceivedByte

		movlw	"V"
		call	SendW
		movlw	"="
		call	SendW
		movlw	d'123'
		call	SendDecimal
		movlw	0x0d
		call	SendW
		movlw	0x0a
		call	SendW
		goto	Main

SendDecimal	clrf	Decimal100
Count100s	incf	Decimal100,F
		addlw	100h-.100;	-100
		btfsc	STATUS,C
		goto	Count100s
		addlw	.100
		clrf	Decimal10
Count10s	incf	Decimal10,F
		addlw	0f6h;		-10
		btfsc	STATUS,C
		goto	Count10s
		movwf	Units
		movfw	Decimal100
		addlw	2fh
		call	SendW
		movfw	Decimal10
		addlw	2fh
		call	SendW
		movfw	Units
		addlw	30h+0ah
		call	SendW
		return

SendW		movwf	TXREG
Wait		btfss	PIR1,TXIF
		goto	Wait
		return

You will of course have to add the variables used to your cblock area.

Mike.
 
Hi Mike, :)

Thank you again for providing me the code which gave me amazing idea about how the USART work.

Mike- After understanding your code, I wrote some code [Help from microchip source code] but it doesn't seem to work at all :(.

What I am trying to do is:

-Wait in the main loop to receive the data [from TERMINAL]

- If data is received, then display the data on PORTB LEDs

-If nothing received, then loop for ever until receive.

Then, Once the data is displayed on LEDs,

-Send value 0x31 back to display on terminal.

I am not getting anything on LEDs as well as on the TERMINAL :(

I will be really grateful if you could have a look at the code and advice me on it.

Many many thanks.

Vili

Code:
	list p=16f877a		;list directive to define processor
	#include <p16f877a.inc>	;processor specific definitions
	errorlevel -302		;suppress "not in bank 0" message

		__config _LVP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF & _DEBUG_OFF

;----------------------------------------------------------------------------
;Variables

		CBLOCK	0x20
		Flags			;byte to store indicator flags
		ENDC

;----------------------------------------------------------------------------
;Macros to select the register bank
;Many bank changes can be optimized when only one STATUS bit changes

Bank0		MACRO			;macro to select data RAM bank 0
		bcf	STATUS,RP0
		bcf	STATUS,RP1
		ENDM

Bank1		MACRO			;macro to select data RAM bank 1
		bsf	STATUS,RP0
		bcf	STATUS,RP1
		ENDM

Bank2		MACRO			;macro to select data RAM bank 2
		bcf	STATUS,RP0
		bsf	STATUS,RP1
		ENDM

Bank3		MACRO			;macro to select data RAM bank 3
		bsf	STATUS,RP0
		bsf	STATUS,RP1
		ENDM

;----------------------------------------------------------------------------
;This code executes when a reset occurs.

		ORG     0x0000		;place code at reset vector

ResetCode:
		clrf    PCLATH	;select program memory page 0
  		goto    Main		;go to beginning of program

;---------------------------------------------------------------------------

;----------------------------------------------------------------------------
;Main routine calls the receive polling routine and checks for a byte
;received. It then calls a routine to transmit the data back.

Main:	ORG		0X010	
	call	SetupSerial	;set up serial port and buffers

;//************-------------------------**************do other initialization here

MainLoop:	
		call	ReceiveSerial     ;go get received data if available
		btfss	Flags,0		 ;check if data received
		goto	MainLoop
		call	TransmitSerial     ;if so then go transmit the data
		bcf	Flags,0	
								
		goto	MainLoop	           ;go do main loop again

;----------------------------------------------------------------------------
;Check if data received and if so, return it in the working register.

ReceiveSerial:	Bank0				;select bank 0
		btfss	PIR1,RCIF		;check if data
		goto	MainLoop
		movfw	RCREG		;get received data
;//
		movwf	PORTB
		
		bsf	Flags,0		
		return

;----------------------------------------------------------------------------
;Transmit data in WREG when the transmit register is empty.

TransmitSerial:	Bank0			;select bank 0
		movlw	0x31      ; no 1
		movwf	TXREG		;and transmit the data

Loop	btfss	PIR1,TXIF		;check if transmitter busy
		goto	Loop	         ;wait until transmitter is not busy	
		return

;----------------------------------------------------------------------------
;Set up serial port.

SetupSerial:	Bank1				;select bank 1
	movlw	b'00000011'	;set tris bits for TX and RX
	movwf	TRISC
	movlw	b'00000000'
	movwf	TRISB
	movlw    b'00011001'	;set baud rate
	movwf	SPBRG
	movlw	b'00100100'          ;enable transmission and high baud rate
	movwf	TXSTA

	Bank0				;select bank 0

	movlw	B'10010000'	;enable serial port and reception
		movwf	RCSTA
		bsf		PIR1,TXIF	;**Set interrupt
		bcf		PIR1,RCIF
	;	bsf		PIE1,RCIE
		clrf	Flags		;clear all flags
		clrf	PORTB
		clrf	PORTC
		return

;----------------------------------------------------------------------------

		END
 
Last edited:
Hi Mike,

I think the problem lies within the "receive" part of my code [ReceiveSerial].

I tried editing the RX section and just used the TX section of the code. It works absolutely fine but as soon as I add the RX section, it doesn't work at all. I am trying and pressing all the numbers and characters in TERMINAL but nothing comes up on the LEDs.

:(
 
Vili,
I think your problem is in the setting up of Port C. The RX and TX bits have to be set to input for the serial port to work.
Code:
SetupSerial:	Bank1				;select bank 1
	movlw	b'[COLOR="Blue"]11[/COLOR]000011'	;set tris bits for TX and RX
	movwf	TRISC

Also, although it shouldn't stop it working it is very bad practice to jump out of a subroutine. This is a better way,
Code:
ReceiveSerial:	Bank0			;select bank 0
		btfss	PIR1,RCIF	;check if data
		[COLOR="Blue"]return[/COLOR]			;was  goto MainLoop
		movfw	RCREG		;get received data
;//
		movwf	PORTB
		
		bsf	Flags,0		
		return

Have fun.

Mike.
 
Pommie said:
Code:
SetupSerial:	Bank1				;select bank 1
	movlw	b'[COLOR="Blue"]11[/COLOR]000011'	;set tris bits for TX and RX
	movwf	TRISC

ReceiveSerial:	Bank0			;select bank 0
		btfss	PIR1,RCIF	;check if data
		[COLOR="Blue"]return[/COLOR]			;was  goto MainLoop
		movfw	RCREG		;get received data
;//
		movwf	PORTB
		
		bsf	Flags,0		
		return

Dear Mike,

Thank you again for the valuable guidance. It was really stupid of me not to look at the TRISC values. Thanks again Mike :)

I stated in my last post that the same code was working for the TX part. I think the reason is that the assembler clears the TX pin even if I set the TX pin in the code. So fortunately it worked.

Mike- I changed the code as you have suggested and it's actually working :D .
But it's working in the other way around :confused: . If you look at the code [below], I am expecting an input from the TERMINAL and as soon as I receive an input, the value should display on PORTB LEDs and finally I am sending 0x31 [char 1] to the TERMINAL.

But the code is doing something else. As soon as I am pressing the go [release from reset] button in MPLAB, I am getting 1 on the TERMINAL as well as on PORTB LEDs. :confused:

I am not sure where the bug is. Please provide any suggestions on this.

Thanks again Mike.

Vili

Code:
	list p=16f877a		;list directive to define processor
		#include <p16f877a.inc>	;processor specific definitions
		errorlevel -302		;suppress "not in bank 0" message

		__config _LVP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF & _DEBUG_OFF

;Bit Definitions

GotNewData	EQU	0		;bit indicates new data received

;----------------------------------------------------------------------------
;Variables

		CBLOCK	0x20
		Flags			;byte to store indicator flags
		ENDC

;----------------------------------------------------------------------------
;Macros to select the register bank
;Many bank changes can be optimized when only one STATUS bit changes

Bank0		MACRO			;macro to select data RAM bank 0
		bcf	STATUS,RP0
		bcf	STATUS,RP1
		ENDM

Bank1		MACRO			;macro to select data RAM bank 1
		bsf	STATUS,RP0
		bcf	STATUS,RP1
		ENDM

Bank2		MACRO			;macro to select data RAM bank 2
		bcf	STATUS,RP0
		bsf	STATUS,RP1
		ENDM

Bank3		MACRO			;macro to select data RAM bank 3
		bsf	STATUS,RP0
		bsf	STATUS,RP1
		ENDM

;----------------------------------------------------------------------------
;This code executes when a reset occurs.

		ORG     0x0000		;place code at reset vector

ResetCode:
		clrf    PCLATH		;select program memory page 0
  		goto    Main		;go to beginning of program

;---------------------------------------------------------------------------

;----------------------------------------------------------------------------
;Main routine calls the receive polling routine and checks for a byte
;received. It then calls a routine to transmit the data back.

Main:	ORG		0X010	
		call	SetupSerial			;set up serial port and buffers

;//************-------------------------**************do other initialization here

MainLoop:	
		call	ReceiveSerial			;go get received data if available
		btfss	Flags,GotNewData	 ;check if data received
		return
		call	TransmitSerial			;if so then go transmit the data
		bcf		Flags,GotNewData		;indicate no data received
									;do other stuff here
		goto	MainLoop			;go do main loop again

;----------------------------------------------------------------------------
;Check if data received and if so, return it in the working register.

ReceiveSerial:	;Bank0				;select bank 0
		btfss	PIR1,RCIF			;check if data
		return
		movfw	RCREG				;get received data
;//
		movwf	PORTB
		
		bsf		Flags,GotNewData		;indicate new data received
		return

;----------------------------------------------------------------------------
;Transmit data in WREG when the transmit register is empty.

TransmitSerial:;	Bank0			;select bank 0
		movlw	0x31      ; no 1
		movwf	TXREG		;and transmit the data

Loop	btfss	PIR1,TXIF		;check if transmitter busy
		goto	Loop			;wait until transmitter is not busy	
;********************************************
	
		return

;----------------------------------------------------------------------------
;Set up serial port.

SetupSerial:	Bank1				;select bank 1
		movlw	b'11000000'			;set tris bits for TX and RX
		movwf	TRISC
		movlw	b'00000000'
		movwf	TRISB
		movlw	b'00011001'		;set baud rate
		movwf	SPBRG
		movlw	b'00100100'			;enable transmission and high baud rate
		movwf	TXSTA
		Bank0				;select bank 0
		movlw	B'10010000'		;enable serial port and reception
		movwf	RCSTA
		bsf		PIR1,TXIF	;**Set interrupt
		bcf		PIR1,RCIF
	;	bsf		PIE1,RCIE
		clrf	Flags		;clear all flags
		clrf	PORTB
		clrf	PORTC
		return

;----------------------------------------------------------------------------

		END
 
Hi,
Code:
MainLoop:	
		call	ReceiveSerial			;go get received data if available
		btfss	Flags,GotNewData	 ;check if data received
		return

where should it return to? Try replacing return with goto MainLoop
 
bananasiong said:
Hi,
Code:
MainLoop:	
		call	ReceiveSerial			;go get received data if available
		btfss	Flags,GotNewData	 ;check if data received
		return

where should it return to? Try replacing return with goto MainLoop

Well spotted Bananasiong.

Do you have a shorter name?

Mike.
 
Mike- I found out the problem!

Using serial cable connection, the same code works absolutely fine. As soon as I am using the USB, it doesn't seem to work at all.

That means, TX is working fine with the USB but it's not working for the RX section. In my UM232R USB circuit, I have connected the handshaking pins [RTS# and CTS#] to each other and not to the PIC. It works for the TX part. I am not sure whether this is causing the problem when I am receiving the data.

I will be really grateful if you could have a look it. [the datasheet and schematic is attached in post 1]

Many many thanks.

Vili
 
Pommie said:
Did you correct the mistake that bananasiong spotted?

Mike.

Mike- I had already changed the mistake in my code :) and it worked absolutely fine with the Serial port cable. The same code doesn't work when the USB module is connected.

Again, if I use just the TX code [with USB module] it works but with TX and RX combined in the same code, it doesn't seem to read any input from TERMINAL, thus the code just loops around in the Main routine giving nothing either on PORTB nor on TERMINAL.

I am a bit puzzled about this :confused: ??

Many thanks.

vili
 
If it works with a serial cable then there is nothing wrong with the code. Are you powering the USB module from 5V?

Mike.
 
Mike- I am supplying 5 V and actually I am using the same settings that I used for the TX part [and it worked]. It's just the RX part. I am concerned about the RTS# and CTS# pins [Hanshaking] of the USB. Do you think this might be the cause of not to receive??

Thanks again Mike.
Vili
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top