That is not assembler. That is C.I know nothing about assembler, so please forgive the stupid questions.
Does this line of code agree with the explanation of what it does?
What does the == mean?Rich (BB code):; if(datahi == 0x0F) // if data == 0xF0..0xFF
Thanks.
There's the answer to my first question. I didn't think the if statement agreed with the explanation. How would one correct the if statement to make it agree with the explanation?Also, the explanation is wrong.
The way that if statement is done, it only works for one case. When datahi is 0x0F. The if statement does not include situations when datahi is 0x1F or 0x2F or 0x3F, etc. But the note says that it should work for all the values of datahi, from 0x0F to 0xFF.
You want to force the bits that you don't care about to be either a 0 or a 1 and then check accordingly.There's the answer to my first question. I didn't think the if statement agreed with the explanation. How would one correct the if statement to make it agree with the explanation?
Thanks.
To make the if statement fit the explanations, you could do it this simple way:It looks to my uneducated mind as if the explanation is defining a range of values, i.e., from hex F0 to hex FF. Is that correct, and if not, how should the explanation be understood?
Thanks.
;******************************************************************
; *
; Filename: ezLCD v3 (12F683).asm *
; Author: Mike McLaren, K8LH *
; (C)2010: Micro Application Consultants, All Rights Reserved *
; Date: 08-Dec-11 (rev:111210.0637z) *
; *
; K8LH 12F683 serial HD44780 LCD 4-bit interface experiment *
; *
; 8-bit test code. this interface traps a 0xFE character and *
; writes the character immediately following it to the LCD as *
; a command character (RS = 0) *
; *
; *
; MPLab: 8.80 (tabs=8) *
; MPAsm: 5.43 *
; *
;******************************************************************
#include <p12f683.inc>
list st=off
errorlevel -302
radix dec
__config _FCMEN_OFF&_IESO_OFF&_MCLRE_OFF&_WDT_OFF&_INTRC_OSC_NOCLKOUT
;--< variables >---------------------------------------------------
datahi equ 0x40 ; shadow for 1st nibble
datalo equ 0x41 ; shadow for 2nd nibble
temp equ 0x42 ; low level LCD routines
delayhi equ 0x43 ;
rsflag equ 0x44 ;
;--< constants >---------------------------------------------------
;
; bit time (cycles) used to sample a serial bit stream
;
; 19200 baud, 104 (104.2) cycles, 0.16% bit rate error
; 57600 baud, 35 ( 34.7) cycles, 0.80% bit rate error
; 115200 baud, 17 ( 17.4) cycles, 2.08% bit rate error
; 250000 baud, 8 ( 8.0) cycles, 0.00% bit rate error
;
clock equ 8 ; 8 MHz clock
usecs equ clock/4 ; cycles/usec multiplier
msecs equ clock/4*1000 ; cycles/msec multiplier
bRate equ 9600 ; baudrate 19200, 57600 or 115200
bTime equ (usecs*10000000/bRate+5)/10
; bTime = 104, 35 or 17 cycles
;
#define D4 0 ; GP0 -> LCD 'D4'
#define D5 1 ; GP1 -> LCD 'D5'
#define D6 2 ; GP2 -> LCD 'D6'
#define SerPin GPIO,3 ; GP3 -> Serial Input
#define D7 4 ; GP4 -> LCD 'D7'
#define E 5 ; GP5 -> LCD 'E'
#define RS D4 ; RS 'rc' integrator on D4 pin
;--< macros >------------------------------------------------------
;
; inDlyCy() in-line delay macro, range 1..1023 cycles,
; produces 1 to 6 instructions.
;
inDlyCy macro pTime
local dloop
if pTime > 3
movlw (pTime)/4-1 ;
dloop addlw -1 ;
bc dloop ;
endif
if pTime%4 & 1
nop ; 1 cycle
endif
if pTime%4 & 2
goto $+1 ; 2 cycles
endif
endm
;
; K8LH DelayCy() subsystem macro generates four instructions
;
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf delayhi
movlw low ((delay-11)/5)
call uDelay-((delay-11)%5)
endm
;******************************************************************
; Reset Vector *
;******************************************************************
org 0x0000
v_reset
clrf STATUS ; |B0
goto Main ; |B0
;******************************************************************
; Interrupt Vector *
;******************************************************************
org 0x0004
v_int
;
; using IOC interrupt on start bit leading edge
;
inDlyCy(bTime/2-4) ; half bit time minus 4 cycles |B0
movlw 1<<E ; preset E bit |B0
movwf datahi ; |B0
movwf datalo ; |B0
;
; collect lo nibble in 'datalo' (LCD data bits b0..b3)
;
bit0 inDlyCy(bTime-3) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datalo,D4 ; set LCD D4 shadow bit |B0
bit1 inDlyCy(bTime-2) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datalo,D5 ; set LCD D5 shadow bit |B0
bit2 inDlyCy(bTime-2) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datalo,D6 ; set LCD D6 shadow bit |B0
bit3 inDlyCy(bTime-2) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datalo,D7 ; set LCD D7 shadow bit |B0
;
; collect hi nibble in 'datahi' (LCD data bits b4..b7)
;
bit4 inDlyCy(bTime-2) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datahi,D4 ; set LCD D4 shadow bit |B0
bit5 inDlyCy(bTime-2) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datahi,D5 ; set LCD D5 shadow bit |B0
bit6 inDlyCy(bTime-2) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datahi,D6 ; set LCD D6 shadow bit |B0
bit7 inDlyCy(bTime-2) ; |B0
btfsc SerPin ; bit = 0? yes, skip, else |B0
bsf datahi,D7 ; set LCD D7 shadow bit |B0
I like it. It much shorter then what I proposed using ||, OR, operator.It really depend on what that comment means.
It could also mean:
if(datahi >= 0x0F || datahi <= 0xff)
Or datahi is greater or equal to 0x0f or datahi is less than or equal to 0xff.
;
; if(datahi == 0x0F) // if data == 0xF0..0xFF
; { datahi.E = 0; // don't write LCD (E bit off)
; datalo.E = 0; // don't write LCD (E bit off)
; } //
; gpio = rsflag; // charge or drain RS cap
; delay_us(3); //
; gpio = datahi; // setup D4..D7 and E=1
; gpio.E = 0; // E = 0 (write LCD)
; gpio = rsflag; // charge or drain RS cap
; delay_us(3); //
; gpio = datalo; // setup D4..D7 and E=1
; gpio.E = 0; // E = 0 (write LCD)
;
; rsflag ^= 1<<RS; // toggle rs flag
; if(datahi.E) // if not 0xFE character
; rsflag = 1<<RS; // reset rs flag (RS=1)
;
wrhi
movf rsflag,W ; the RS bit flag & mask |B0
movwf GPIO ; charge or drain RS cap |B0
movlw b'00110111' ; mask for datahi = 0x0F |B0 --
xorwf datahi,W ; is data == 0xF0..0xFF? |B0 --
skpnz ; no, skip, else |B0 --
bcf datahi,E ; don't write LCD |B0 --
skpnz ; no, skip, else |B0 --
bcf datalo,E ; don't write LCD |B0 --
movf datahi,W ; get data 7..4 bits |B0
movwf GPIO ; setup D4..D7, E=1 |B0
bcf GPIO,E ; E = 0 (write LCD) |B0
wrlo
movf rsflag,W ; the RS bit flag & mask |B0
movwf GPIO ; charge or drain RS cap |B0
movlw 1<<RS ; |B0 --
xorwf rsflag,F ; toggle RS flag & mask |B0 --
btfsc datahi,E ; if datahi not 0x0F |B0 --
iorwf rsflag,F ; reset RS flag & mask (RS=1) |B0 --
goto $+1 ; |B0 --
movf datalo,W ; get data 3..0 bits |B0
movwf GPIO ; setup D4..D7, E = 1 |B0
bcf GPIO,E ; E = 0 (write LCD) |B0
stop
inDlyCy(bTime-24) ; during middle of stop bit |B0
movf GPIO,W ; clear IOC mismatch |B0
bcf INTCON,GPIF ; clear IOC interrupt flag |B0
retfie ; |B0
;******************************************************************
; main *
;******************************************************************
;
; void main()
; {
; cmcon0 = 7; // comparator off
; gpio = 0; // clear gpio output latches
; trisio = 0b00001000; // gp3 input, others outputs
; osccon = 0b01110000; // setup intosc for 8 MHz
; while(osccon.HTS == 0); // wait for osc stable
;
Main
movlw b'00000111' ; |B0
movwf CMCON0 ; comparator off |B0
clrf GPIO ; clear GPIO output latches |B0
bsf STATUS,RP0 ; bank 1 |B1
; clrf ANSEL ; no analog, all digital |B1
movlw b'00001000' ; GP3 input, all others outputs |B1
movwf TRISIO ; |B1
movwf IOCA ; enable IOC for GP3 'SerPin' |B1
movlw b'01110000' ; |B1
movwf OSCCON ; 8-mhz INTOSC system clock |B1
stable btfss OSCCON,HTS ; oscillator stable? |B1
goto stable ; no, branch, else |B1
;
; HD44780 "initialize by instruction" for 4-bit interface mode
;
bcf STATUS,RP0 ; bank 0 |B0
DelayCy(50*msecs) ; LCD 50 msec 'power up' reset |B0
movlw 0x03 ; hi nibble of "8-bit" command |B0
call PutNyb ; step 1 (send nibble only) |B0
DelayCy(4*msecs) ; required 4 msec delay |B0
movlw 0x03 ; |B0
call PutNyb ; step 2 (send nibble only) |B0
DelayCy(160*usecs) ; (n/a for serial interface) |B0
movlw 0x03 ; |B0
call PutNyb ; step 3 (send nibble only) |B0
DelayCy(160*usecs) ; (n/a for serial interface) |B0
movlw 0x02 ; hi nibble of "4-bit" command |B0
call PutNyb ; select 4-bit interface mode |B0
DelayCy(160*usecs) ; (n/a for serial interface) |B0
movlw 0x28 ; 4-bit, 2-lines, 5x7 font |B0
call PutCmd ; send "function set" command |B0
movlw 0x0C ; display on, cursor & blink off |B0
call PutCmd ; send "display on/off" command |B0
movlw 0x06 ; cursor inc, shift off |B0
call PutCmd ; send "entry mode set" command |B0
movlw 0x01 ; clear display (1.53-msecs) |B0
call PutCmd ; send "entry mode set" command |B0
DelayCy(1530*usecs) ; 1.53 msec delay for "clear" |B0
;
; // setup RA3 'SerPin' for interrupt-on-change
;
; rsflag = 1<<RS; // set RS flag & mask
; while(SerPin == 0); // wait for hi level on GP3
; temp = gpio; // clear any mismatch condx
; intcon.RAIF = 0; // clear IOC interrupt flag
; ioca.IOCA3 = 1; // eanble IOC for GP3 'SerPin'
; intcon.GIE = 1; // enable global interrupts
;
; while(1); // loop forever
; }
;
bcf STATUS,RP0 ; bank 0 |B0
movlw 1<<RS ; |B0
movwf rsflag ; set RS flag & mask (RS=1) |B0
btfss SerPin ; stop state? yes, skip, else |B0
goto $-1 ; loop (wait) |B0
movf GPIO,W ; clear GPIO mismatch condition |B0
bcf INTCON,GPIF ; clear IOC interrupt flag |B0
bsf INTCON,GIE ; enable global interrupts |B0
bsf INTCON,GPIE ; enable 'IOC' interrupts |B0
loop
goto loop ; loop forever |B0
;******************************************************************
; low level lcd subroutines *
;******************************************************************
PutCmd ; entry point for "cmd" data
clrc ; RS = 0 (command) |B?
skpnc ; skip unconditionally |B?
PutDat ; entry point for "dat" data
setc ; RS = 1 (data) |B?
banksel temp ; bank 0 |B0
movwf temp ; save WREG data byte |B0
swapf temp,W ; |B0
call PutNyb ; send hi nybble |B0
swapf temp,W ; |B0
call PutNyb ; send lo nybble |B0
DelayCy(50*usecs) ; required between writes |B0
return ; |B0
PutNyb
movwf temp ; |B0
bcf GPIO,RS ; RS = 0 (discharge RS cap) |B0
skpnc ; RS = 0? yes, skip, else |B0
bsf GPIO,RS ; RS = 1 (charge RS cap) |B0
movlw 1<<E ; |B0
btfsc temp,0 ; |B0
iorlw 1<<D4 ; |B0
btfsc temp,1 ; b1 = 0? yes, skip, else |B0
iorlw 1<<D5 ; |B0
btfsc temp,2 ; b2 = 0? yes, skip, else |B0
iorlw 1<<D6 ; |B0
btfsc temp,3 ; b3 = 0? yes, skip, else |B0
iorlw 1<<D7 ; |B0
movwf GPIO ; LCD D4..D7 = data1, E = 1 |B0
bcf GPIO,E ; E = 0 |B0
return ; |B0
;******************************************************************
; K8LH DelayCy() 16-bit uDelay (11..327690 cycle) subroutine *
;******************************************************************
nop ; entry for (delay-11)%5 == 4 |B0
nop ; entry for (delay-11)%5 == 3 |B0
nop ; entry for (delay-11)%5 == 2 |B0
nop ; entry for (delay-11)%5 == 1 |B0
uDelay addlw -1 ; subtract 5 cycle loop time |B0
skpc ; borrow? no, skip, else |B0
decfsz delayhi,F ; done? yes, skip, else |B0
goto uDelay ; do another loop |B0
return ; return with C = Z = 0 |B0
;******************************************************************
end
Ok. That one is combination of assembler and C. It depends on software environment/infrastructure, some support assembler sections in C, some don't.Here is the first half of the code as written and posted by Mike McLaren. Apparently it's too long to include in one post, so I will put the last half in another post.) I had hoped he would happen by, but so far has not. So, I am trying to troubleshoot code that I don't understand. The whole story is in this thread.
Rich (BB code):;****************************************************************** ; * ; Filename: ezLCD v3 (12F683).asm * ; Author: Mike McLaren, K8LH * ; (C)2010: Micro Application Consultants, All Rights Reserved * ; Date: 08-Dec-11 (rev:111210.0637z) * ; * ; K8LH 12F683 serial HD44780 LCD 4-bit interface experiment * ; * ; 8-bit test code. this interface traps a 0xFE character and * ; writes the character immediately following it to the LCD as * ; a command character (RS = 0) * ; * ; * ; MPLab: 8.80 (tabs=8) * ; MPAsm: 5.43 * ; * ;****************************************************************** #include <p12f683.inc> list st=off errorlevel -302 radix dec __config _FCMEN_OFF&_IESO_OFF&_MCLRE_OFF&_WDT_OFF&_INTRC_OSC_NOCLKOUT ;--< variables >--------------------------------------------------- datahi equ 0x40 ; shadow for 1st nibble datalo equ 0x41 ; shadow for 2nd nibble temp equ 0x42 ; low level LCD routines delayhi equ 0x43 ; rsflag equ 0x44 ; ;--< constants >--------------------------------------------------- ; ; bit time (cycles) used to sample a serial bit stream ; ; 19200 baud, 104 (104.2) cycles, 0.16% bit rate error ; 57600 baud, 35 ( 34.7) cycles, 0.80% bit rate error ; 115200 baud, 17 ( 17.4) cycles, 2.08% bit rate error ; 250000 baud, 8 ( 8.0) cycles, 0.00% bit rate error ; clock equ 8 ; 8 MHz clock usecs equ clock/4 ; cycles/usec multiplier msecs equ clock/4*1000 ; cycles/msec multiplier bRate equ 9600 ; baudrate 19200, 57600 or 115200 bTime equ (usecs*10000000/bRate+5)/10 ; bTime = 104, 35 or 17 cycles ; #define D4 0 ; GP0 -> LCD 'D4' #define D5 1 ; GP1 -> LCD 'D5' #define D6 2 ; GP2 -> LCD 'D6' #define SerPin GPIO,3 ; GP3 -> Serial Input #define D7 4 ; GP4 -> LCD 'D7' #define E 5 ; GP5 -> LCD 'E' #define RS D4 ; RS 'rc' integrator on D4 pin ;--< macros >------------------------------------------------------ ; ; inDlyCy() in-line delay macro, range 1..1023 cycles, ; produces 1 to 6 instructions. ; inDlyCy macro pTime local dloop if pTime > 3 movlw (pTime)/4-1 ; dloop addlw -1 ; bc dloop ; endif if pTime%4 & 1 nop ; 1 cycle endif if pTime%4 & 2 goto $+1 ; 2 cycles endif endm ; ; K8LH DelayCy() subsystem macro generates four instructions ; DelayCy macro delay ; 11..327690 cycle range movlw high((delay-11)/5)+1 movwf delayhi movlw low ((delay-11)/5) call uDelay-((delay-11)%5) endm ;****************************************************************** ; Reset Vector * ;****************************************************************** org 0x0000 v_reset clrf STATUS ; |B0 goto Main ; |B0 ;****************************************************************** ; Interrupt Vector * ;****************************************************************** org 0x0004 v_int ; ; using IOC interrupt on start bit leading edge ; inDlyCy(bTime/2-4) ; half bit time minus 4 cycles |B0 movlw 1<<E ; preset E bit |B0 movwf datahi ; |B0 movwf datalo ; |B0 ; ; collect lo nibble in 'datalo' (LCD data bits b0..b3) ; bit0 inDlyCy(bTime-3) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datalo,D4 ; set LCD D4 shadow bit |B0 bit1 inDlyCy(bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datalo,D5 ; set LCD D5 shadow bit |B0 bit2 inDlyCy(bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datalo,D6 ; set LCD D6 shadow bit |B0 bit3 inDlyCy(bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datalo,D7 ; set LCD D7 shadow bit |B0 ; ; collect hi nibble in 'datahi' (LCD data bits b4..b7) ; bit4 inDlyCy(bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datahi,D4 ; set LCD D4 shadow bit |B0 bit5 inDlyCy(bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datahi,D5 ; set LCD D5 shadow bit |B0 bit6 inDlyCy(bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datahi,D6 ; set LCD D6 shadow bit |B0 bit7 inDlyCy(bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf datahi,D7 ; set LCD D7 shadow bit |B0