vi du pic dung c

56
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;

description

vài bài ví dụ về ứng dụng pic

Transcript of vi du pic dung c

Page 1: vi du pic dung c

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;

Page 2: vi du pic dung c

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

Page 3: vi du pic dung c

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 */

Page 4: vi du pic dung c

#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

Page 5: vi du pic dung c

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 */

Page 6: vi du pic dung c

#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

Page 7: vi du pic dung c

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. ////

Page 8: vi du pic dung c

//// //////// (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

////////////////////////////////////////////////////////////////////////////

Page 9: vi du pic dung c

//// 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

Page 10: vi du pic dung c

// 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

Page 11: vi du pic dung c

// the I/O port direction register.

STRUCT lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are outSTRUCT 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 ) {

Page 12: vi du pic dung c

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) {

Page 13: vi du pic dung 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 ////

Page 14: vi du pic dung c

//// 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)

Page 15: vi du pic dung c

#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);

Page 16: vi du pic dung c

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);}

Page 17: vi du pic dung c

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 *

Page 18: vi du pic dung c

* 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);

Page 19: vi du pic dung c

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 ////

Page 20: vi du pic dung 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");

Page 21: vi du pic dung c

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 //////// ////

Page 22: vi du pic dung c

//// 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);}

Page 23: vi du pic dung c

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

Page 24: vi du pic dung c

///////////////////////////////////////////////////////////////////////////// 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;

Page 25: vi du pic dung c

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

Page 26: vi du pic dung c

///////////////////////////////////////////////////////////////////////////// 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 counterbyte int_count; // Number of interrupts left before a second has elapsed

#int_rtcc // This function is called every timeclock_isr() { // the RTCC (timer0) overflows (255->0).

Page 27: vi du pic dung c

// 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);

}

Page 28: vi du pic dung c

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. //////// //////// ////

Page 29: vi du pic dung c

//// (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() {

Page 30: vi du pic dung c

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);}

Page 31: vi du pic dung c

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) ////

Page 32: vi du pic dung c

//// //////// //////// (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();

Page 33: vi du pic dung c

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);}

Page 34: vi du pic dung c

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);

Page 35: vi du pic dung c

}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

Page 36: vi du pic dung c

#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. ////

Page 37: vi du pic dung c

//// //////// 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);

Page 38: vi du pic dung c

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 //////// //////////////////////////////////////////////////////////////////////////////

Page 39: vi du pic dung c

#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);}

Page 40: vi du pic dung c

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. ////

Page 41: vi du pic dung c

//// //////// 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};

Page 42: vi du pic dung c

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);

Page 43: vi du pic dung c

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

Page 44: vi du pic dung c

///////////////////////////////////////////////////////////////////////////// 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) //////// ////

Page 45: vi du pic dung c

//// (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); } }

Page 46: vi du pic dung c

}

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();

Page 47: vi du pic dung c

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);}

Page 48: vi du pic dung c

signed long get_long() { char s[7]; signed long l;

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