You are on page 1of 48

Example to drive 8 LEDS

/************************************************
* *
* COPYRIGHT (c) Blitzlogic Sdn. Bhd. *
* Author : Abraham Wong 21/1/2000 *
* *
* example of using WHILE loop construct *
* to drive 8 LEDS connected to port B *
* *
************************************************/

#include <16c84.h>

#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */

#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No
Power-up Timer */

#byte port_b=6 /* define the location of register


port_b */

main(){

byte cnt; value;

set_tris_b(0); /* set port_b to be outputs */


port_b = 0; /* initialize All port_b outp/uts to
be zero */
value = 0x01;

while( TRUE )
{ /* forever loop using WHILE construct */
cnt = 0;

while ( cnt<8 )
{
port_b = value;
DELAY_MS(1000);
value = value << 1; /* shift left will put
0x01, 0x02, 0x04, 0x08, 0x10 */
cnt++; /* 0x20, 0x40, 0x80 to port_b */
}
}
}

Dieu khien led 7 doan


Example to drive two 7-Segment
LEDs
/****************************************
*
* COPYRIGHT (c) Blitzlogic Sdn. Bhd.
* Author : Abraham Wong 21/1/2000
*
* example of using FOR loop to drive
* two 7-Segment LEDs

****************************************/

#include <16c84.h>

#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */


#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No
Power-up Timer */

#byte port_b=6 /* define the location of register


port_b */
#byte port_a=5 /* define the location of register
port_b */
byte CONST LED_MAP[10] =
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

main(){
byte cnt, right,num ;

set_tris_b(0); /* set port_b as outputs */


set_tris_a(0); /* set port_a as output */
port_b = 0; /* ZERO port_a & port_b */
port_a = 0;

for( ;; ){
for (right=1;right<3;right++){
port_a = right;
for (cnt=0;cnt<10;cnt++){
port_b = LED_MAP[cnt];
DELAY_MS(1000); /* one second delay */

}
}
}
}

Ket noi voi matran 5x7


Example to drive 5 x 7 Matrix LED
/************************************************
* *
* COPYRIGHT (c) Blitzlogic Sdn. Bhd. *
* Author : Abraham Wong 21/1/2000 *
* *
* example of driving 5 x 7 Matrix LEDs *
* *
************************************************/

#include <16c84.h>

#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock


*/
#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No
Power-up Timer */

#byte port_b=6 /* define the location of register


port_b */
#byte port_a=5 /* define the location of register
port_b */

char const pat[5]={0x3f,0x02,0x04,0x02,0x3f};

main(){
char cnt, col;

set_tris_b(0); /* set port_b as outputs */


set_tris_a(0); /* set port_a as output */

port_b = 0; /* ZERO port_a & port_b */


port_a = 0;

for( ;; )
{
col = 1;
for(cnt = 0;cnt < 5;cnt++)
{
port_b = pat[cnt];
port_a = col;

delay_ms(1);

col<<=1;
}
}
}

Ket noi voi ma tran 16x1


EXAMPLE to use KBD.C and LCD.C
drivers
/////////////////////////////////////////////////////
////////////////////
//// EX_LCDKB.C
////
////
////
//// This program uses both the KBD.C and LCD.C
drivers to allow ////
//// keypad entry and LCD display. All keys are
echoed except * ////
//// that will clear the display. Either the
kbd_getc or lcd_putc ////
//// may be replaced with getc or putc to use just
one device with ////
//// the RS-232.
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
////////////////////

#include <16F84.H>
#fuses XT,NOPROTECT,NOWDT

#use delay(clock=4000000)
#include
#include

main() {
char k;

lcd_init();
kbd_init();

lcd_putc("\fReady...\n");

while (TRUE) {
k=kbd_getc();
if(k!=0)
if(k=='*')
lcd_putc('\f');
else
lcd_putc(k);
}
}

Driver for common LCD modules


/////////////////////////////////////////////////////
///////////////////////
//// LCD.C
////
//// Driver for common LCD modules
////
////
////
//// lcd_init() Must be called before any other
function. ////
////
////
//// lcd_putc(c) Will display c on the next
position of the LCD. ////
//// The following have special
meaning: ////
//// \f Clear display
////
//// \n Go to start of second
line ////
//// \b Move back one position
////
////
////
//// lcd_gotoxy(x,y) Set write position on LCD
(upper left is 1,1) ////
////
////
//// lcd_getc(x,y) Returns character at position
x,y on LCD ////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
///////////////////////

// As defined in the following structure the pin


connection is as follows:
// B0 enable
// B1 rs
// B2 rw
// B4 D4
// B5 D5
// B6 D6
// B7 D7
//
// LCD pins D0-D3 are not used and PIC B3 is not
used.

struct lcd_pin_map { // This


structure is overlayed
boolean enable; // on to an I/O
port to gain
boolean rs; // access to the
LCD pins.
boolean rw; // The bits are
allocated from
boolean unused; // low order up.
ENABLE will
int data : 4; // be pin B0.
} lcd;

#byte lcd = 6 // This puts the


entire structure
// on to port B
(at address 6)

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2


lines
#define lcd_line_two 0x40 // LCD RAM address for
the second line

byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type <<


2), 0xc, 1, 6};
// These bytes need to
be sent to the LCD
// to start it up.

// The following are


used for setting
// the I/O port
direction register.

STRUCT lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; //


For write mode all pins are out
STRUCT lcd_pin_map const LCD_READ = {0,0,0,0,15}; //
For read mode data pins are in

byte lcd_read_byte() {
byte low,high;

set_tris_b(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_b(LCD_WRITE);
return( (high<<4) | low);
}

void lcd_send_nibble( byte n ) {


lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}

void lcd_send_byte( byte address, byte n ) {


lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

void lcd_init() {
byte i;

set_tris_b(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}

void lcd_gotoxy( byte x, byte y) {


byte address;

if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {


switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}

char lcd_getc( byte x, byte y) {


char value;

lcd_gotoxy(x,y);
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}

Generic keypad scan driver


/////////////////////////////////////////////////////
//////////////////////
//// KBD.C
////
//// Generic keypad scan driver
////
////
////
//// kbd_init() Must be called before any other
function. ////
////
////
//// c = kbd_getc(c) Will return a key value if
pressed or /0 if not ////
//// This function should be called
frequently so as ////
//// not to miss a key press.
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
//////////////////////

////////////////// The following defines the keypad


layout on port B
#byte kbd = 6 // Keypad is connected to port B
(address 6)

//Keypad connection: (for example column 0 is B2)


// Bx:

#ifdef
blue_keypad /////////////////////////////////////
For the blue keypad
#define COL0 (1 << 2)
#define COL1 (1 << 3)
#define COL2 (1 << 6)

#define ROW0 (1 << 4)


#define ROW1 (1 << 7)
#define ROW2 (1 << 1)
#define ROW3 (1 << 5)

#else ///////////////////////////////////////////////
/// For my keypad
#define COL0 (1 << 6)
#define COL1 (1 << 2)
#define COL2 (1 << 3)

#define ROW0 (1 << 4)


#define ROW1 (1 << 5)
#define ROW2 (1 << 1)
#define ROW3 (1 << 7)
#endif

#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)


#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2)

// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};

#define KBD_DEBOUNCE_FACTOR 33 // Set this number


to apx n/333 where
// n is the number
of times you expect
// to call kbd_getc
each second

void kbd_init() {
#ifdef __PCM__
port_b_pullups(true); // If not PCM be sure to
use external pullups
#endif
}

char kbd_getc( ) {
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;

byte kchar;
byte row;

kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
switch (col) {
case 0 : set_tris_b(ALL_PINS&~COL0);
kbd=~COL0&ALL_PINS;
break;
case 1 : set_tris_b(ALL_PINS&~COL1);
kbd=~COL1&ALL_PINS;
break;
case 2 : set_tris_b(ALL_PINS&~COL2);
kbd=~COL2&ALL_PINS;
break;
}

if(kbd_down) {
if((kbd & (ALL_ROWS))==(ALL_ROWS)) {
kbd_down=false;
kchar=last_key;
last_key='\0';
}
} else {
if((kbd & (ALL_ROWS))!=(ALL_ROWS)) {
if((kbd & ROW0)==0)
row=0;
else if((kbd & ROW1)==0)
row=1;
else if((kbd & ROW2)==0)
row=2;
else if((kbd & ROW3)==0)
row=3;
last_key =KEYS[row][col];
kbd_down = true;
} else {
++col;
if(col==3)
col=0;
}
}
kbd_call_count=0;
}
set_tris_b(ALL_PINS);
return(kchar);
}
Giao tiep voi ltc1298

Driver for LTC1298 A/D Converter


/
*****************************************************
************************
*
*
* Driver for LTC1298 A/D
Converter *
*
*
* adc_init()
Call after power up *
*
*
* value = read_analog( channel )
Read a analog channel *
*
channel is 0 or 1 *
*
*
* convert_to_volts( value, string )
Fills in string with *
*
the true voltage in *
*
the form 0.000 *
*
*
* (C) Copyright 1996,1997 Custom Computer
Services *
*
*

*****************************************************
************************/
#ifndef ADC_CS

#define ADC_CLK PIN_B0


#define ADC_DOUT PIN_B1
#define ADC_DIN PIN_B2
#define ADC_CS PIN_B3

#endif

void adc_init() {
output_high(ADC_CS);
}

void write_adc_byte(byte data_byte, byte


number_of_bits) {
byte i;

delay_us(2);
for(i=0; i>1;
output_high(ADC_CLK);
delay_us(50);
output_low(ADC_CLK);
delay_us(50);
}
}

byte read_adc_byte(byte number_of_bits) {


byte i,data;

data=0;
for(i=0;i<<8)|l);
}

void convert_to_volts( long int data, char volts[6])


{
byte i, d, div_h, div_l;
long int temp,div;

div=0x3330;

for(i=0;i<=4;i++) {
temp=data/div;
volts[i]=(byte)temp+'0';
if(i==0) {
volts[1]='.';
i++;
}
temp=div*(byte)temp;
data=data-temp;
div=div/10;
}
volts[i]='\0';
}
Example to read two A/D Channels of
LTC1298
/////////////////////////////////////////////////////
////////////////////
//// EX_AD12.C
////
////
////
//// This program will read both A/D channels and
display the ////
//// results as both a voltage and raw hex number
over the RS-232. ////
//// A reading is taken every second.
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
////////////////////

#include <16F84.H>

#fuses HS,NOPROTECT,NOWDT

#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)

#include

void display_data( long int data ) {


char volt_string[6];

convert_to_volts( data, volt_string );


printf(volt_string);
printf(" (%4lX)",data);
}

main() {
long int value;

adc_init();

printf("Sampling:\r\n");
do {
delay_ms(1000);

value = read_analog(0);
printf("\n\rCh0: ");
display_data( value );

value = read_analog(1);
printf(" Ch1: ");
display_data( value );

} while (TRUE);

I2C Library Sub-Routines for 24LC02


/////////////////////////////////////////////////////
//////////////////////
//// /
///
//// Library for a MicroChip 24LC02B configured for
a x8 org ////
////
////
//// init_ext_eeprom(); Call before the other
functions are used ////
////
////
//// write_ext_eeprom(a, d); Write the byte d to
the address a ////
////
////
//// d = read_ext_eeprom(a); Read the byte d from
the address a ////
////
////
//// The main program may define eeprom_sda
////
//// and eeprom_scl to override the defaults below.
////
////
////
//// /
///
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
//////////////////////

#ifndef EEPROM_SDA

#define EEPROM_SDA PIN_B7


#define EEPROM_SCL PIN_B6

#endif

#use i2c(master,sda=EEPROM_SDA, scl=EEPROM_SCL)

#define EEPROM_ADDRESS byte


#define EEPROM_SIZE 256

void init_ext_eeprom() {
output_low(eeprom_scl);
output_high(eeprom_sda);
}

void write_ext_eeprom(byte address, byte data) {

i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(11);
}
byte read_ext_eeprom(byte address) {
byte data;

i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
return(data);
}

I2C EEPROM 24LC02 EXAMPLE

I2C EEPROM 24LC02 EXAMPLE


/////////////////////////////////////////////////////
////////////////////
//// EX_EXTEE.C
////
////
////
//// This program uses the 24xx or 93xx external
EEPROM drivers to ////
//// read and write to an external serial EEPROM.
z ////
////
////
//// Change the #include <9356.C> to any of the
other drivers to ////
//// test other parts. Note each driver defines
EEPROM_ADDRESS ////
//// indicate 8 or 16 bit addresses.
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
////////////////////

#include <16F84.H>
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)

#include
#include <2402.C>

main() {

byte value,cmd;
EEPROM_ADDRESS address;
init_ext_eeprom();

do {
do {
printf("\r\nRead or Write: ");
cmd=getc();
cmd=toupper(cmd);
putc(cmd);
} while ( (cmd!='R') && (cmd!='W') );

printf("\n\rLocation: ");

#if sizeof(EEPROM_ADDRESS)==1
address = gethex();
#else
#if EEPROM_SIZE>0xfff
address = gethex();
#else
address = gethex1();
#endif
address = (address<<8)+gethex();
#endif

if(cmd=='R')
printf("\r\nValue:
%X\r\n",READ_EXT_EEPROM( address ) );

if(cmd=='W') {
printf("\r\nNew value: ");
value = gethex();
printf("\n\r");
WRITE_EXT_EEPROM( address, value );
}
} while (TRUE);

Stop Watch function via RTCC &


interrupts
/////////////////////////////////////////////////////
////////////////////
//// EX_STWT.C
////
////
////
//// This program uses the RTCC (timer0) and
interrupts to keep a ////
//// real time seconds counter. A simple stop watch
function is ////
//// then implemented.
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
//// ///
/
/////////////////////////////////////////////////////
////////////////////

#include <16F84.H>

#fuses XT,NOWDT,NOPROTECT

#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)

#define INTS_PER_SECOND 76 //
(20000000/(4*256*256))

byte seconds; // A running seconds counter


byte int_count; // Number of interrupts left
before a second has elapsed

#int_rtcc // This function


is called every time
clock_isr() { // the RTCC
(timer0) overflows (255->0).
// For this
program this is apx 76 times
if(--int_count==0) { // per second.
++seconds;
int_count=INTS_PER_SECOND;
}
}

main() {

byte start;

int_count=INTS_PER_SECOND;
set_rtcc(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts(RTCC_ZERO);
enable_interrupts(GLOBAL);

do {

printf("Press any key to begin.\n\r");


getc();
start=seconds;
printf("Press any key to stop.\n\r");
getc();
printf("%u seconds.\n\r",seconds-start);

} while (TRUE);

}
Example to create a pulse via
RTCC( timer0 )
/////////////////////////////////////////////////////
////////////////////
//// EX_PULSE.C
////
////
////
//// This program uses the RTCC (timer0) to time a
single pulse ////
//// input to the PIC.
////
////
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
////////////////////

#include <16F84.H>

#fuses XT,NOPROTECT,NOWDT

#include

#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)

char get_scale() {
char scale;

do {
printf("\n\rPress S for short or L for long: ");
scale = getc();
scale = toupper(scale);
} while ( (scale!='S') && (scale!='L') );

return(scale);
}

void wait_for_low_to_high() {

while(input(PIN_B1)) ; /* if it's high, wait


for a low */

delay_us(3); /* account for fall


time */

while(!input(PIN_B1)); /* wait for signal to


go high */
}

void wait_for_low() {
delay_us(3); /* account for rise
time */

while(input(PIN_B1)); /* wait for signal to


go high */
}

main() {

char scale;
byte time;

do {
scale = get_scale();

if(scale=='S')
setup_counters( RTCC_INTERNAL,
RTCC_DIV_64 );
else
setup_counters( RTCC_INTERNAL,
RTCC_DIV_256 );

printf("\n\rWaiting...\n\r");

wait_for_low_to_high();
set_rtcc(0);
wait_for_low();
time = get_rtcc();

printf("Counter value: %2X\n\n\r", time);

} while (TRUE);
}
Library for Dallas 1621 Temperature
chip
/////////////////////////////////////////////////////
//////////////////////
////
////
//// Library for a Dallas 1621 Temperature chip
////
////
////
//// init_temp(); Call before the other
functions are used ////
////
////
//// d = read_temp(); Read the temerature in
degrees (0-255) ////
////
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
//////////////////////

#use i2c(master,sda=PIN_B7, scl=PIN_B6)

void temp_config(byte data) {

i2c_start();
i2c_write(0x90);
i2c_write(0xac);
i2c_write(data);
i2c_stop();
delay_ms(11);
}

void init_temp() {
output_high(PIN_B7);
output_high(PIN_B6);
i2c_start();
i2c_write(0x90);
i2c_write(0xee);
i2c_stop();
temp_config(8);
}

byte read_temp() { ////// Returns degrees F


(0-255)
byte datah,datal;
long data;

i2c_start();
i2c_write(0x90);
i2c_write(0xaa);
i2c_start();
i2c_write(0x91);
datah=i2c_read();
datal=i2c_read(0);
i2c_stop();
data=datah;
data=data*9;
if((datal&0x80)!=0)
data=data+4;
data=(data/5)+32;
datal=data;
return(datal);
}
Example to Read temperature using
the DS1621
/////////////////////////////////////////////////////
//////////////////////
////
////
//// EX_TEMP.C
////
////
////
//// Reads temperature using the DS1621 and sends
it over the RS232 ////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
//////////////////////

#include <16F84.H>

#use delay(clock=4000000)

#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)

#include

main() {
byte value;

init_temp();

do {
value = read_temp();
printf("%u\r\n",value);
delay_ms(1000);
}while (TRUE);
}

74595 Library Routine to expand no.


of output lines
/////////////////////////////////////////////////////
//////////////////////
//// Library for a 74595 Expanded Output Chip
////
////
////
//// Any number of these chips may be connected in
serise to get ////
//// 8 additional outputs per chip. The cost is 3
I/O pins for ////
//// any number of chips.
////
////
////
//// write_expanded_outputs(eo); Writes the array
eo to the chips ////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
//////////////////////

#IFNDEF EXP_OUT_ENABLE

#define EXP_OUT_ENABLE PIN_B0


#define EXP_OUT_CLOCK PIN_B1
#define EXP_OUT_DO PIN_B2
#define NUMBER_OF_74595 1
#ENDIF

void write_expanded_outputs(byte* eo) {


byte i;

output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);

for(i=1;i<=NUMBER_OF_74595*8;++i) { // Clock out


bits from the eo array
if((*(eo+(NUMBER_OF_74595-1))&0x80)==0)
output_low(EXP_OUT_DO);
else
output_high(EXP_OUT_DO);
shift_left(eo,NUMBER_OF_74595,0);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
}
output_high(EXP_OUT_ENABLE);
}

74165 Library Routine to expand no.


of input lines
/////////////////////////////////////////////////////
//////////////////////
//// Library for a 74165 Expanded Input Chip
////
////
////
//// Any number of these chips may be connected in
series to get ////
//// 8 additional inputs per chip. The cost is 3
I/O pins for ////
//// any number of chips.
////
////
////
//// read_expanded_inputs(ei); Reads the array ei
from the chips ////
////
////
/////////////////////////////////////////////////////
//////////////////////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
//// This source code may only be used by licensed
users of the CCS C ////
//// compiler. This source code may only be
distributed to other ////
//// licensed users of the CCS C compiler. No other
use, reproduction ////
//// or distribution is permitted without written
permission. ////
//// Derivative programs created using this software
in object code ////
//// form are not restricted in any way.
////
/////////////////////////////////////////////////////
///////////////////////

#IFNDEF EXP_IN_ENABLE

#define EXP_IN_ENABLE PIN_B3


#define EXP_IN_CLOCK PIN_B4
#define EXP_IN_DI PIN_B5
#define NUMBER_OF_74165 1

#ENDIF

void read_expanded_inputs(byte *ei) {


byte i;

output_high(EXP_IN_CLOCK);
output_low(EXP_IN_ENABLE); // Latch all inputs
output_high(EXP_IN_ENABLE);
for(i=1;i<=NUMBER_OF_74165*8;++i) { // Clock
in bits to the ei structure
shift_left(ei,NUMBER_OF_74165,input(EXP_IN_DI));
output_low(EXP_IN_CLOCK);
output_high(EXP_IN_CLOCK);
}
output_low(EXP_IN_ENABLE);
}

Example to expand number of I/O


using 74165 & 74595
/////////////////////////////////////////////////////
////////////////////
//// EX_EXPIO.C
////
////
////
//// This program shows how to use the 74165.C
and 74595.C ////
//// libraries for extended input and output.
////
////
////
//// When button S1 is pushed, LED 1 will toggle
green. Button ////
//// S2 will toggle LED 2. However, when both
buttons are pushed, ////
//// LED 3 will toggle green.
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
/////////////////////
#ifdef __PCB__
#include <16C56.H>
#else
#include <16C74.H>
#endif

#include <74595.C>
#include <74165.C>

main() {
byte data;

do {
read_expanded_inputs (&data);

data |= 0xF8; //Force


the unused input bits on
data -= (!(data&0x01)&!(data&0x02))<<2; //Turn
on bit 2 it both inputs are

//toggled
write_expanded_outputs (&data);
} while (TRUE);
}
TW523 X10 Driver
/////////////////////////////////////////////////////
/////////////////////
//// TW523 X10 Driver
////
////
////
//// x10_write(house_code,key_code) Send a data
burst, house_code ////
//// must be 'A'
to 'P' and ////
//// key_code is
0-1F ////
////
////
//// x10_read( house_code, key_code) Waits for and
reads the next ////
//// data burst.
////
////
////
//// x10_data_ready() Returns true
if a data burst ////
//// is starting.
Be sure to call ////
//// faster than
1khz in order not ////
//// to miss any
data. ////
//// Connect B0 to TW523 pin 1
////
//// B1 3
////
//// B2 4
////
//// GND 2
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
/////////////////////

#ifndef X10_ZERO_CROSS

#define X10_ZERO_CROSS PIN_B0


#define X10_TO_PIC PIN_B1
#define X10_FROM_PIC PIN_B2

#endif

char const X10_HOUSE_CODES[16] =


{'M','N','O','P','C','D','A','B','E',

'F','G','H','K','L','I','J'};
byte const X10_KEY_CODES[16] =
{13,14,15,16,3,4,1,2,5,6,7,8,11,12,9,10};
void wait_for_zero_cross() {

if(input(X10_ZERO_CROSS))
while(input(X10_ZERO_CROSS)) ;
else
while(!input(X10_ZERO_CROSS)) ;
}

void x10_write_bits(byte data, byte n, byte start) {


byte i;
boolean the_bit;

for(i=1;i<=n;++i) {
wait_for_zero_cross();
the_bit=shift_right(&data,1,0);
output_bit(X10_FROM_PIC, the_bit);
delay_ms(1);
output_low(X10_FROM_PIC);
if(start==0) {
wait_for_zero_cross();
output_bit(X10_FROM_PIC, !the_bit);
delay_ms(1);
output_low(X10_FROM_PIC);
}
}
}

void x10_write(byte house_code, byte key_code) {


byte i;

i=0;
while (X10_HOUSE_CODES[i]!=house_code)
i++;
house_code=i;
if(key_code<16) {
i=0;
while (X10_KEY_CODES[i]!=key_code)
i++;
key_code=i;
}
x10_write_bits(7,4,1);
x10_write_bits(house_code,4,0);
x10_write_bits(key_code,5,0);
x10_write_bits(0,6,1);
}

byte x10_data_ready() {
port_b_pullups(TRUE);
return(!input(X10_TO_PIC));
}

byte x10_read_bits(byte n) {
byte data,i;

for(i=1;i<=n;++i) {
wait_for_zero_cross();
delay_us(300);
shift_right(&data,1,input(X10_TO_PIC));
wait_for_zero_cross();
delay_us(300);
}
data>>=8-n;
return(data);
}

void x10_read(byte *house_code,byte *key_code) {

port_b_pullups(TRUE);
x10_read_bits(2);
*house_code=x10_read_bits(4);
*house_code=X10_HOUSE_CODES[*house_code];
*key_code=x10_read_bits(5);
if(*key_code<16)
*key_code=X10_KEY_CODES[*key_code];
}

X10 TO RS232 INTERFACE EXAMPLE


/////////////////////////////////////////////////////
////////////////////
//// EX_X10.C
////
////
////
//// This program interfaces a X10 TW523 unit to RS-
232. This ////
//// program will accept and send three character
codes of the ////
//// form xyy where x is A-P and yy is 00-1F.
////
//// Key codes 00-0F are translated to the key
number. ////
////
////
//// A * is sent to indicate transmition was aborted
due to ////
//// a collision. A > is sent when reception begins
to reduce ////
//// the chance of attempting to transmit during
reception. ////
////
////
//// Connect B0 to TW523 pin 1
////
//// B1 3
////
//// B2 4
////
//// GND 2
////
////
////
//// For a 40 pin part such as the 16C74 add jumpers
from ////
//// 8 to 11, 7 to 12, and change the #USE RS232 to:
////
//// #use rs232(baud=9600, xmit=PIN_C6,
rcv=PIN_C7) ////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
////////////////////

#include <16F84.H>

#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)

#fuses XT,NOPROTECT,NOWDT

#include < x10.c >


#include < input.c >

main() {
char house_code;
byte key_code;

printf("Online\n\r");

while (TRUE) {

if(kbhit()) {
house_code = getc();
if((house_code>='A') && (house_code<='P')) {
putc(house_code);
key_code=gethex();
x10_write(house_code,key_code);
x10_write(house_code,key_code);
}
}

if(x10_data_ready()) {
putc('>');
x10_read(&house_code,&key_code);
printf("%c%2X",house_code,key_code);
}
}
}

Sub-Routines for standard inputs


/////////////////////////////////////////////////////
///////////////////////
////
////
//// Routines for standard inputs
////
////
////
//// (C) Copyright 1996,1997 Custom Computer
Services ////
////
////
/////////////////////////////////////////////////////
///////////////////////
#include < CTYPE.H >

byte gethex1() {
char digit;

digit = getch();

putchar(digit);

if(digit<='9')
return(digit-'0');
else
return((toupper(digit)-'A')+10);
}

byte gethex() {
int lo,hi;

hi = gethex1();
lo = gethex1();
if(lo==0xdd)
return(hi);
else
return( hi*16+lo );
}

void get_string(char * s,int max) {


int len;
char c;

max--;
len=0;
do {
c=getc();
if(c==8) { // Backspace
if(len>0) {
len--;
putc(c);
putc(' ');
putc(c);
}
} else if ((c>=' ')&&(c<='~'))
if( len < max ) {
s[len++]=c;
putc(c);
}
} while(c!=13);
s[len]=0;
}

#ifdef _stdlib_

signed int get_int() {


char s[5];
signed int i;

get_string(s, 5);

i=atoi(s);
return(i);
}
signed long get_long() {
char s[7];
signed long l;

get_string(s, 7);
l=atol(s);
return(l);
}
#endif

You might also like