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.

Any assembly experts here?

Status
Not open for further replies.

scomi

New Member
Seems like it is quite hard to find someone who is using machine language like assembly for programming. As I only know C and C++ but not assembly. However I was not lucky enough to have a reference of project codes written in assembly. Thinking of modifying part of it really get me headache. Anyone kind enuf here?:)
 
I was using assembly language before for intel microprocessors. I used 386, 486, 586, pentium 2 and I think 3 and 4 too. I also tried for the PIC assembly language. what do you want to understand really?
 
ASM is to C as the telegraph is to the telephone.
 
A couple of years ago I would have stated that asm was the only way to write code on a microcontroller. This has now changed as we now have compilers that produce code that is only slightly slower than you could write in assembler. Have a look at BoostC and Swordfish Basic, both very powerful languages that enable you to write efficient code in a fraction of the time. The only time I would now use asm is if it was really time and cost critical.

Mike.
 
ASM pro reporting for duty!

You can post your code here, or post it on Microchips forums.
 
I write nearly all my code in assembler. C is for wusses.
 
You guys are all jumping on this, but you have no idea what processor this project is for or that he wants help with.

Just post your question and if people can answer it, they will.
 
Last edited:
It doesn't matter. If you've seen one assembly language you've seen 'em all.
 
Seems like there are a lots of assembly programmer here. However when asking on getting some help, some run! Haha.

OK, serious. I have an assembly code. There is a register which is used to store a variable called AmpHours. It is a 16 bit binary number. The number is big-endian, higher byte are in the RAM address while lower byte in AmpsHours+1. I want to get only this binary out as serial. Instead, I will need to convert this to ASCII string. And this meter only takes 3 readings per second.

I know as long as IO available, it can be used as serial communication. I am using the 16F88. Serial routine is my obstacle now. Assembler?

Code:
;                  Main Program Starts Here!

Start:
	clrf 	PORTA
	clrf	PORTB
	bsf	STATUS,RP0	; bank 1
	ifdef	__16F88
	movlw	B'11101111'	; PortA directions (16F88)
	movwf	TRISA
	movlw	B'11000001'	; PortB directions (16F88)
	movwf	TRISB
	movlw	B'01100000'	; 4MHz internal osc (16F88)
	movwf	OSCCON
	else
	movlw	B'11111111'	; PortA directions (16F870)
	movwf	TRISA
	movlw	B'00000000'	; PortB directions (16F870)
	movwf	TRISB
	movlw	B'11111111'	; PortC directions (16F870)
	movwf	TRISC
	endif
	movlw   B'01010111'	; Weak pullups enabled, Timer0 src = clkout/256
	movwf	OPTION_REG
	bcf	STATUS,RP0	; bank 0

; Set up Interrupts

	clrf	INTCON		; clear any pending ints
	clrf	PIR1
	bsf	INTCON,PEIE	; enable peripheral ints
	bsf	INTCON,GIE	; enable interrupts

; set up LCD Display

	movlw	25		; wait 500mS
	call	waitx20k

	call	LCDinit		; Set up the LCD display
	call	show_signon	; show signon message

	movlw	50		; wait 1 second
	call	waitx20k

; set up A/D convertor

	bsf	STATUS,RP0	; bank 1
	ifdef	__16F88
	movlw	b'10110000'	; right-justify, ext vref (16F88)
	movwf	ADCON1
	movlw	b'00001111'
	movwf	ANSEL		; Analog inputs on RA0~RA3 (16F88)
	else
	movlw	b'10001101'	; right-justify, ext vref, RA1/RA0 (16F870)
	movwf	ADCON1
	endif
	bcf	STATUS,RP0	; bank 0
	movlw	b'01000000'	; CLK/8
	movwf	ADCON0

; Start Timer0

	movlw	REFRESH_DELAY
	movwf	TMR0

; initialize variables

	clrf	Flags
	clrf	Flags2
	movlw	0
	movwf	pagenum
	clrf	Page_Timer
	clrf	Blade_Timer
	clr16	CCPR
	clr16	Period
	clr32	AmpSum
	clr32	rpm
	movlw	2
	movwf	NumBlades

; Set up CCP1 and Timer1 for rpm capture

	clrf	TMR1L
	clrf	TMR1H		; clear Timer1
	movlw	b'00100001'
	movwf	T1CON		; 4:1 prescaler, Timer1 ON
	bcf	PIR1,TMR1IF
	bcf	PIR1,CCP1IF	; clear Int flags
	banksel	PIE1
	bsf	PIE1,CCP1IE	; enable CCP1 Ints
	bsf	PIE1,TMR1IE	; enable TMR1 Ints
	banksel	0
	movlw	b'00000111'	; capture every 16th leading edge
	movwf	CCP1CON		; enable Capture

ReadInputs:
	clr16	Volts
	clr16	Amps
	clr16	Watts
	movlw	64		; 64 times oversampling
	movwf	Readings
NextRead:
	movlw	b'01000001'	; CLK/8, select RA0 (Volts), A/D on
	movwf	ADCON0
	call	wait100		; wait 100uS to stabilize analog input
	bsf	ADCON0,GO_DONE	; start A/D conversion
waitv:	btfsc	ADCON0,GO_DONE
	goto	waitv		; wait until conversion Done
	movf	ADRESH,w
	movwf	Temp1
	addwf	Volts
	bsf	STATUS,RP0
	movf	ADRESL,w	; add 10 bit A/D result to Volts
	bcf	STATUS,RP0
	movwf	Temp2
	addwf	Volts+1
	skpnc
	incf	Volts

	bcf	Flags,MAX_VOLTS
	movf	Temp1,w
	xorlw	b'00000011'
	skpnz
	bsf	Flags,MAX_VOLTS	; Volts overloaded ?
	movf	Temp2,w
	xorlw	b'11111111'
	skpz
	bcf	Flags,MAX_VOLTS

	movlw	b'01001001'	; CLK/8, select RA1 (Amps), A/D on
	movwf	ADCON0
	call	wait100		; wait 100uS to stabilize analog input
	bsf	ADCON0,GO_DONE	; start A/D conversion
waita:	btfsc	ADCON0,GO_DONE
	goto	waita		; wait until conversion Done
	movf	ADRESH,w
	movwf	Temp1
	addwf	Amps
	bsf	STATUS,RP0
	movf	ADRESL,w	; get 10 bit A/D result
	bcf	STATUS,RP0
	movwf	Temp2
	addwf	Amps+1
	skpnc
	incf	Amps

	bcf	Flags,MAX_AMPS
	movf	Temp1,w
	xorlw	b'00000011'
	skpnz
	bsf	Flags,MAX_AMPS	; Amps overloaded ?
	movf	Temp2,w
	xorlw	b'11111111'
	skpz
	bcf	Flags,MAX_AMPS

	decfsz	Readings
	goto	NextRead	; accumulate readings

	clrc
	rr16	Volts		; Volts / 2

	movlw	Volts
	call	Divx12		; Volts / 12.8

	movlw	Amps
	call	Divx12		; Amps / 12.8

	btfsc	Flags,GOT_ZERO	; have Amps been zeroed ?
	goto	sub_zero
get_zero:
	mov16	Amps,ZeroAmps	; record zero Amps value
	bsf	Flags,GOT_ZERO
sub_zero:
	bcf	Flags,NEG_AMPS
	sub16	ZeroAmps,Amps	; subtract zero value from Amps
	skpnc
	goto	got_amps
	bsf	Flags,NEG_AMPS
	com16	Amps		; Amps = -0 to -0.99
got_amps:
	mov16	Amps,aa
	mov16	Volts,bb
	call	Mult16		; Watts = Volts * Amps
	movi16	1000,aa
	call	Div32		; Watts = Watts / 1000
	subi16	500,bb
	skpc			; remainder > 0.5 ?
	goto	store_watts
	inc16	dd+2		; yes, round up
store_watts:
	mov16	dd+2,Watts
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


; CCPR is a copy of the CCPR1 register. It is updated from the Interrupt
; routine. This may happen at any time, so we must prevent it from being
; updated while copying it. We cannot disable interrupts while copying
; because it could upset capture timing.
;
	bsf	Flags,LOCK_P	; lock CCPR
	mov16	CCPR,Period     ; get period (1/rpm)
	bcf	Flags,LOCK_P	; unlock CCPR

; reduce rpm jitter by averaging this and previous measurement

	tst16	Period
	skpz			; got good rpm ?
	goto	sp_good
	clr16	OldPeriod	; no, old period = 0
	goto	sp_done
sp_good:
	tst16	OldPeriod
	skpnz			; got previous good rpm ?
	goto	sp_done		; no
	mov1632	Period,dd
	add1632	OldPeriod,dd
	rr32	dd		; dd = (Period+OldPeriod)/2
	mov16	Period,OldPeriod ; old period = current period
	mov16	dd+2,Period	; Period now averaged
sp_done:

; show results on LCD screen

do_display:
	movlw	6		; 6 * 55.555mS = 3 readings per second
	movwf	ref_timer
display_page:
	movlw	0
	call	Set_Cursor	; set cursor to start of line
	movf	pagenum,w
	skpnz			; page 0 ?
	goto	page0
	addlw	-1
	skpnz			; page 1 ?
	goto	page1

	ifdef	LCD8x2

; 8x2 or 16x1 display, 3 pages

	addlw	-1
	skpnz			; page 2 ?
	goto	page2

page0:	call	Show_Volts
	movlw	LCDLINE2
	call	Set_Cursor	; "99.99V 99.99A"
	call	Show_Amps
	goto	ref_delay

page1:	call	Show_Watts	; "9999.9W 99.99Ah"
	movlw	LCDLINE2
	call	Show_AmpHours
	goto	ref_delay

page2:	call	Show_rpm
	movlw	LCDLINE2
	call	Set_Cursor	; "99999rpm   x 9"
	call	Show_Blades

	else

; 16x2 display, 2 pages

page0:	call	Show_Volts
	call	Show_Amps	; "99.99V 99.99A"
	movlw	LCDLINE2
	call	Set_Cursor
	call	Show_Watts
	call	Show_AmpHours 	; "9999.9W 99.99Ah"
	goto	ref_delay

page1:	call	Show_Volts
	call	Show_Amps	; "99.99V 99.99A"
	movlw	LCDLINE2
	call	Set_Cursor
	call	Show_rpm	; "99999rpm   x 9"
	call	Show_Blades

	endif

; Wait 1/3 second (3 readings per second)
; Check buttons while waiting

ref_delay:
	btfss	INTCON,TMR0IF
	goto	ref_delay	; wait for Timer0 overflow (55.555mS)
	movlw	REFRESH_DELAY
	addwf	TMR0		; recharge Timer0
	bcf	INTCON,TMR0IF
	call	page_button	; handle page button
	call	blade_button	; handle blades button
	decfsz	ref_timer
	goto	display_page	; 6 Timer0 overflows = 333.3mS (1/3 Second)
check_hold:
	btfss	HDBTN		; hold switch on ?
	goto	do_display	; yes, hold last readings

	goto	ReadInputs	; no, get new readings

	END
 
As always, check my tutorials, which include routines for both software and hardware serial, plus routines for 16 bit binary to ASCII, and display on both LCD and via the serial port.
 
You want an assembly language routine to bit-bang a serial port on a PIC16F? That's a pretty common routine, Nigel has them, also check the Microchip website app notes.
 
Last edited:
You have gotten some excellent advice here, now ask yourself the question that Pommie raised - how much time do you have and is the timing of the application critical.

I love ASM, started with the motorola 68000 years ago - but even I had to port over to C for certain applications as the tradeoff (time\speed) was worth it.

If you were to develop in C with the 16F88 you would be reducing the number of compilers that are available to you (I don't think MCC18 supports 16X chips).

All the best.
 
Thanks for reply me. Well, it is getting nearer to the deadline, hopefully u guys can standby so that i manage to have response as soon as possible.

OK now, 3 pins are unuse for 16F88, RA6, RA7, and RA8. However they represent MCLR, clock out and clock in respectively. Can i configure one of them as serial output?

I will looking at Nigel tutorials now ... lets boosts up, ok? Thanks
 
Last edited:
OK Nigel, I'd looked at your tutorial basically on serial transmission (RS232) and yet I found it is quite understand-able. I tried to modify it and suit to my application, just wanna ask is this working before I burnt my PIC down. LOL

OK, so here is the code modified from your tutorial 7:
Code:
;Serial routines
            Xmit_Byte    AmpHour        ;16 bits binary number
            ;Rcv_Byte     Equ  0x21        ;well I just need to transmit value in AmpHour
            Bit_Cntr     Equ  0x22        ;bit counter for RS232
            Delay_Count  Equ  0x23        ;delay loop counter
SER_INIT
            BSF     STATUS, RP0           ;select bank 1
            BCF     TRISA, 6              ;set A6 as an output
            ;BSF     TRISB, 7              ;set B7 as an input
            BCF     STATUS, RP0           ;select bank 0
            ;BSF     PORTA, 6              ;Set A6 HIGH
            RETURN

XMIT_RS232  MOVWF   Xmit_Byte             ;move W to Xmit_Byte
            MOVLW   0x10                 ;set 16 bits out
            MOVWF   Bit_Cntr
            BCF     PORTA, 6
            CALL    Bit_Delay
Ser_Loop    RRF     Xmit_Byte , f         ;send one bit
            BTFSS   STATUS    , C
            BCF     PORTA, 6
            BTFSC   STATUS    , C
            BSF     PORTA, 6
            CALL    Bit_Delay
            DECFSZ  Bit_Cntr  , f         ;test if all done
            GOTO    Ser_Loop
            BSF     PORTA, 6
            CALL    Bit_Delay
            RETURN

;Rcv_RS232   BTFSC   PORTB, 7              ;wait for start bit
;            GOTO    Rcv_RS232
;            CALL    Start_Delay	          ;do half bit time delay
;            BTFSC   PORTB, 7              ;check still in start bit
;            GOTO    Rcv_RS232
;            MOVLW   0x08                  ;set up to read 8 bits
;            MOVWF   Bit_Cntr
 ;           CLRF    Rcv_Byte

;Next_RcvBit CALL    Bit_Delay
;            BTFSS   PORTB, 7
;            BCF     STATUS    , C
;            BTFSC   PORTB, 7
;            BSF     STATUS    , C
;            RRF     Rcv_Byte  , f
;            DECFSZ  Bit_Cntr  , f         ;test if all done
 ;           GOTO    Next_RcvBit
 ;           CALL    Bit_Delay
 ;           MOVF    Rcv_Byte, W
 ;           RETURN

Start_Delay MOVLW   0x0C
            MOVWF   Delay_Count
Start_Wait  NOP
            DECFSZ  Delay_Count , f
            GOTO    Start_Wait
            RETURN

Bit_Delay   MOVLW   0x18
            MOVWF   Delay_Count
Bit_Wait    NOP
            DECFSZ  Delay_Count , f
            GOTO    Bit_Wait
            RETURN

As RS232 require receive and transmit, but my application only needs to transmit the 2 Bytes/16 bits binary AmpHour out. I uses pin A6 as my output. How do I check whether Equ 0x22 (Bit count is the one can be stored?) Thanks.


My project coding is here.

Thank You
 
Last edited:
I know C and C++. I have good idea of Assembly so what are the details of your program.

Well, I am having project on watt meter. Within my project, I have voltage and current input at pin 17 and 16 respectively. Then the MCU will do ADC, display the voltage, current, watt and accumulated ampere hour to the LCD via the 2 control buses and 4 data buses. Beside having display the data on the LCD, i still need one serial output on the accumulated ampere hour out to my module. So i need some help here for having serial output to the module. The register Amphour is 16 bits binary, i need to convert it to ASCII string 1st before output it.
 
;BSF PORTA, 6 ;Set A6 HIGH

I don't think you want to comment out this one. That line idles high.
 
I don't think you want to comment out this one. That line idles high.

oopss... yaya..silly mistake .. :eek:

Code:
;Serial routines
            Xmit_Byte    AmpHour        ;16 bits binary number
            ;Rcv_Byte     Equ  0x21        ;well I just need to transmit value in AmpHour
            Bit_Cntr     Equ  0x22        ;bit counter for RS232
            Delay_Count  Equ  0x23        ;delay loop counter
SER_INIT
            BSF     STATUS, RP0           ;select bank 1
            BCF     TRISA, 6              ;set A6 as an output
            ;BSF     TRISB, 7              ;set B7 as an input
            BCF     STATUS, RP0           ;select bank 0
            BSF     PORTA, 6              ;Set A6 HIGH
            RETURN

XMIT_RS232  MOVWF   Xmit_Byte             ;move W to Xmit_Byte
            MOVLW   0x10                 ;set 16 bits out
            MOVWF   Bit_Cntr
            BCF     PORTA, 6
            CALL    Bit_Delay
Ser_Loop    RRF     Xmit_Byte , f         ;send one bit
            BTFSS   STATUS    , C
            BCF     PORTA, 6
            BTFSC   STATUS    , C
            BSF     PORTA, 6
            CALL    Bit_Delay
            DECFSZ  Bit_Cntr  , f         ;test if all done
            GOTO    Ser_Loop
            BSF     PORTA, 6
            CALL    Bit_Delay
            RETURN

;Rcv_RS232   BTFSC   PORTB, 7              ;wait for start bit
;            GOTO    Rcv_RS232
;            CALL    Start_Delay	          ;do half bit time delay
;            BTFSC   PORTB, 7              ;check still in start bit
;            GOTO    Rcv_RS232
;            MOVLW   0x08                  ;set up to read 8 bits
;            MOVWF   Bit_Cntr
 ;           CLRF    Rcv_Byte

;Next_RcvBit CALL    Bit_Delay
;            BTFSS   PORTB, 7
;            BCF     STATUS    , C
;            BTFSC   PORTB, 7
;            BSF     STATUS    , C
;            RRF     Rcv_Byte  , f
;            DECFSZ  Bit_Cntr  , f         ;test if all done
 ;           GOTO    Next_RcvBit
 ;           CALL    Bit_Delay
 ;           MOVF    Rcv_Byte, W
 ;           RETURN

Start_Delay MOVLW   0x0C
            MOVWF   Delay_Count
Start_Wait  NOP
            DECFSZ  Delay_Count , f
            GOTO    Start_Wait
            RETURN

Bit_Delay   MOVLW   0x18
            MOVWF   Delay_Count
Bit_Wait    NOP
            DECFSZ  Delay_Count , f
            GOTO    Bit_Wait
            RETURN
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top