Телесистемы
 Разработка, производство и продажа радиоэлектронной аппаратуры
На главную   | Карта сайта | Пишите нам | В избранное
Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс.
e-mail:jobsmp@pochta.ru

Телесистемы | Электроника | Конференция «Микроконтроллеры и их применение»

Ответ:

Отправлено Леонид Иванович 19 декабря 2007 г. 02:01
В ответ на: ds18s20+atmega - есть у кого-нить исходники вменяемые? отправлено waszkiewicz 19 декабря 2007 г. 00:23


На Си:

//----------------------------------------------------------------------------

#include <Main.h>
#include <Ds18s20.h>

//----------------------------- Константы: -----------------------------------

#define TH_DELAY 1000 //задержка на готовность термометра

//----------------------------- Переменные: ----------------------------------

char Th_Data[9]; //структура данных термометра
bool Th_Present; //флаг присутствия термометра
bool Th_Ready; //флаг готовности данных термометра
int Th_Timer; //таймер термометра

//----------------------------- Функции: -------------------------------------

__monitor bool Th_Check(void); //проверка готовности термометра
void Th_Start(void); //старт термометра
void Th_Read(void); //чтение термометра
void TReset(void); //формирование импульса сброса
char TByte(char dat); //запись/чтение байта
bool TBit(bool b); //запись/чтение бита
void Th_Crc8(char b, char *crc); //вычисление CRC

//---------------------- Инициализация термометра: ---------------------------

void Init_Th(void)
{
Th_Present = 0; //сброс флага присутствия термометра
Th_Ready = 0; //сброс флага готовности данных
Th_Timer = TH_DELAY; //загрузка таймера термометра
Th_Start(); //старт термометра
}

//--------------- Проверка готовности и чтение термометра: -------------------

void Exe_Th(void)
{
if(Th_Check())
{
Th_Read();
Th_Start();
}
}

//-------------------- Проверка готовности термометра: -----------------------

bool Th_Check(void)
{
if(Th_Timer) return(0);
Th_Timer = TH_DELAY;
return(1);
}

//-------------------------- Старт термометра: -------------------------------

void Th_Start(void)
{
TReset(); //импульс сброса
if(Th_Present)
{
TByte(0xCC); //skip ROM
TByte(0x44); //convert T
}
else
{
Th_Ready = 0; //термометр отсутствует
}
}

//------------------------- Чтение термометра: -------------------------------

void Th_Read(void)
{
static char Th_Crc; //контрольная сумма термометра
if(Th_Present)
{
TReset(); //импульс сброса
if(Th_Present)
{
TByte(0xCC); //skip ROM
TByte(0xBE); //read scratchpad
Th_Crc = 0; //инициализация CRC
for(char i = 0; i < 9; i++)
{
char b = TByte(0xFF); //чтение данных
Th_Crc8(b, &Th_Crc); //обновление CRC
Th_Data[i] = b; //сохранение данных
}
}
}
Th_Ready = Th_Present && !Th_Crc; //готовность данных
}

//--------------------- Генерация импульса сброса: ---------------------------

void TReset(void)
{
char si;
Th_Present = 0; //сброс флага присутствия термометра
Port_OWP_0; //OWP <- 0
Delay_us(500); //delay 500 uS
si = __save_interrupt();
__disable_interrupt(); //запрещение прерываний
Port_OWP_Z; //OWP <- 1
Delay_us(14); //delay 14 uS
if(Port_OWP) //если OWP = 0, то ошибка
{
Delay_us(52); //delay 52 uS
if(!Port_OWP) //если OWP = 1, то ошибка
{
__restore_interrupt(si); //восстанавление прерываний
Delay_us(250); //delay 250 uS
if(Port_OWP) //если OWP = 0, то ошибка
{
Th_Present = 1; //если ошибок нет, термометр присутствует
}
}
}
__restore_interrupt(si); //восстанавление прерываний в случае ошибки
}

//-------------- Запись/чтение байта по однопроводной шине: ------------------

char TByte(char dat)
{
char res;
for(char i = 0; i < 8; i++)
{
res = res >> 1;
if(TBit(dat & 1)) res |= 0x80;
else res &= ~0x80;
dat = dat >> 1;
}
return(res);
}

//--------------- Запись/чтение бита по однопроводной шине: ------------------

bool TBit(bool b)
{
char si;
si = __save_interrupt();
__disable_interrupt(); //запрещение прерываний
Port_OWP_0; //OWP <- 0
Delay_us(2); //delay 2 uS
if(b) Port_OWP_Z; //bit = 1, OWP <- 1
Delay_us(13); //delay 13 uS
bool owp = Port_OWP; //чтение порта
Delay_us(45); //delay 45 uS
Port_OWP_Z; //OWP <- 1
__restore_interrupt(si); //восстанавление прерываний
Delay_us(2); //delay 2 uS
return(owp);
}

//--------------------- Вычисление контрольной суммы: ------------------------

void Th_Crc8(char b, char *crc)
{
for(char i = 0; i < 8; b = b >> 1, i++)
if((b ^ *crc) & 1) *crc = ((*crc ^ 0x18) >> 1) | 0x80;
else *crc = (*crc >> 1) & ~0x80;
}

//----------------------------------------------------------------------------
header:
//----------------------------------------------------------------------------

#ifndef Ds18s20H
#define Ds18s20H

//----------------------------------------------------------------------------

extern char Th_Data[9]; //структура данных термометра
extern bool Th_Present; //флаг присутствия термометра
extern bool Th_Ready; //флаг готовности данных термометра
extern int Th_Timer; //таймер готовности термометра

//----------------------------------------------------------------------------

void Init_Th(void); //инициализация термометра
void Exe_Th(void); //чтение термометра

//----------------------------------------------------------------------------

#endif

На асм:

;----------------------------------------------------------------------------

;TH-800 DS18S20 thermometer support module

;----------------------------------------------------------------------------

;Constantes:

.equ ThV = 200 ;thermometers ready delay, x5mS
.equ TvV = 10 ;temperature valid time, x1S

.equ Sign = 0x35 ;signature byte

.DSEG ;Data segment

ThPres: .byte 1 ;thermometers present flags
ThTM: .byte 1 ;thermometers ready timer
ThVal1: .byte 11 ;thermometer 1 data structure
ThVal2: .byte 11 ;thermometer 2 data structure

.CSEG ;Code segment

;----------------------------------------------------------------------------

;Init thermometer subsystem:

ThInit: ldy ThVal1 ;thermometer 1 data
rcall ClrPr ;clear present flag
rcall ClrTv ;clear T valid flag

ldy ThVal2 ;thermometer 2 data
rcall ClrPr ;clear present flag
rcall ClrTv ;clear T valid flag

rcall TStrt1 ;start thermometer 1
rcall TStrt2 ;start thermometer 2
ldi temp,ThV
sts ThTM,temp ;thermometers timer start
ret

;----------------------------------------------------------------------------

;Process thermometer timer:

ThTmrs: lds temp,ThTM ;process thermometer ready timer
tst temp
breq Thtr
dec temp
sts ThTM,temp
Thtr: ret

;----------------------------------------------------------------------------

;Check ready and read thermometers:

Therm: lds temp,ThTM
tst temp ;check thermometer timer
brne thno
rcall TRead1 ;read thermometer 1
rcall TRead2 ;read thermometer 2
rcall TStrt1 ;start thermometer 1
rcall TStrt2 ;start thermometer 2
ldi temp,ThV
sts ThTM,temp ;thermometers timer restart
stbr FLAGS,UpdD ;set display update flag
thno: ret

;----------------------------------------------------------------------------

;Start thermometer 1:

TStrt1: ldy ThVal1 ;thermometer 1 data
rcall TRes1 ;reset
rcall ChkPr ;check present
brcs TSret1 ;skip start if not present
ldi temp,0xCC ;skip ROM
rcall TByte1
ldi temp,0x44 ;convert T
rcall TByte1
TSret1: ret

;----------------------------------------------------------------------------

;Start thermometer 2:

TStrt2: ldy ThVal2 ;thermometer 2 data
rcall TRes2 ;reset
rcall ChkPr ;check present
brcs TSret2 ;skip start if not present
ldi temp,0xCC ;skip ROM
rcall TByte2
ldi temp,0x44 ;convert T
rcall TByte2
TSret2: ret

;----------------------------------------------------------------------------

;Read thermometer 1:

TRead1: ldy ThVal1 ;thermometer 1 data
rcall ChkPr ;check present
brcs TRret1 ;skip read if not present
rcall TRes1
rcall ChkPr ;check present
brcs TRret1 ;skip read if not present
ldi temp,0xCC ;skip ROM
rcall TByte1
ldi temp,0xBE ;read scratchpad
rcall TByte1
clr CRC ;CRC init

ldi Cnt,8
Rdt1: ser temp
rcall TByte1 ;read data byte
st Y+,temp ;save data byte
dec Cnt
brne Rdt1

ldy ThVal1 ;thermometer 1 data
ser temp
rcall TByte1 ;read CRC
tst CRC ;check CRC
brne Rn1

rcall SetTv ;set T valid flag
rjmp TRret1

Rn1: rcall ClrPr ;clear present flag
rcall ClrTv ;clear T valid flag
TRret1: ret

;----------------------------------------------------------------------------

;Read thermometer 2:

TRead2: ldy ThVal2 ;thermometer data
rcall ChkPr ;check present
brcs TRret2 ;skip read if not present
rcall TRes2
rcall ChkPr ;check present
brcs TRret2 ;skip read if not present
ldi temp,0xCC ;skip ROM
rcall TByte2
ldi temp,0xBE ;read scratchpad
rcall TByte2
clr CRC ;CRC init

ldi Cnt,8
Rdt2: ser temp
rcall TByte2 ;read data byte
st Y+,temp ;save data byte
dec Cnt
brne Rdt2

ldy ThVal2 ;thermometer data
ser temp
rcall TByte2 ;read CRC
tst CRC ;check CRC
brne Rn2

rcall SetTv ;set T valid flag
rjmp TRret2

Rn2: rcall ClrPr ;clear present flag
rcall ClrTv ;clear T valid flag
TRret2: ret

;----------------------------------------------------------------------------

;Save calibration 1:

SaveC1: ldy ThVal1 ;thermometer data
rcall TRes1 ;reset
rcall ChkPr ;check present
brcs svret1 ;skip save if not present
ldi temp,0xCC ;skip ROM
rcall TByte1
ldi temp,0x4E ;write scratchpad
rcall TByte1
ldi temp,Sign ;write signature
rcall TByte1
mov temp,EdCv ;write EdCv
rcall TByte1

rcall TRes1 ;reset
rcall ChkPr ;check present
ldi temp,0xCC ;skip ROM
rcall TByte1
ldi temp,0x48 ;copy scratchpad to EEPROM
rcall TByte1
ldi temp,ThV
sts ThTM,temp ;thermometers timer restart
svret1: ret

;----------------------------------------------------------------------------

;Save calibration 2:

SaveC2: ldy ThVal2 ;thermometer data
rcall TRes2 ;reset
rcall ChkPr ;check present
brcs svret2 ;skip save if not present
ldi temp,0xCC ;skip ROM
rcall TByte2
ldi temp,0x4E ;write scratchpad
rcall TByte2
ldi temp,Sign ;write signature
rcall TByte2
mov temp,EdCv ;write EdCv
rcall TByte2

rcall TRes2 ;reset
rcall ChkPr ;check present
ldi temp,0xCC ;skip ROM
rcall TByte2
ldi temp,0x48 ;copy scratchpad to EEPROM
rcall TByte2
ldi temp,ThV
sts ThTM,temp ;thermometer timer restart
svret2: ret

;----------------------------------------------------------------------------

;1-Wire port 1 support:

;Send reset pulse and receive presence pulse:

TRes1: Port_OWP1_0 ;OWP1 <- 0
ldi Cnt,250
rcall Delay ;delay 250 uS
ldi Cnt,250
rcall Delay ;delay 250 uS
cli ;interrupts disable
Port_OWP1_Z ;OWP1 <- 1
ldi Cnt,14
rcall Delay ;delay 14 uS
Skip_if_Port_OWP1_1
rjmp RFail1
ldi Cnt,52
rcall Delay ;delay 52 uS
Skip_if_Port_OWP1_0
rjmp RFail1
sei ;interrupts enable
ldi Cnt,250
rcall Delay ;delay 250 uS
Skip_if_Port_OWP1_1
rjmp RFail1
rcall SetPr ;set present
rjmp Rret1
RFail1: sei ;interrupts enable
rcall ClrPr ;present flag clear
rcall ClrTv ;clear T valid flag
Rret1: ret

;R/W byte via 1-wire port 1:
;temp - data byte

TByte1: push Cnt
ldi Cnt,8 ;bit counter
tb1: ror temp ;shift data byte
rcall TBit1 ;send bit
dec Cnt
brne tb1
ror temp ;shift last bit
pop Cnt
ret

;R/W one bit via 1-wire port 1:

TBit1: push Cnt
push temp
cli ;interrupts disable
Port_OWP1_0 ;OWP1 <- 0
ldi Cnt,2
rcall Delay ;delay 2 uS
brcc bit01
Port_OWP1_Z ;OWP1 <- 1 if C == 1
bit01: ldi Cnt,13
rcall Delay ;delay 13 uS
clc
Skip_if_Port_OWP1_0
sec
ldi Cnt,45
rcall Delay ;delay 45 uS
Port_OWP1_Z ;OWP1 <- 1
sei ;interrupts enable
ldi Cnt,2
rcall Delay ;delay 2 uS
rcall Do_CRC ;update CRC
pop temp
pop Cnt
ret

;----------------------------------------------------------------------------

;1-Wire port 2 support:

;Send reset pulse and receive presence pulse:

TRes2: Port_OWP2_0 ;OWP2 <- 0
ldi Cnt,250
rcall Delay ;delay 250 uS
ldi Cnt,250
rcall Delay ;delay 250 uS
cli ;interrupts disable
Port_OWP2_Z ;OWP2 <- 1
ldi Cnt,14
rcall Delay ;delay 14 uS
Skip_if_Port_OWP2_1
rjmp RFail2
ldi Cnt,52
rcall Delay ;delay 52 uS
Skip_if_Port_OWP2_0
rjmp RFail2
sei ;interrupts enable
ldi Cnt,250
rcall Delay ;delay 250 uS
Skip_if_Port_OWP2_1
rjmp RFail2
rcall SetPr ;set present
rjmp Rret2
RFail2: sei ;interrupts enable
rcall ClrPr ;present flag clear
rcall ClrTv ;clear T2 valid flag
Rret2: ret

;R/W byte via 1-wire port 2:
;temp - data byte

TByte2: push Cnt
ldi Cnt,8 ;bit counter
tb2: ror temp ;shift data byte
rcall TBit2 ;send bit
dec Cnt
brne tb2
ror temp ;shift last bit
pop Cnt
ret

;R/W one bit via 1-wire port 2:

TBit2: push Cnt
push temp
cli ;interrupts disable
Port_OWP2_0 ;OWP2 <- 0
ldi Cnt,2
rcall Delay ;delay 2 uS
brcc bit02
Port_OWP2_Z ;OWP2 <- 1 if C == 1
bit02: ldi Cnt,13
rcall Delay ;delay 13 uS
clc
Skip_if_Port_OWP2_0
sec
ldi Cnt,45
rcall Delay ;delay 45 uS
Port_OWP2_Z ;OWP2 <- 1
sei ;interrupts enable
ldi Cnt,2
rcall Delay ;delay 2 uS
rcall Do_CRC ;update CRC
pop temp
pop Cnt
ret

;----------------------------------------------------------------------------

;Update CRC:
;In: CRC, C - data bit
;Out: new CRC

Do_CRC: in temp,SREG ;save C
push temp
rol temp ;temp.0 <- C
eor temp,CRC ;temp.0 eor CRC.0
ror temp ;temp.0 -> C
brcc ZERO1
ldi temp,0x18
eor CRC,temp ;update the CRC value
ZERO1: ror CRC ;position the new CRC
pop temp
out SREG,temp ;restore C
ret

;----------------------------------------------------------------------------

;Delay:
;Cnt - delay value, uS (2uS min)
;CAUTION! Code is timed for 11.059 MHz

Delay: dec Cnt
nop
nop
nop
nop
De: dec Cnt
nop
nop
nop
nop
nop
nop
nop
nop
brne De
ret

;----------------------------------------------------------------------------

;Set present flag:

SetPr: ldd temp,Y+10
ori temp,0x01
std Y+10,temp
ret

;Clear present flag:

ClrPr: ldd temp,Y+10
andi temp,~0x01
std Y+10,temp
ret

;Check present flag:

;Out: C = 0 if present

ChkPr: ldd temp,Y+10
andi temp,0x01
subi temp,1
ret

;----------------------------------------------------------------------------

;Set T valid flag:

SetTv: ldd temp,Y+10
ori temp,0x02
std Y+10,temp
ret

;Clear T valid flag:

ClrTv: ldd temp,Y+10
andi temp,~0x02
std Y+10,temp
ret

;Check T valid flag:

;Out: C = 0 if valid

ChkTv: ldd temp,Y+10
andi temp,0x02
subi temp,1
ret

;----------------------------------------------------------------------------

;Convert temperature to obtain 0.1°C resolution:
;In: Y - pointer to thermometer data structure:
; [Y+1]:[Y+0] - temperature (signed, 0.5°C resolution)
; [Y+2] - signature
; [Y+3] - calibration byte
; [Y+4] - reserved
; [Y+5] - reserved
; [Y+6] - CR
; [Y+7] - CPC
;Out: [Y+9]:[Y+8] - temperature (signed, 0.1°C resolution)

TConv: ldd tempH,Y+7 ;load CPC
ldd tempL,Y+6 ;load CR
sub tempH,tempL ;CPC - CR
ldi tempL,20
mul tempH,tempL ;20 * (CPC - CR)
clr tempL
ldd temp,Y+7 ;load CPC
clr tempX
clr tempA ;clear remainder Low byte
sub tempB,tempB ;clear remainder High byte and carry
ldi Cnt,17 ;init loop counter
div1: rol r0 ;shift left dividend
rol r1
dec Cnt ;decrement counter
breq div2 ;jump if done
rol tempA
rol tempB
sub tempA,temp
sbc tempB,tempX
brcc div3 ;if result negative
add tempA,temp ; restore remainder
adc tempB,tempX
clc ; clear carry to be shifted into result
rjmp div1
div3: sec
rjmp div1
div2: push r0 ;r1:r0 = 20 * (CPC - CR) / CPC
push r1
ldd tempL,Y+0
ldd tempH,Y+1
asr tempH ;truncate 0.5°C
ror tempL
ldi tempX,20 ;20 * T
mulsu tempH,tempX ;(signed)tempH * (unsigned)tempX
mov tempB,r0
mul tempL,tempX ;(unsigned)tempL * (unsigned)tempX
mov tempA,r0
add tempB,r1
subi tempA,5 ;20 * (T - 0.25°C)
sbci tempB,0
pop r1
pop r0
add tempA,r0 ;20 * (T - 0.25°C) + 20 * (CPC - CR) / CPC
adc tempB,r1
asr tempB ;10 * (T - 0.25°C + (CPC - CR) / CPC)
ror tempA

clr tempL ;calibration byte = 0
ldd temp,Y+2 ;read signature
cpi temp,Sign ;check signature
brne sg_ok ;use calibration byte = 0 if signature fail
ldd tempL,Y+3 ;read calibration byte
cpi tempL,TcvU ;check calibration byte for TcvU
brlt sg_u
ldi tempL,TcvU ;calibration byte = TcvU
rjmp sg_ok
sg_u: cpi tempL,TcvD ;check calibration byte for TcvD
brge sg_ok
ldi tempL,TcvD ;calibration byte = TcvD

sg_ok: clr tempH
bbrc tempL,7,calp ;convert signed8 CALIB to signed16
com tempH
calp: add tempA,tempL ;10 * (T - 0.25°C + (CPC - CR) / CPC) + CALIB
adc tempB,tempH
std Y+8,tempA ;save result
std Y+9,tempB
ret

;----------------------------------------------------------------------------

;Convert temperature value to BCD format:
;In: [Y+9]:[Y+8] - temperature (signed, 0.1°C resolution)
;Out: tempH:tempL:tempX = in BCD format
; tempH:tempL:tempX = '--.-' if thermometer not present
; if (T<0) T = 1

T2BCD: rcall ChkTv ;check T valid
brcc t1ok
ldi tempH,MINUS ;indicate --.-
ldi tempL,MINUS
ldi tempX,MINUS
rjmp t2bcdr ; if not present

t1ok: ldd tempA,Y+8 ;temperature value load
ldd tempB,Y+9

;Get abs value:

clt ;T = 0
bbrc tempB,7,plus
com tempA ;tempB:tempA = - tempB:tempA
com tempB
subi tempA,low (-1)
sbci tempB,high(-1)
set ;T = 1

;Check for 99.9°C:

plus: ldi tempL,low (999)
ldi tempH,high(999)
cp tempA,tempL
cpc tempB,tempH
brlo t_ok
mov tempB,tempH
mov tempA,tempL

t_ok: ser tempH
div100: inc tempH
subi tempA,low (100)
sbci tempB,high(100)
brcc div100
subi tempA,-100
ser tempL
div10: inc tempL
subi tempA,10
brcc div10
subi tempA,-10
mov tempX,tempA
t2bcdr: ret

;----------------------------------------------------------------------------


Составить ответ | Вернуться на конференцию

Ответы


Отправка ответа
Имя*: 
Пароль: 
E-mail: 
Тема*:

Сообщение:

Ссылка на URL: 
URL изображения: 

если вы незарегистрированный на форуме пользователь, то
для успешного добавления сообщения заполните поле, как указано ниже:
поделите шесть пополам:

Перейти к списку ответов | Конференция | Раздел "Электроника" | Главная страница | Карта сайта

Rambler's Top100 Рейтинг@Mail.ru
 
Web telesys.ru