Enzo Gomez [enzo.gomez at ieee.org] says:
I have this code to connect with DS1990A, an electronic key (its just a ROM device). It was originally written for PIC 16F84
The code is C code, compiled great with C2C compiler, from Pavel Baranov.
http//www.geocities.com/SiliconValley/Network/3656/c2c/c.html
a shareware compiler.
// Interfaz con dispositivos DALLAS
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define Dallas_Port PORTB // Define el puerto de datos de DS1990A
#define Dallas_Tris TRISB // Define el puerto de configuración
#define Dallas_Pin 7 // para acceder a la memoria DS1990A.
asm {
DALLAS_PORT EQU PORTB
DALLAS_PIN EQU 7
}
char SN_Dallas[8]; // Para guardar el Serial Number de Dalas
// 0x01 + SN[6] + CRC[1]
char CRC_Dallas; // Para el chequeo del CRC.
//Configura el puerto como salida
void SetOut_Dallas(void)
{
set_bit( STATUS, RP0 ); //Selecciona el banco de registros 1
clear_bit(Dallas_Tris, Dallas_Pin);
clear_bit( STATUS, RP0 ); //Selecciona el banco de registros 0
}
//Configura el puerto como entrada
void SetIn_Dallas(void)
{
set_bit( STATUS, RP0 ); //Selecciona el banco de registros 1
set_bit(Dallas_Tris, Dallas_Pin);
clear_bit( STATUS, RP0 ); //Selecciona el banco de registros 0
}
//Pone un cero a la salida del pin DS1990A
void Set0_Dallas(void)
{
clear_bit( Dallas_Port, Dallas_Pin);
}
// Transmite un bit a DS1990A.
void Write_Dallas(char bit)
{
// Pone un CERO a la salida
// (pulso de comienzo).
clear_bit( Dallas_Port, Dallas_Pin);
SetOut_Dallas(); // Pone el puerto como salida.
delay_us(17); // Espera 15us min
if (bit)
{
// si llega aqui debe transmitir un UNO
SetIn_Dallas(); // Configura puerto como entrada para que
// suba en tensión automáticamente.
delay_us(50); // Espera 50us (este tiempo debe completar
// los 60us como mínimo).
}
else
{
delay_us(100); // Espera el tiempo que es como máximo 120us
SetIn_Dallas(); // Pone el puerto como entrada.
}
// Espera 1us (tREC) en el return
}
//Transmite un Byte al dispositivo
void WriteByte_Dallas(char Data)
{
char n;
for(n=0; n<8; n++)
{
if (Data & 0x01)
{
// Pone un CERO a la salida
// (pulso de comienzo).
clear_bit( Dallas_Port, Dallas_Pin);
set_bit( STATUS, RP0 ); //Selecciona el banco de registros 1
clear_bit(Dallas_Tris, Dallas_Pin); // Pone un cero a la salida
set_bit(Dallas_Tris, Dallas_Pin); // Pone el puerto en entrada
clear_bit( STATUS, RP0 ); //Selecciona el banco de registros 0
delay_us(103); // Espera 103us (este tiempo debe completar
// los 120us como mínimo).
}
else
{
SetOut_Dallas(); // Pone el puerto como salida.
clear_bit( Dallas_Port, Dallas_Pin);// Pone un CERO a la salida
delay_us(100); // Espera 100us
SetIn_Dallas(); // Configura puerto como entrada para que
// suba en tensión automáticamente.
}
Data >>= 1;
}
}
//Lee el puerto de Dallas.
char ReadIn_Dallas(void)
{
asm {
clrw
btfsc DALLAS_PORT, DALLAS_PIN
movlw D'1'
return
}
}
//Lee un bit de la memoria Dallas.
char ReadBit_Dallas(void)
{
char Lectura;
// Pone un CERO a la salida
// (pulso de comienzo).
clear_bit( Dallas_Port, Dallas_Pin);
set_bit( STATUS, RP0 ); //Selecciona el banco de registros 1
clear_bit(Dallas_Tris, Dallas_Pin); // Configura como salida \
nop(); // espera... > Pulso de inicio
set_bit(Dallas_Tris, Dallas_Pin); // Configura como entrada /
clear_bit( STATUS, RP0 ); //Selecciona el banco de registros 0
nop(); // Espera para leer
nop();
nop();
nop();
nop();
Lectura = ReadIn_Dallas();
delay_us(60-18); // Espera para completar los 120us max
return Lectura; // Lee el pin
}
// Envia el pulso de Reset al bus 1-Wire, y devuelve
// true si recibe el pulso de presencia
char Reset_Dallas(void)
{
// Pone un CERO a la salida
// (pulso de RESET).
clear_bit( Dallas_Port, Dallas_Pin);
SetOut_Dallas(); // Pone el puerto en salida.
delay_us(255); // Espero 480us mínimo.
delay_us(225);
SetIn_Dallas(); // Pone el puerto como entrada y
// espera a que la DS1990A ponga un cero.
delay_us(75); // Espera un mínimo de 15us+60us.
if ( ReadIn_Dallas() ) // Si lee un UNO es que no hay memoria colgada del
return false; // bus.
delay_us(165); // Espera para completar los 480us (peor caso)
delay_us(240);
return true;
}
// Calcula el CRC8 acumulado
char CRC8_Dallas(char Data)
{
char i, f;
for (i = 0; i < 8; i++)
{
f = 1 & (Data ^ CRC_Dallas);
CRC_Dallas >>= 1;
Data >>= 1;
if (f) CRC_Dallas ^= 0x8c; // b10001100 es la palabra del CRC (x8 + x5 + x4 + 1)
// 7..43..0 junto con el 1 aplicado a f.
}
return CRC_Dallas;
}
//Chequea el CRC de los datos recibidos
char CheckCRC()
{
char k;
CRC_Dallas = 0;
for (k = 0; k < 8; k++) CRC8_Dallas(SN_Dallas[k]);
return !CRC_Dallas;
}
// Lee un byte desde el dispositivo
char ReadByte_Dallas()
{
char n, Byte_Dallas;
for (n=0; n<8; n++)
{
Byte_Dallas >>= 1;
if ( ReadBit_Dallas() ) Byte_Dallas |= 0x80; // LSB first!
nop();
}
return Byte_Dallas;
}
//Lee el código de la memoria y lo guarda en la variable
//global SN_Dallas
char ReadSN_Dallas(void)
{
//Escribe el comando de lectura de ROM (Read ROM = 0x33)
WriteByte_Dallas(0x33); // 0x33 - Read ROM
for(CRC_Dallas = 0; CRC_Dallas < 8; CRC_Dallas++)
SN_Dallas[CRC_Dallas] = ReadByte_Dallas();
return CheckCRC();
}
// Inicializa todo lo necesario
// para manejar las llaves Dallas
// (pines, interrupciones)
void Init_Dallas( void )
{
//Inicializacion del HW del uC.
set_bit( STATUS, RP0 ); //Seleccciona el banco de registros 1.
set_bit( Dallas_Tris, Dallas_Pin ); // Configura el pin para entrada.
set_bit( OPTION_REG, 7 ); //Deshabilita las pull-up del puerto B.
clear_bit( STATUS, RP0 ); //Seleccciona el banco de registros 0.
set_bit( INTCON, 3 ); // Habilita las interrupciones por cambios en puerto B.
}
////////////////////////////////////////////////////////////////////////
/*
main()
{
Init_Dallas();
Reset_Dallas();
ReadSN_Dallas();
} /* */
Questions: