PIC Assembler Modules

For Non-Commercial Use Only

I would appreciate to be credited within your project, if you use any of the source code below. If you have an interesting project going on, I'll be glad about feedback.

The software below comes with no guarantee or warranty except for my good intentions. Further the use of this code implies that the user has a fundamental understanding of electronics and its risks. I'm not responsible for any harm or damage, caused by inproper use of any of the code below.
Any commercial use of parts or all of this code requires the permission of the author.

Table of Contents [Toc]

General
Standard Modules
Dot Matrix LCD Modules
   LCD Display Driver Routines
   LCD Display Conversion Routines
Serial Communication Modules (RS232)
Notes on Modules
General Recommendations
   Known Limitations of MPLAB IDE
   Technical Hints

 

General  [Toc] [Top]

Modules are source code blocks, which can be included in the MAIN PROGRAM by simply adding the command line:
  #include "C:/ (...) m_bank.asm"
The code will be inline expanded. All you need is to specify the necessary registers in front of the include statement in the main program, e.g.

LCDtris equ TRISB
LCDport equ PORTB

CONSTANT BASE = 0x0C ; 16F84 base address of user file registers

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcd.asm"

 

Standard Modules   [Toc] [Top]

Assembler include files: General macros to ease assembler handling, e.g. macros BANK0, BANK1

m_bank.asm

V2.01  (2010/05/05)
Standard macros for bank and page handling and conditional branching.
Device-specific customization of macros by using #DEFINE TWO_BANKS for adjusting macro instructions to small PIC MCUs with only two register banks in order to optimize the corresponding code size.

Bank/page handling: BANK0, BANK1, BANK2, BANK3

Branch macros (to simplify 'IF THEN ELSE' queries):
  BEQ val: branch on equal w and val
  BNE val: branch on not equal w and val
  BREG val: branch on equal or greater w than val
  (...)

m_wait.asm

V1.02  (20.08.2004)
Parameterizable wait function, which performs a "busy" wait.
Suitable for all Microchip PIC MCUs with an internal 8-bit timer (routine uses TMR0).
Implemented standard delay (@ 4 MHz):
WAIT 0x01 is equal to 1 unit == 1.02 ms
The assigned standard prescaler for TMR0 is PRESCstd = b'00000001'

Relationship between TMR0 prescaler and unit delay (WAIT 0x01):
b'00000000' == 1:2 ==> 0.512 ms
b'00000001' == 1:4 ==> 1.02 ms (standard)
b'00000111' == 1:256 ==> 65.3 ms

Declarations required in main program:

CONSTANT BASE = 0x0C ; 16F84 base address of user file registers

#include "..\m_bank.asm"
#include "..\m_wait.asm"

; Call of implemented procedures with:
; WAIT 0x01 ; standard delay, 1.02 ms
; WAITX d'16',d'7' ; 1.045 s @ 4 MHz, extended with specific prescaler
m_beep.asm

V1.00  (16.02.2003)
Beep function on parameterizable output port.

Declarations required in main program:

#define BEEPport PORTA,0x0
#define BEEPtris TRISA,0x0

CONSTANT BASE = 0x0C ; 16F84 base address of user file registers

#include "..\m_bank.asm"
#include "..\m_beep.asm"

; Call of implemented procedures with:
; BEEPinit ; initialization to set output port
; BEEP 0xFF,0x0
m_16bit.asm
V1.01  (2010/05/14)
Provides basic 16-bit arithmetic routines such as CLR16, MOV16, NEG16, ADD16, SUB16, CMP16, LSR16, LSL16, INC16, and DEC16 operations and the corresponding immediate operations, if applicable.

For demo-programs or complete applications, refer to 'Projects'   [click here]
 

Dot Matrix LCD Modules   [Toc] [Top]

Assembler include files: Display drivers for dot matrix LCD displays.   (Hitachi HD44780 compatibles)
 

4x20 LCD

Dot Matrix LCD Display
4 lines x 20 characters

2x40 LCD

Dot Matrix LCD Display
2 lines x 40 characters

LCD Display Driver Routines   [Toc] [Top]

Download the PDF schematic to illustrate the connectivity of both 'classes' of LCD driver routines:

m_lcd.asm

V2.06  (26.12.2004)
7 wires, 4 bit LCD interface
Based on timing constraints, no busy flag check. So if LCD fails, system is still running stable. Higher reliability, because less critical system components.
No portable code for higher clock frequencies.
R/W connection to LCD supported for compatibility to m_lcd_bf.asm, but can be put to GND at LCD side => You'll get one interrupt pin more on the processor side.

Schematic of LCD connection (PDF)

Declarations required in main program:

LCDtris equ TRISB ; could also be PORTC, PORTD on 16F77
LCDport equ PORTB
; LCD data ports D4-D7 are on LCDport,0x1-0x4
; LCD_EN is on LCDport,0x05 ; Enable
; LCD_RW is on LCDport,0x06 ; Read/Write
; LCD_RS is on LCDport,0x07 ; Register Select

CONSTANT BASE = 0x0C ; 16F84 base address of user file registers

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcd.asm"
m_lcdx.asm

V2.26  (26.12.2004)
7 wires, 4 bit LCD interface
Extended m_lcd.asm with the ability to define your own characters (max. 8) in macro LCDspecialChars. Based on timing constraints, specifications as m_lcd.asm.

Schematic of LCD connection (PDF)

Declarations required in main program:

LCDtris equ TRISB ; could also be PORTC, PORTD on 16F77
LCDport equ PORTB
; LCD data ports D4-D7 are on LCDport,0x1-0x4
; LCD_EN is on LCDport,0x05 ; Enable
; LCD_RW is on LCDport,0x06 ; Read/Write
; LCD_RS is on LCDport,0x07 ; Register Select

CONSTANT BASE = 0x0C ; 16F84 base address of user file registers

; complete/replace macro LCDspecialChars to define your own characters
#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcdx.asm"

m_lcd_bf.asm

V3.09  (26.12.2004)
7 wires, 4 bit LCD interface
Extended m_lcd.asm which reads busy flag of LCD (bi-directional communication between controller and LCD)
R/W connection to LCD needed for hand shaking.
Clock independent program code, successfully tested up to 10 MHz on PIC 16F84 and up to 20 MHz on PIC 16C74A!
Gives the best performance, but system fails, if LCD (-connection) fails, because processor is waiting for ready signal from LCD to send next character. => Deadlock, but should not occur under normal circumstances!
Solution:
Connect an auxilliary 10k resistor from DB7 to GND, so if the LCD is disconnected, the microprocessor will read an inactive busy flag. (That's needed because of the internal weak pull ups of the microprocessor ports. Maybe also required if you switch them off.)

Schematic of LCD connection (PDF)

Declarations required in main program:

LCDtris equ TRISB ; could also be PORTC, PORTD on 16F77
LCDport equ PORTB
; LCD data ports D4-D7 are on LCDport,0x1-0x4
; LCD_EN is on LCDport,0x05 ; Enable
; LCD_RW is on LCDport,0x06 ; Read/Write
; LCD_RS is on LCDport,0x07 ; Register Select

CONSTANT BASE = 0x0C  ; 16F84 base address of user file registers
FLAGreg equ BASE+d'7' ; general flag register
#define LCDbusy FLAGreg,0x0 ; LCD busy flag
#define LCDcflag FLAGreg,0x1

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcd_bf.asm"

m_lcdxbf.asm

V3.29  (26.12.2004)
7 wires, 4 bit LCD interface
Basically the same as m_lcd_bf.asm, but with the ability to define your own characters (max. 8) in macro LCDspecialChars. Bi-directional communication, reads busy flag of LCD.

Schematic of LCD connection (PDF)

m_lcde.asm

V2.12e  (17.08.2004)
7 wires, 4 bit LCD interface
Basically as m_lcd.asm, but with the ability to independently configure LCD control and data lines, i.e. LCD data on low nibble of any port, LCD command lines on any port bits (even different port).

Schematic of LCD connection (PDF)

Declarations required in main program:

LCDtris equ TRISA ; LCD data on low nibble of portA
LCDport equ PORTA
#define LCD_ENtris TRISB,0x01 ; EN on portB,1
#define LCD_EN PORTB,0x01
#define LCD_RStris TRISB,0x02 ; RS on portB,2
#define LCD_RS PORTB,0x02
#define LCD_RWtris TRISB,0x03 ; RW on portB,3
#define LCD_RW PORTB,0x03

CONSTANT BASE = 0x0C ; 16F84 base address of user file registers

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcde.asm"

m_lcde_bf.asm

V4.03e  (17.08.2004)
7 wires, 4 bit LCD interface
Extended m_lcde.asm which reads busy flag of LCD (bi-directional communication between controller and LCD)

Schematic of LCD connection (PDF)

Declarations required in main program:

LCDtris equ TRISA ; LCD data on low nibble of portA
LCDport equ PORTA
#define LCD_ENtris TRISB,0x01 ; EN on portB,1
#define LCD_EN PORTB,0x01
#define LCD_RStris TRISB,0x02 ; RS on portB,2
#define LCD_RS PORTB,0x02
#define LCD_RWtris TRISB,0x03 ; RW on portB,3
#define LCD_RW PORTB,0x03

CONSTANT BASE = 0x0C  ; 16F84 base address of user file registers
FLAGreg equ BASE+d'7' ; general flag register
#define LCDbusy FLAGreg,0x6  ; LCD busy flag
#define LCDcflag FLAGreg,0x7 ; LCD command/data flag

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcde_bf.asm"

m_lcdexbf.asm

V4.23e  (17.08.2004)
7 wires, 4 bit LCD interface
Basically the same as m_lcde_bf.asm, but with the ability to define your own characters (max. 8) in macro LCDspecialChars. Bi-directional communication, reads busy flag of LCD.

Schematic of LCD connection (PDF)

For demo-programs or complete applications, refer to 'Projects'   [click here]
 

LCD Display Conversion Routines   [Toc] [Top]

m_lcdv08.asm 

V1.02  (20.08.2004)
8 bit binary to decimal conversion routine for LCD output, stringent for any numeric display output or interaction.

Declarations required in main program:

CONSTANT BASE = 0x0C  ; 16F84 base address of user file registers
FLAGreg equ BASE+d'4' ; general flag register
LO equ BASE+d'5'
LO_TEMP set BASE+d'6'
#define BCflag FLAGreg,0x0 ; blank checker for preceding zeros

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcd.asm"
#include "..\m_lcdv08.asm"

; Call of implemented procedure with:
LCDval_08 ; result is stored in register LO

m_lcdv16.asm

V1.02  (20.08.2004)
16 bit binary to decimal conversion routine for LCD output, stringent for any numeric display output or interaction.

Declarations required in main program:

CONSTANT BASE = 0x0C  ; 16F84 base address of user file registers
FLAGreg equ BASE+d'4' ; general flag register
LO equ BASE+d'5'
HI equ BASE+d'6'
LO_TEMP set BASE+d'7'
HI_TEMP set BASE+d'8'
#define BCflag FLAGreg,0x0 ; blank checker for preceding zeros

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcd.asm"
#include "..\m_lcdv16.asm"

; Call of implemented procedure with:
LCDval_16 ; result is stored in registers HI, LO

m_lcdb08.asm

V1.00  (20.08.2004)
8 bit binary LCD output routine for debugging of registers and bitstreams, e.g. to visualize the binary output of an A/D converter to check the magnitude of its LSB toggling due to digital quantization and/or noise.

Declarations required in main program:

CONSTANT BASE = 0x0C  ; 16F84 base address of user file registers
b08_cnt equ BASE+d'4' ; counter
LO equ BASE+d'5'
LO_TEMP set BASE+d'6'

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcd.asm"
#include "..\m_lcdb08.asm"

; Call of implemented procedure with:
LCDbin_08 ; value in register LO, output to LCD

m_lcdb16.asm

V1.00  (20.08.2004)
16 bit binary LCD output routine for debugging of registers and bitstreams, e.g. to visualize the binary output of an A/D converter to check the magnitude of its LSB toggling due to digital quantization and/or noise.

Declarations required in main program:

CONSTANT BASE = 0x0C  ; 16F84 base address of user file registers
b16_cnt equ BASE+d'4' ; counter
LO equ BASE+d'5'
HI equ BASE+d'6'
LO_TEMP set BASE+d'7'
HI_TEMP set BASE+d'8'

#include "..\m_bank.asm"
#include "..\m_wait.asm"
#include "..\m_lcd.asm"
#include "..\m_lcdb16.asm"

; Call of implemented procedure with:
LCDbin_16 ; value in registers HI, LO, output to LCD

For demo-programs or complete applications, refer to 'Projects'   [click here]
 

Serial Communication Modules (RS232)   [Toc] [Top]

Software-based RS232 communication for all Microchip PIC MCUs. The routines handle all aspects of RS232 transmission and reception, based on busy waits. The MCU port for RS232 transmission can be selected freely by the user, provided it is an active digital push/pull port. The MCU port for RS232 reception is limited to PORTB,0 due to its own interrupt flag.

Note that for external interrupts, such as the RB0/INT pin or PORTB change interrupt, the latency will be three to four instruction cycles. The exact latency depends on when the interrupt occurs. The latency is the same for both one and two cycle instructions.
(=> see Microchip PIC16/17 Microcontroller Databook.)

For those, who are not familiar with interfacing a PIC to the RS232 using a MAX232 :   RS232-Interface.pdf   (9.7 kB)

m_rs096.asm

V1.03  (2010/05/04)
Completely software handled RS232 Interface for interrupt featured PICs (PIC16C84, PIC16F84,...).
Specifications: 9600 baud, 8 bit, no parity, 1 stopbit (9600-8-N-1) @ 4 MHz / 1 MIPS

Declarations required in main program:

#define TXport PORTA,0x00 ; RS232 output port, could be
#define TXtris TRISA,0x00 ; any active push/pull port
; RS232 input port is RB0, because of its own interrupt flag

CONSTANT BASE = 0x0C ; 16F84 base address of user file registers
TXD equ BASE+d'7' ; TX data register, for transmission
RXD equ BASE+d'8' ; RX data register, for storage

#include "..\m_bank.asm"
#include "..\m_rs096.asm"

; Call of implemented procedures with:
; RS232init ; initialization
; SEND 'c' ; sends character 'c'
; SENDw ; sends content of working register
; RECEIVE ; macro in ISR: receive from RS232, store in register RXD

m_rs012.asm V1.03  (2010/05/04)
Functionality as m_rs096.asm

Specifications: 1200 baud, 8 bit, no parity, 1 stopbit (1200-8-N-1) @ 4 MHz / 1 MIPS
m_rs024.asm V1.03  (2010/05/04)
Functionality as m_rs096.asm

Specifications: 2400 baud, 8 bit, no parity, 1 stopbit (2400-8-N-1) @ 4 MHz / 1 MIPS
m_rs048.asm V1.03  (2010/05/04)
Functionality as m_rs096.asm

Specifications: 4800 baud, 8 bit, no parity, 1 stopbit (4800-8-N-1) @ 4 MHz / 1 MIPS
m_rs192.asm V1.03  (2010/05/04)
Functionality as m_rs096.asm

Specifications: 19200 baud, 8 bit, no parity, 1 stopbit (19200-8-N-1) @ 4 MHz / 1 MIPS
m_rs7n1.asm V1.03  (2010/05/04)
Functionality as m_rs096.asm

Developed for an old and heavy matrix needle printer with RS232 Interface.
Specifications: 9600 baud, 7 bit, no parity, 1 stopbit (9600-7-N-1) @ 4 MHz / 1 MIPS

For demo-programs or complete applications, refer to 'Projects'   [click here]
 

Notes on Modules   [Toc] [Top]

General Recommendations   [Toc] [Top]

Known Limitations of MPLAB IDE   [Toc] [Top]

Technical Hints   [Toc] [Top]

specifying cycle-accurate periods

The Stopwatch
having been reset at 'bsf TXport' and run to the 'nop' statement. The latency of the 'WAITX d73,d2' statement within this setup (4 MHz clock, PIC16F84) turns out to be approximately 150 ms.


 

Last updated: 2010/05/14

[Toc] [Top]
 

If you see only this page in your browser window,
click here
to get the entire site.