dorinm
Joined: 07 Jan 2006 Posts: 38
|
Emulating a DS2401 on 16F88 |
Posted: Mon Feb 21, 2011 7:36 am |
|
|
this is the whole code needed to emulate a DS2401 8byte serial number;
it is based on some code found on web written for hitech compiler (as far as I remember), the code didn't mention the author so I can't do that either;
...the original code has some bugs in it (mainly bad timming and "corner-cuts"; also the reset procedure in the interrupt routine was not ok), I have just adapted it for CCS and corrected where it was necessary;
... I do not take any responsability on how it's used
Code: |
#include <16f88.h>
#device *=16
#fuses HS, WDT, PUT, MCLR, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT, NOIESO, NOFCMEN
//i've tried also with lower frequencies, there are problems with precise timmings
//so I recomend using 20MHZ; do not even think about internal RC ;)
#use delay(clock=20000000)
#use fast_io(B)
//some arbitrary serial data
#rom 0x2100={0x01,0x11,0x22,0x33,0x44,0x55,0x69,0x00}
// comment it out if you're not using leds for debugging
#define MOD_TEST
#define LED_PWR PIN_B1
#define LED_RST PIN_B2
#define LED_RX PIN_B3
#define LED_TX PIN_B4
//the pin used for interfacing with DS2401
//do not forget that sometimes you should use a pullup resistor on this line, 50k>(100k) should be fine
//be aware about the fact that in some cicumstances the DS's are powered up using parasite mode (by DQ line),
//this is not the case so you should power up your schematics from your 5V line
#define DS_DQ PIN_B0
#define PLIN 1
#define GOL 0
#define BUFFER_MAX 7
#define INIT_SEQ (flag_Rx=FALSE, flag_BUF_Rx=GOL, bit_curent=0)
int1 flag_Rx;
int1 flag_BUF_Rx;
int8 BUF_Rx;
int1 bRx;
int8 BUF_Tx[8];
int8 SN[8];
int8 bit_curent, buffer_index, del_count;
#INT_EXT
void interrupt(void)
{
if (flag_Rx)
{
#ifdef MOD_TEST
output_high(LED_RX);
#endif
delay_us(15);
bRx = input(DS_DQ);
flag_BUF_Rx = GOL;
bit_curent++;
if (bit_curent == 8)
{
#ifdef MOD_TEST
output_low(LED_RX);
#endif
flag_BUF_Rx = PLIN;
bit_curent = 0;
}
BUF_Rx >>= 1;
if (bRx)
BUF_Rx |= 0x80;
delay_us(5);
if(input(DS_DQ))
{
#ifdef MOD_TEST
output_low(LED_RX);
#endif
clear_interrupt(INT_EXT);
return;
}
else
{
del_count = 45;
while (del_count--)
{
if (input(DS_DQ))
{
#ifdef MOD_TEST
output_low(LED_RX);
#endif
clear_interrupt(INT_EXT);
return;
}
}
}
}
RST:
set_tris_b(0b00000001);
#ifdef MOD_TEST
output_high(LED_RST);
#endif
delay_us(200);
while(!input(DS_DQ));
delay_us(30);
output_low(DS_DQ);
set_tris_b(0b00000000);
delay_us(480);
INIT_SEQ;
flag_Rx = TRUE;
set_tris_b(0b00000001);
#ifdef MOD_TEST
output_low(LED_RST);
#endif
clear_interrupt(INT_EXT);
return;
}
void C_CRC(byte *CRCVal, int8 value)
{
int8 odd, bcnt;
for (bcnt=0; bcnt<8; bcnt++)
{
odd = (value ^ *CRCVal) & 0x01;
*CRCVal >>= 1;
value >>= 1;
if (odd != 0)
*CRCVal ^= 0x8C;
}
}
int8 CalcCRC(byte code_len, int8 *code)
{
int8 i, CRCVal=0;
for ( i=0; i<code_len; i++ )
C_CRC( &CRCVal, code[i] );
return CRCVal;
}
void Read_SN(void)
{
int8 adresa;
for ( adresa=0; adresa<BUFFER_MAX; adresa++ )
SN[adresa] = read_eeprom (adresa);
SN[adresa] = CalcCRC(7, SN);
}
/******************* MAIN *****************/
void main() {
int8 i,mask;
setup_wdt(WDT_2304MS);
INIT_SEQ;
Read_SN();
BUF_Rx = 0;
setup_adc(ADC_OFF);
setup_adc_ports(NO_ANALOGS);
set_tris_a(0b11111111);
set_tris_b(0b00000001);
output_float(DS_DQ);
ext_int_edge( H_TO_L );
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
#ifdef MOD_TEST
output_high(LED_PWR);
#endif
for(i=0; i<8; i++)
BUF_Tx[i] = SN[i];
while(TRUE)
{
if (flag_BUF_Rx == PLIN)
{
if (BUF_Rx == 0x33)
{
#ifdef MOD_TEST
output_high(LED_TX);
#endif
disable_interrupts(INT_EXT);
set_tris_b(0b00000001);
for (buffer_index=0; buffer_index<8; buffer_index++)
{
for (bit_curent=0; bit_curent<8; bit_curent++)
{
set_tris_b(0b00000001);
while(input(DS_DQ));
output_low(DS_DQ);
mask=0x01 & BUF_Tx[buffer_index];
set_tris_b(mask);
delay_us(35);
set_tris_b(0b00000001);
BUF_Tx[buffer_index] >>= 1;
}
}
#ifdef MOD_TEST
output_low(LED_TX);
#endif
for(i=0; i<8; i++)
BUF_Tx[i] = SN[i];
INIT_SEQ;
restart_wdt();
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
}
restart_wdt();
}
}
}
|
feel free to ask questions if you need
Dorin M |
|