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

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

Вот чисто программное решение для MCS51. Может, пригодится: (+)

Отправлено vinogradov aleksei 11 июля 2007 г. 16:12
В ответ на: Ответ: отправлено <font color=gray>Roman_V</font> 11 июля 2007 г. 16:05

;Программа реализует интеллектуальный датчик на AT89C2051.
;Кварц на 10 МГц.
;Коды ошибок, передаваемые хосту:
;"not_found" - ИМС DS1822 не найдена
;"not_ready" - Измерения еще не производились

$nomod51
$include (reg51.inc)

org 000h ;
jmp main_program ;Переход на основную программу

org 023h ;Обработчик прерывания от
jmp rs_232c_isr ;последовательного порта

;Буфер данных
temperature_low equ 08h ;Младший байт температуры
temperature_high equ 09h ;Старший байт температуры
th equ 0ah ;ALARM - регистр (младший байт)
tl equ 0bh ;ALARM - регистр (старший байт)
config equ 0ch ;Байт конфигурации DS1822
reserved_1 equ 0dh ;Зарезервировано
reserved_2 equ 0eh ;Зарезервировано
reserved_3 equ 0fh ;Зарезервировано
crc equ 10h ;Байт кода циклического контроля

;Вспомогательный буфер
bufer_1 equ 11h
bufer_2 equ 12h
bufer_3 equ 13h
bufer_4 equ 14h
bufer_5 equ 15h
bufer_6 equ 16h
bufer_7 equ 17h
bufer_8 equ 18h
bufer_9 equ 19h

;Обработчик прерывания от последовательного порта
rs_232c_isr:
push 00h ;
push acc ;
push psw ;

jnb ti,int_receive ;
clr ti ;
jnb ri,to_reti ;
int_receive:
clr ri ;
mov a,sbuf ;Принят символ запроса
cjne a,#'g',to_reti ;информации 'g' ?

acall report_results ;Выдать результаты измерения хосту

to_reti: pop psw ;
pop acc ;
pop 00h ;
reti ;Возврат из подпрограммы

;Основная программа
main_program:
mov sp,#30h ;Настроить SP на начало доступной RAM

acall ports_tuning ;Настроить линии портов
acall delay_500ms ;Три раза
clr led ;
acall delay_500ms ;мигнуть
setb led ;
acall delay_500ms ;светодиодом
clr led ;
acall delay_500ms ;при
setb led ;
acall delay_500ms ;подключении
clr led ;
acall delay_500ms ;датчика
setb led ;

acall error_not_ready ;Измерения еще не производились
acall bufer_to_bufer ;

acall set_serial_mode ;Настроить последовательный порт
setb ie.4 ;Разрешить прерывания (RS232C)
setb ie.7 ;Разрешить прерывания

cycle: acall delay_500ms ;Интервал опроса датчика
acall initial ;Инициализировать датчик
cjne a,#255,init_is_ok ;Проверим, была-ли ошибка
it_was_error:
acall error_not_found ;Датчик не найден !
acall bufer_to_bufer ;
jmp cycle ;Бесконечный цикл

init_is_ok:acall measurement ;Измерим температуру
cjne a,#0,it_was_error ;
acall bufer_to_bufer ;
jmp cycle ;Бесконечный цикл

;-----------------------------------------------------------------------------
;Область процедур:
;-----------------------------------------------------------------------------
;Процедура настраивает порты при включении термометра
ports_tuning:
setb data_line ;Настроить линию данных датчика на ввод
clr _rxd_txd ;Настроить интерфейсную ИС на прием
setb led ;Выключить светодиод
ret ;

;-----------------------------------------------------------------------------
;Процедура настраивает последовательный порт микроконтроллера (600 бит/сек.):
set_serial_mode:
push acc ;
push psw ;

orl tmod,#00100000b ;Настроим Т/С1 на режим
anl tmod,#00101111b ;8-ми битного перезагружаемого счетчика

mov th1,#169 ;Задаем требуемую скорость

mov scon,#01010000b ;Настроить УАПП на режим 1
orl pcon,#10000000b ;Взвести SMOD в единичку (скорость 600)

setb tcon.6 ;Запустить Т/С1
pop psw ;
pop acc ;
ret ;Возврат из подпрограммы

;-----------------------------------------------------------------------------
;Процедура инициализирует датчик и возвращает AСС=0,если датчик
;обнаружен, и код ошибки ACC=255 - в противном случае.
initial: push psw ;
push 00h ;
push b ;

mov b,#255 ;Сначала считаем, что была ошибка
setb data_line ;Настроить линию данных на вывод лог.1
clr ie.7 ;Запретить прерывания
clr data_line ;Сбросить линию data_line в ноль
acall delay_500mks ;
setb data_line ;Снова взвести линию data_line в единичку
acall delay_60mks ;Через 60 мкс чип должет ответить лог.
acall delay_15mks ;нулем (мы приняли запас = 15 мкс)
mov a,p3 ;
anl a,#10h ;
cjne a,#0,exit ;Нет ответа от чипа - на выход (ошибка)

mov r0,#255 ;Здесь сделана защита от зависания -
initial_wait_release: ;если чип не снимет низкий уровень
mov a,p3 ;
anl a,#10h ;
cjne a,#0,ok ;за определенное время,процедура просто
djnz r0,initial_wait_release;вернет в аккумуляторе код ошибки (255)
jmp exit ;

ok: mov b,#0 ;Датчик обнаружен - вернуть "ноль"

exit: setb ie.7 ;Разрешить прерывания
mov a,b ;Переписать признак ошибки в аккумулятор
pop b ;
pop 00h ;
pop psw ;
ret ;Возврат из подпрограммы

;-----------------------------------------------------------------------------
;Процедура принимает байт от ИС термометра. Принятый байт возвращается в ACC
read_byte: push 00h ;
push 01h ;
push b ;
push psw ;

mov b,#0 ;Результат пока равен нулю

;Теперь примем сам байт данных:
mov r0,#1 ;Прием младшими разрядами вперед (маска)
receive_all_bits:
setb data_line ;Вывести на линии "data_line" единичку
clr ie.7 ;Запретить прерывания
clr data_line ;Тайм -
acall delay_5mks ;слот
setb data_line ;чтения
acall delay_5mks ;
jnb data_line,zero_received
one_received:
mov a,b
orl a,r0 ;Формирование бита результата
mov b,a
zero_received:
mov a,r0 ;К новой
rl a ;битовой
mov r0,a ;маске

acall delay_60mks ;Здесь мы надеемся, что тайм-слот закон-
;чится за эти 60 мкС, но на всякий слу-
;чай это надо проверить:
mov r1,#255 ;Здесь сделана защита
wait_release: ;от зависания - если чип не снимет лог.0
jb data_line,time_slot_end;за определенное время, то произошел
djnz r1,wait_release ;сбой при передаче или DS1822 неисправна
time_slot_end: ;ВНИМАНИЕ !!! Здесь вступает в силу сле-
;дующее соображение. За время действия
;этого цикла DS1822 должна завершить тайм -
;слот взводом линии data_line в "1". Если
;это сделано не было, произошел сбой. Ни-
;каких извещений об этом в вызвавшую про-
;грамму не передается, а корректность
;данных проверяется подсчетом CRC
setb ie.7 ;Разрешить прерывания

mov a,r0 ;Проверим,
cjne a,#1,receive_all_bits;все-ли биты были приняты

read_exit: mov a,b ;Переписывание принятого символа в ACC
pop psw ;
pop b ;
pop 01h ;
pop 00h ;
ret ;

;-----------------------------------------------------------------------------
;Процедура передает байт, находящийся в регистре "B", в ИС термометра.
write_byte:push 00h ;
push acc ;
push psw ;

;Передача ...
setb data_line ;Вывести на линии данных единичку
acall delay_5mks ;Небольшая задержка

;Теперь передадим сам байт данных: ;
mov a,b
mov r0,#8
transmit_all_bits:
rrc a
jc transmit_1

transmit_0:clr ie.7 ;Запретить прерывания
clr data_line ;Тайм -
acall delay_60mks ;слот
acall delay_15mks ;передачи
setb data_line ;нулевого бита
setb ie.7 ;Разрешить прерывания
acall delay_5mks ;Промежуток между тайм - слотами
jmp transmit_next ;К следующему биту

transmit_1:clr ie.7 ;Запретить прерывания
clr data_line ;Тайм -
acall delay_5mks ;слот
setb data_line ;передачи единичного бита
setb ie.7 ;Разрешить прерывания
acall delay_10mks ;Тайм-слот записи должен длиться
acall delay_60mks ;на менее 60 мкс.
acall delay_5mks ;Промежуток между тайм - слотами

transmit_next:
djnz r0,transmit_all_bits ;Пока не переданы все биты, цикл ...

setb data_line ;Снова настроим линию данных на ввод

pop psw ;
pop acc ;
pop 00h ;
ret ;

;-----------------------------------------------------------------------------
;Процедура передает байт через RS-232C. Вход: A = передаваемый байт
transmitter:
push psw ;
setb _rxd_txd
clr ti ;Сбросить флаг прерывания передатчика
mov sbuf,a ;Загрузить передаваемый байт
;в буфер передатчика
wait_end_transmit:
jnb ti,wait_end_transmit ;
clr ti ;
acall delay_1600mks ;
clr _rxd_txd
pop psw ;
ret ;Возврат из подпрограммы

;-----------------------------------------------------------------------------
;Процедура выполняет измерение температуры.
;При ошибке инициализации датчика в аккумуляторе возвращается код ошибки 255.
;При успешном измерении в аккумуляторе возвращается "Ноль"
measurement:
push b ;
push acc ;
push psw ;

mov b,#0cch ;"Skip ROM"
acall write_byte ;Записать команду в DS1822

mov b,#044h ;"Convert T"
acall write_byte ;Записать команду в DS1822

clr led
acall delay_750ms ;Подождем окончания преобразования
setb led

acall initial ;Инициализируем датчик
cjne a,#255,error_not_occured
mov a,#255 ;Код ошибки "Датчик не обнаружен"
jmp measurement_exit ;

error_not_occured:
mov b,#0cch ;"Skip ROM"
acall write_byte ;Записать команду в DS1822

mov b,#0beh ;"Read ScratchPad"
acall write_byte ;Записать команду в DS1822

;Читаем данные
acall read_byte ;"Temperature LSB"
mov bufer_1,a ;Эта ячейка нужна только для расчета CRC

acall read_byte ;"Temperature MSB"
mov bufer_2,a ;Эта ячейка нужна только для расчета CRC

acall read_byte ;"TH Register"
mov bufer_3,a

acall read_byte ;"TL Register"
mov bufer_4,a

acall read_byte ;"Configuration Register"
mov bufer_5,a

acall read_byte ;"Reserved_1"
mov bufer_6,a

acall read_byte ;"Reserved_2"
mov bufer_7,a

acall read_byte ;"Reserved_3"
mov bufer_8,a

acall read_byte ;"CRC"
mov bufer_9,a

mov a,#0 ;

measurement_exit:
pop psw ;
pop acc ;
pop b ;
ret ;

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 750 миллисекунд
delay_750ms:
push 00h
push 01h
push psw

mov r0,#50
long_delay_1_750ms:
mov r1,#30
long_delay_2_750ms:
acall delay_500mks
djnz r1,long_delay_2_750ms
djnz r0,long_delay_1_750ms

pop psw
pop 01h
pop 00h
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 500 миллисекунд
delay_500ms:
push 00h
push 01h
push psw

mov r0,#50
long_delay_1_500ms:
mov r1,#20
long_delay_2_500ms:
acall delay_500mks
djnz r1,long_delay_2_500ms
djnz r0,long_delay_1_500ms

pop psw
pop 01h
pop 00h
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 10 миллисекунд
delay_10ms:push 00h
push psw

mov r0,#166
long_delay_10ms:
acall delay_60mks
djnz r0,long_delay_10ms

pop psw
pop 00h
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 1600 микросекунд
delay_1600mks:
push 00h
push psw

mov r0,#26
long_delay_1600mks:
acall delay_60mks
djnz r0,long_delay_1600mks

pop psw
pop 00h
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 500 микросекунд
delay_500mks:
push psw ;
orl tmod,#00000001b ;Настроим Т/С0 на режим
anl tmod,#11110001b ;16-тибитного счетчика

mov th0,#high(65536-416) ;Реализуем задержку
mov tl0,#low(65536-416) ;длительностью 500 мкс.
setb tcon.4 ;Запустить таймер 0
time_cycle_2:
jnb tcon.5,time_cycle_2 ;Цикл, пока не будет выставлен
;флаг переполнения таймера
anl tcon,#11001111b ;Таймер отсчитал положенное количество
;машинных циклов - сбросим флаг переполне-
;ния таймера (tcon.5) и запретим его
;работу (tcon.4)
pop psw ;
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью 60 микросекунд
delay_60mks:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 15.6 микросекунд
delay_15mks:
nop
nop
nop
nop
nop
nop
nop
nop
nop
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 10.8 микросекунд
delay_10mks:
nop
nop
nop
nop
nop
ret

;-----------------------------------------------------------------------------
;Процедура формирует задержку длительностью примерно 4.8 микросекунд
delay_5mks:ret

;Процедура переписывает вспомогательный буфер в буфер данных (эту процедуру
;прерывать нельзя !)
bufer_to_bufer:
push acc
push psw

clr ie.7
mov a,bufer_1
mov temperature_low,a
mov a,bufer_2
mov temperature_high,a
mov a,bufer_3
mov th,a
mov a,bufer_4
mov tl,a
mov a,bufer_5
mov config,a
mov a,bufer_6
mov reserved_1,a
mov a,bufer_7
mov reserved_2,a
mov a,bufer_8
mov reserved_3,a
mov a,bufer_9
mov crc,a
setb ie.7

pop psw
pop acc
ret

;Процедура записывает во вспомогательный буфер фразу "not_ready"
error_not_ready:
push psw
mov bufer_1,#'n' ;
mov bufer_2,#'o' ;
mov bufer_3,#'t' ;
mov bufer_4,#'_' ;
mov bufer_5,#'r' ;
mov bufer_6,#'e' ;
mov bufer_7,#'a' ;
mov bufer_8,#'d' ;
mov bufer_9,#'y' ;
pop psw
ret

;Процедура записывает во вспомогательный буфер фразу "not_found"
error_not_found:
push psw
mov bufer_1,#'n' ;
mov bufer_2,#'o' ;
mov bufer_3,#'t' ;
mov bufer_4,#'_' ;
mov bufer_5,#'f' ;
mov bufer_6,#'o' ;
mov bufer_7,#'u' ;
mov bufer_8,#'n' ;
mov bufer_9,#'d' ;
pop psw
ret

;Процедура отсылает хосту результат измерения (9 байтов)
report_results:
push acc
push psw

mov a,temperature_low ;
acall delay_10ms
acall transmitter ;
mov a,temperature_high ;
acall delay_10ms
acall transmitter ;
mov a,th ;
acall delay_10ms
acall transmitter ;
mov a,tl ;
acall delay_10ms
acall transmitter ;
mov a,config ;
acall delay_10ms
acall transmitter ;
mov a,reserved_1 ;
acall delay_10ms
acall transmitter ;
mov a,reserved_2 ;
acall delay_10ms
acall transmitter ;
mov a,reserved_3 ;
acall delay_10ms
acall transmitter ;
mov a,crc ;
acall delay_10ms
acall transmitter ;

pop psw
pop acc
ret

;****************************************************************************
;Область данных программы ;
;****************************************************************************
copyright: db 'Интеллектуальный термодатчик'
db '(C) И. Коваль (Специально для О.Климчука).'
db 'Версия от 21 мая 2004г.'

led equ p1.7 ;Светодиод

data_line equ p3.4 ;Линия данных датчика
_rxd_txd equ p1.5 ;При наличии лог. 0 на этой линии датчик
;принимает данные от хоста, при наличии
;лог. 1 - передает данные хосту
end

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

Ответы


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

Сообщение:

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

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

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

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