Инструменты пользователя

Инструменты сайта


doc:1201:643.mgul.12013-01_12_01

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
doc:1201:643.mgul.12013-01_12_01 [2017/02/14 02:09]
gotrum
doc:1201:643.mgul.12013-01_12_01 [2018/04/28 23:47] (текущий)
Строка 1: Строка 1:
-**АННОТАЦИЯ**+ 
 +====Аннотация====
  
 В данном программном документе приведен текст программы «telemetry_rev1-1»,​ предназначенной для опроса телеметрических датчиков,​ подключенных к микроконтроллеру Atmel Atmega328P, и отправки полученных данных по последовательному порту на бортовую ЭВМ. Текст программы реализован в виде символической записи на языке ассемблера AVR. Компилятором является консольная программа для UNIX-подобных операционных систем - avra. В данном программном документе приведен текст программы «telemetry_rev1-1»,​ предназначенной для опроса телеметрических датчиков,​ подключенных к микроконтроллеру Atmel Atmega328P, и отправки полученных данных по последовательному порту на бортовую ЭВМ. Текст программы реализован в виде символической записи на языке ассемблера AVR. Компилятором является консольная программа для UNIX-подобных операционных систем - avra.
Строка 14: Строка 15:
 В процессе сбора данных происходит их перевод в двоично-десятичный код и отправка по USB-to-Serial протоколу с сохранением в памяти бортовой ЭВМ. В процессе сбора данных происходит их перевод в двоично-десятичный код и отправка по USB-to-Serial протоколу с сохранением в памяти бортовой ЭВМ.
  
-Программа состоит из основной программы,​подключаемых модулей и файла объявления имен регистров:​+Программа состоит из основной программы,​ подключаемых модулей и файла объявления имен регистров:​
   *telemetry_rev1-1.asm - основная программа;​   *telemetry_rev1-1.asm - основная программа;​
   *1wire.asm - работа с датчиками по 1-Wire протоколу;​   *1wire.asm - работа с датчиками по 1-Wire протоколу;​
Строка 23: Строка 24:
   *m328Pdef.inc - объявление имен регистров и ячеек памяти.   *m328Pdef.inc - объявление имен регистров и ячеек памяти.
  
-**1. Текст программы telemetry_rev1-1.asm ​на языке ассемблера AVR** +====Текст программы telemetry_rev1-1.asm====
- +
-<code asm>;​-------------------------------------------------------------------------------------------------------------- +
-; Program ​     : telemetry_rev1-1 +
-; Compiler ​    : AVRA +
-; Chip type    : ATmega328P +
-; System Clock : 16 MHz +
-; Date         : 18.01.2017 +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Подключение_библиотек_и_резервация---------------------------------------- +
-;​--------------------------------------------места_под_данные-------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- .include "​m328Pdef.inc"​ +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- .dseg +
-adc_data: +
- .byte 8 +
-Trm: ; Ячейки ОЗУ под показания датчиков DS18B20 +
- .byte 14  +
-bmp_temp:​ ;​ Ячейки ОЗУ под показания темп. датчика BMP180 +
- .byte 2 +
-bmp_pres:​ ;​ Ячейки ОЗУ под показания давления датчика BMP180  +
-        .byte 2 +
-bh_lux: +
- .byte 2 +
-;​-------------------------------------------------------------------------------------------------------------- +
-  +
- .cseg +
- +
-        .include "​iterrupts.asm"​ ;​ Библиотека векторов прерываний +
- .include "​macr.asm"​ ;​ Библиотека макросов +
- .include "​twi_lib.asm"​ ;​ Библиотека работы шины TWI +
- .include "​hextobcd.asm"​ ;​ Библиотека перевода чисел в неупаковынный 2-10 код +
- .include "​1wire.asm"​ ;​ Библиотека 1-wire устройств +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​--------------------------------Конец_подключения_библиотек_и_резервации-------------------------------------- +
-;​--------------------------------------------места_под_данные-------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
-RESET: +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​-----------------------------------------Начальная_инициализация---------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- ldi R16, Low(RAMEND) ;​ Инициализация стека +
- out SPL, R16 +
- ldi R16, High(RAMEND) +
- out SPH, R16 +
- +
- ​ .def try ​r21 +
- .def temp ​r16 +
- .def razr1 ​r17 +
- .def razr2 ​r18 +
- .def razr3 = r19 +
- +
-  +
- .equ W1_DDR = DDRB ; Присваиваем псевдоним регистрам порта датчиков DS18B20 +
- .equ W1_PORT = PORTB  +
- .equ W1_PIN = PINB  +
- .equ W1_BIT = 0 ; Бит порта на котором датчики (8 цифровой контакт на плате Ардуино) +
- +
- .equ FREQ = 16000000 ; Частота процессора  +
- .equ baudrate = 38400 ; Расчитываем делитель бодрейта для UART +
- .equ bauddivider = FREQ/​(16*baudrate)-1 +
- .equ FreqSCL = 200000 ; Расчитываем частоту работы шины TWI +
- .equ FreqTWBR = ((FREQ/​FreqSCL)-16)/​2 +
- +
- ldi R16, low(bauddivider) ;​ Инициализация UART +
- sts UBRR0L,​R16 +
- ldi R16, high(bauddivider) +
- sts UBRR0H,​R16 +
- +
- ldi R16,0 +
- sts UCSR0A, R16 +
-  sts UCSR0B, R16 +
- sts UCSR0C, R16 +
- +
- LDI R16, (1<<​RXEN0)|(1<<​TXEN0)|(0<<​RXCIE0)|(0<<​TXCIE0)|(0<<​UDRIE0) +
- sts UCSR0B, R16  +
- ​ ldi r16,​0 +
- +
- LDI R16, (0<<​USBS0)|(0<<​UMSEL0)|(0<<​UMSEL1)|(1<<​UCSZ00)|(1<<​UCSZ01) +
- sts UCSR0C, R16 +
-  +
-  +
- ldi r16,​0b01000000 ;​ Инициализация АЦП +
- sts ADMUX,​r16 +
- ldi r16,​0b11011111 +
- sts ADCSRA,​r16 +
- ldi r25,​0 +
- +
- rcall W1_Sbros ;​ Сбрасываем шину 1-Wire +
- rcall W1_Init_12bit ;​ Перестраиваем конфигурационный байт на 12 битную схему работы +
- rcall W1_Sbros ;​ Вновь сбрасываем +
- +
- ldi r16,​0b00000101 ;​ Инициализация работы прерывания по таймеру для отправки показаний +
- sts TCCR2B,​r16 ;​ датчиков DS18B20 по шине 1-Wire +
- ldi r16,​0b00000001 +
- sts TIMSK2,​r16 +
- sts TIFR2,​r16 +
- ldi r16,​0xF0 +
- sts TCNT2,​r16 +
- +
- ldi r16,​0b00000101 ;​ Инициализация работы прерывания по таймеру для отправки показаний +
- sts TCCR1B,​r16 ;​ датчиков DS18B20 по шине 1-Wire +
- ldi r16,​0b00000001 +
- sts TIMSK1,​r16 +
- sts TIFR1,​r16 +
- ldi r16,​0xA0 +
- sts TCNT1H,​temp +
- sts TCNT1L,​temp +
-  +
- ldi R16, 0b00110000 ;​ Инициализация шины TWI +
-        out PORTC, R16 +
- ldi r16,​FreqTWBR +
- sts TWBR,​r16 +
- ldi r16,​0x00 +
- sts TWSR,​r16 +
- +
- clr try +
- clr r2 +
- clr r3 +
- clr r4 +
- clr r5 +
- ldi r24,​0x00 +
-        ldi R16, 0b00000000 +
-         out PORTD, R16 +
- +
-        ldi R16, 0b00000100 +
-        out DDRD, R16  +
-  +
- rcall i2c_start +
- ldi r16,​0x46 ;​ Если нет, то остаемся этой процедуре +
- rcall i2c_send +
- ldi r16,​0x11 +
- rcall i2c_send +
- rcall i2c_stop +
- sei ; Разрешаем прерывания +
- rjmp main +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Конец_начальной_инициализации------------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Основная_подпрограмма------------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- +
-main:  +
- cli ; Запрещаем прерывания в основном цикле +
- ;​rcall Board_timer +
-;​----------------------print_time------------------- +
-  +
- pushr +
- mov r17,​r5 +
- mov r16,​r4 +
- rcall bin2ASCII15 +
- mov r17,​r3 +
- mov r16,​r2 +
- rcall bin2ASCII15 +
- popr +
- tabulate +
-;​--------------------------------------------------- +
- +
- rcall W1_ConvTemp ;​ Говорим датчикам конвертировать температуры +
-  +
- push r16 +
- lds r16,​bh_lux+1 +
- cpi r16,​0x82 +
- brlo light +
- brsh no_light +
-light: +
- lds r16,​bh_lux +
- cpi r16,​0x01 +
- brsh light_exit +
- ldi r16,​0b00000100 +
- out PORTD,​r16 +
- jmp light_exit +
-no_light:​  +
- ldi r16,​0b00000000 +
- out PORTD,​r16 +
- jmp light_exit +
-light_exit:​ +
- +
- pop r16 +
- ldi ZL, LOW(adc_data) ;​ Производим косвенную адресацию на показания АЦП, чтобы потом их +
- ldi ZH, HIGH(adc_data) ;​ последовательно отправить по UART +
- clr r20 +
-print_adc:​ ;​ Цикл отправки показаний АЦП +
- inc r20 +
- pushr +
- ld r17,​Z +
- adiw ZH:​ZL,​1 +
- ld r16,​Z +
- adiw ZH:​ZL,​1 +
- rcall bin2ASCII15 +
- popr +
- tabulate +
- cpi r20,​4 +
- brne print_adc ;​ Закончили цикл +
- tabulate +
- +
- pushr +
- lds r17,​bmp_temp ;​ Выводим показания датчика BMP180 +
- lds r16,​bmp_temp+1 +
- rcall bin2ASCII15 +
- tabulate +
- lds r17,​bmp_pres +
- lds r16,​bmp_pres+1 +
- rcall bin2ASCII15 +
- tabulate +
- lds r17,​bh_lux +
- lds r16,​bh_lux+1 +
- rcall bin2ASCII15 +
- popr +
- +
- +
- inc r24 ;​ Увеличили счетчик кадров и отправили его значение по UART +
- newline +
- +
-  +
- +
- rcall i2c_start +
- ldi r16,​0x47 +
- rcall i2c_send +
- rcall i2c_receive +
- sts bh_lux,​r16 +
- rcall i2c_receive_last +
- sts bh_lux+1,​r16 +
- rcall i2c_stop +
- sei ; Разрешили прерывания,​ чтобы микроконтроллер смог обработать +
- ; новые показания АПЦ, термометров и датчика BMP180 +
- rcall i2c_start +
- rjmp main +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Конец_основной_подпрограммы------------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Прерывание_АЦП------------------------------------------------------------ +
-;​-------------------------------------------------------------------------------------------------------------- +
-adc_conv:​  +
- cli ; Запрещаем прерывания +
- ;​rcall Board_timer +
-  +
- lds r17,​ADCL ;​ Снимаем показания сделанные во время нашего отсутствия в прерывании +
- lds r18,​ADCH +
- +
- +
-  +
- cpi r25,​0 ;​ Смотрим,​ какое число содержится в r25 +
- breq adc0 ;​ Переходим по метке для этого числа +
- cpi r25,​1 +
- breq adc1 +
- cpi r25,​2 +
- breq adc2 +
- cpi r25,​3 +
- breq adc3 +
- cpi r25,​4 +
- breq adc4 +
- +
-adc0:​ sts adc_data+6,​r18 ;​ Записываем снятые в начале показания АЦП +
- sts adc_data+7,​r17 +
- ldi r16,​0b01000000 ;​ Запускаем новое преобразования в зависимости от пина АЦП +
- sts ADMUX,​r16 +
- rjmp adc_ex ;​ Переходим на выход +
- +
-adc1:​ sts adc_data,​r18 +
- sts adc_data+1,​r17 +
- ldi r16,​0b01000001 +
- sts ADMUX,​r16 +
- rjmp adc_ex +
- +
-adc2:​ sts adc_data+2,​r18 +
- sts adc_data+3,​r17 +
- ldi r16,​0b01000010 +
- sts ADMUX,​r16 +
- rjmp adc_ex +
- +
-adc3:​ sts adc_data+4,​r18 +
- sts adc_data+5,​r17 +
- ldi r16,​0b01000011 +
- sts ADMUX,​r16 +
- rjmp adc_ex +
- +
-adc4:​ clr r25 ;​ Если r25 = 4, очищаем его и прыгаем на adc0 +
- rjmp adc0 +
- +
-adc_ex:​ ldi r16,​0b11011111 ;​ Каждый раз повторно инициализируем АЦП +
- sts ADCSRA,​r16 +
- inc r25 +
- sei +
- reti +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Конец_прерывания_АЦП------------------------------------------------------ +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Прерывание_таймера1-------------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
-W1_timer: +
- cli +
- ;​rcall Board_timer +
- ldi r16,​0x54 +
- check1 r16 +
- tabulate +
- rcall W1_Sbros ;​ Сбрасываем шину и проверяем есть ли датчик  +
- ldi YL, LOW(Trm) +
- ldi YH, HIGH(Trm) +
- ldi ZL,​LOW(Addr1*2) +
- ldi ZH,​HIGH(Addr1*2) +
- rcall W1_ReadMem ;​ Читаем в ОЗУ текущую температуру +
- ldi ZL,​LOW(Addr2*2) +
- ldi ZH,​HIGH(Addr2*2) +
- rcall W1_ReadMem +
- ldi ZL,​LOW(Addr3*2) +
- ldi ZH,​HIGH(Addr3*2) +
- rcall W1_ReadMem +
- ldi ZL,​LOW(Addr4*2) +
- ldi ZH,​HIGH(Addr4*2) +
- rcall W1_ReadMem +
- ldi ZL,​LOW(Addr5*2) +
- ldi ZH,​HIGH(Addr5*2) +
- rcall W1_ReadMem +
- ldi ZL,​LOW(Addr6*2) +
- ldi ZH,​HIGH(Addr6*2) +
- rcall W1_ReadMem +
- ldi ZL,​LOW(Addr7*2) +
- ldi ZH,​HIGH(Addr7*2) +
- rcall W1_ReadMem +
- pushf ; На всякий случай отправляем в стек SREG +
- ldi ZL, LOW(Trm) ; Делаем косвенную адресацию на массив данных температуры датчиков DS18B20 +
- ldi ZH, HIGH(Trm) +
- clr r20 +
-print1:​ ;​ Цикл печати данных +
- inc r20 +
- pushr +
- ld r16,​Z +
- adiw ZH:​ZL,​1 +
- ld r17,​Z +
- adiw ZH:​ZL,​1 +
- rcall bin2ASCII15 +
- tabulate  +
- popr +
- cpi r20,​7 +
- +
- brne print1 +
- newline +
- ; Задаем число с которого таймер начнет считать до следующего прерывания +
- ldi r22,​0xA0 +
- sts TCNT1H,​r22 +
- sts TCNT1L,​r22 +
- popf ; Возвращаем SREG из стека +
- sei ; Разрешаем прерывания +
- reti +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Конец_прерывания_таймера1-------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Прерывание_таймера0-------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
-Board_timer:​ +
- cli +
-  +
- ;​lds r16,​TIFR2 +
- ;​andi r16,​0b00000001 +
- ;​sbrs temp,​TOV2 +
- ;ret +
-  +
- pushf +
- mov r16,​r2 +
-  +
- cpi r16,​0xFF +
- breq r2cap +
- inc r2 +
- jmp btim_exit +
-r2cap: +
- clr r2 +
- mov r16,​r3 +
- cpi r16,​0xFF +
- breq r3cap +
- inc r3 +
- jmp btim_exit +
-r3cap: +
- clr r3 +
- mov r16,​r4 +
- cpi r16,​0xFF +
- breq r4cap +
- inc r4 +
- jmp btim_exit +
-r4cap: +
- clr r4 +
- mov r16,​r5 +
- cpi r16,​0xFF +
- breq r5cap +
- jmp btim_exit +
- inc r5 +
-r5cap: +
- clr r5 +
- jmp btim_exit +
-  +
-btim_exit:​ +
- ldi r22,​0xE9 +
- sts TCNT2,​r22 +
- popf +
- sei +
- reti +
-  +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------Конец_прерывания_таймера0-------------------------------------------------- +
-;​-------------------------------------------------------------------------------------------------------------- +
- +
- +
- +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​------------------------------------------Прерывание_TWI------------------------------------------------------ +
-;​-------------------------------------------------------------------------------------------------------------- +
-TWI_int: +
- cli ; Запрещаем прерывания +
- ;​rcall Board_timer +
- +
- push r16 ;​ Отправляем в стек r16 +
- lds r16,​TWSR ;​ Сравниваем Статус-регистр TWI  +
- andi r16,​0xF8 +
- cpi r16,​0x08 ;​ Если он равен 0x08, то нам надо запустить вычисление  +
- breq TWI_start_samples_1  +
- cpi r16,​0x10 ;​ Если он равен 0х10, то нам надо считывать показания +
- breq TWI_read_samples_1  +
-TWI_exit:​ pop r16 ;​ Возвращаем r16 из стека +
- sei ; Разрешаем прерывания +
- reti +
- +
-TWI_start_samples_1:​ ;​ Запускаем вычисление некомпенсированной температуры +
- ; Проверяем содержимое переменной try +
- cpi try,​1 ;​ Если 1, то прыгаем на запуск вычисления давления +
- breq TWI_start_samples_2 +
- ldi r16,​0xEE ;​ Если нет, то остаемся этой процедуре +
- rcall i2c_send +
- +
- ldi r16,​0xF4 +
- rcall i2c_send +
- +
- ldi r16,​0x2E +
- rcall i2c_send +
- rcall i2c_start +
- rjmp TWI_exit +
- +
-TWI_start_samples_2:​ ;​ Запускаем вычисление некомпенсированного давления +
- ldi r16,​0xEE +
- rcall i2c_send +
- +
- ldi r16,​0xF4 +
- rcall i2c_send +
-  +
- ldi r16,​0x34 +
- rcall i2c_send +
- rcall i2c_start +
- rjmp TWI_exit +
-TWI_read_samples_1:​ ;​ Считываем показания некомпенсированной температуры +
- ; Снова проверяем try +
- cpi try,​1 +
- breq TWI_read_samples_2 +
- ldi r16,​0xEE +
- rcall i2c_send +
- +
- ldi r16,​0xF6 +
- rcall i2c_send +
-  +
- rcall i2c_start +
- +
- ldi r16,​0xEF +
- rcall i2c_send +
- +
- rcall i2c_receive +
- sts bmp_temp,​r16 +
- rcall i2c_receive_last +
- sts bmp_temp+1,​r16 +
- ldi try,​0b00000001 +
- rcall i2c_stop +
- rjmp TWI_exit +
-TWI_read_samples_2:​  +
- ldi r16,​0xEE +
- rcall i2c_send +
- +
- ldi r16,​0xF6 +
- rcall i2c_send +
-  +
- rcall i2c_start +
- +
- ldi r16,​0xEF +
- rcall i2c_send +
- +
- rcall i2c_receive +
- sts bmp_pres,​r16 +
- rcall i2c_receive_last +
- sts bmp_pres+1,​r16 +
- ldi try,​0b00000000 ;​ Уменьшаем try до 0 +
- rcall i2c_stop +
- rjmp TWI_exit +
-;​-------------------------------------------------------------------------------------------------------------- +
-;​--------------------------------------Конец_прерывания_TWI---------------------------------------------------- +
-;​--------------------------------------------------------------------------------------------------------------+
  
-Addr1: .db 0x28,​0xFF,​0x41,​0x3,​0xA3,​0x15,​0x1,​0xBB ; Адреса датчиков DS18B20 +<hidden развернуть>​ 
-Addr2: .db 0x28,​0xFF,​0xE2,​0x1A,​0xA2,​0x15,​0x4,​0xF9 +<code asm> 
-Addr3: .db 0x28,​0xFF,​0x91,​0xF,​0xA3,​0x15,​0x4,​0xC8 +  ;​---------------------------------------------------- 
-Addr4: .db 0x28,​0xFF,​0x90,​0x82,​0xA3,​0x15,​0x4,​0x41 +  ; Program ​ : telemetry_rev1-1 
-Addr5: .db 0x28,​0xFF,​0xC6,​0xB,​0xA3,​0x15,​0x4,​0x2 +  ; Compiler ​ : AVRA 
-Addr6: .db 0x28,​0xFF,​0x9,​0x5D,​0xA3,​0x15,​0x4,​0x9E +  ; Chip type : ATmega328P 
-Addr7: .db 0x28,​0xFF,​0x7F,​0x83,​0xA3,​0x15,​0x4,​0x7B+  ; System Clock : 16 MHz 
 +  ; Date   : 18.01.2017 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +   
 +  ;​Подключение библиотек и резервация места под данные 
 +  .include "​m328Pdef.inc " 
 +   
 +  .dseg 
 +  adc_data: 
 +  .byte8 
 +  Trm:; Ячейки ОЗУ под показания датчиков DS18B20 
 +  .byte14 
 +  bmp_temp:; Ячейки ОЗУ под показания темп. датчика BMP180 
 +  .byte2 
 +  bmp_pres:; Ячейки ОЗУ под показания давления датчика BMP180  
 +  .byte2 
 +  bh_lux: 
 +  .byte2 
 +   
 +  .cseg 
 +  .include "​iterrupts.asm";​ Библиотека векторов прерываний 
 +  .include "​macr.asm";​ Библиотека макросов 
 +  .include "​twi_lib.asm";​ Библиотека работы шины TWI 
 +  .include "​hextobcd.asm";​ Библиотека перевода чисел в неупакованный 2-10 код 
 +  .include "​1wire.asm";​ Библиотека 1-wire устройств 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +   
 +  RESET: 
 +   
 +  ;​Начальная_инициализация 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +   
 +  ldi R16, Low(RAMEND);​ Инициализация стека 
 +  out SPL, R16 
 +  ldi R16, High(RAMEND) 
 +  out SPH, R16 
 +   
 +  .def try = r21 
 +  .def temp = r16 
 +  .def razr1 = r17 
 +  .def razr2 = r18 
 +  .def razr3 = r19 
 +   
 +   
 +  .equ W1_DDR = DDRB ; Присваиваем псевдоним регистрам порта датчиков DS18B20 
 +  .equ W1_PORT = PORTB  
 +  .equ W1_PIN = PINB  
 +  .equ W1_BIT = 0 ; Бит порта на котором датчики (8 цифровой контакт на плате Ардуино) 
 +   
 +  .equ FREQ = 16000000 ; Частота процессора  
 +  .equ baudrate = 38400; Рассчитываем делитель бодрейта для UART 
 +  .equ bauddivider = FREQ/​(16*baudrate)-1 
 +  .equ FreqSCL = 200000; Рассчитываем частоту работы шины TWI 
 +  .equ FreqTWBR = ((FREQ/​FreqSCL)-16)/​2 
 +   
 +  ldi R16, low(bauddivider);​ Инициализация UART 
 +  sts UBRR0L,​R16 
 +  ldi R16, high(bauddivider) 
 +  sts UBRR0H,​R16 
 +   
 +  ldi R16,0 
 +  sts UCSR0A, R16 
 +  sts UCSR0B, R16 
 +  sts UCSR0C, R16 
 +   
 +  LDI R16, (1<<​RXEN0)|(1<<​TXEN0)|(0<<​RXCIE0)|(0<<​TXCIE0)|(0<<​UDRIE0) 
 +  sts UCSR0B, R16 
 +  ldi r16,0 
 +   
 +  LDI R16, (0<<​USBS0)|(0<<​UMSEL0)|(0<<​UMSEL1)|(1<<​UCSZ00)|(1<<​UCSZ01) 
 +  sts UCSR0C, R16 
 +   
 +   
 +  ldi r16,​0b01000000;​ Инициализация АЦП 
 +  sts ADMUX,r16 
 +  ldi r16,​0b11011111 
 +  sts ADCSRA,​r16 
 +  ldi r25,0 
 +   
 +  rcall W1_Sbros; Сбрасываем шину 1-Wire 
 +  rcall W1_Init_12bit;​ Перестраиваем конфигурационный байт на 12 битную схему работы 
 +  rcall W1_Sbros; Вновь сбрасываем 
 +   
 +  ldi r16,​0b00000101;​ Инициализация работы прерывания по таймеру для отправки показаний 
 +  sts TCCR2B,r16; датчиков DS18B20 по шине 1-Wire 
 +  ldi r16,​0b00000001 
 +  sts TIMSK2,​r16 
 +  sts TIFR2,r16 
 +  ldi r16,0xF0 
 +  sts TCNT2,r16 
 +   
 +  ldi r16,​0b00000101;​ Инициализация работы прерывания по таймеру для отправки показаний 
 +  sts TCCR1B,r16; датчиков DS18B20 по шине 1-Wire 
 +  ldi r16,​0b00000001 
 +  sts TIMSK1,​r16 
 +  sts TIFR1,r16 
 +  ldi r16,0xA0 
 +  sts TCNT1H,​temp 
 +  sts TCNT1L,​temp 
 +   
 +  ldi R16, 0b00110000; Инициализация шины TWI 
 +  out PORTC, R16 
 +  ldi r16,​FreqTWBR 
 +  sts TWBR,r16 
 +  ldi r16,0x00 
 +  sts TWSR,r16 
 +   
 +  clr try 
 +  clr r2 
 +  clr r3 
 +  clr r4 
 +  clr r5 
 +  ldi r24,0x00 
 +  ldi R16, 0b00000000 
 +  out PORTD, R16 
 +   
 +  ldi R16, 0b00000100 
 +  out DDRD, R16 
 +   
 +  rcall i2c_start 
 +  ldi r16,0x46; Если нет, то остаемся этой процедуре 
 +  rcall i2c_send 
 +  ldi r16,0x11 
 +  rcall i2c_send 
 +  rcall i2c_stop 
 +  sei; Разрешаем прерывания 
 +  rjmp main 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  ;​Конец_начальной_инициализации 
 +   
 +   
 +   
 +   
 +  ;​Основная_подпрограмма 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +   
 +   
 +  main: 
 +  cli; Запрещаем прерывания в основном цикле 
 +  push r 
 +  mov r17,r5 
 +  mov r16,r4 
 +  rcall bin2ASCII15 
 +  mov r17,r3 
 +  mov r16,r2 
 +  rcall bin2ASCII15 
 +  popr 
 +  tabulate 
 +   
 +  rcall W1_ConvTemp;​ Говорим датчикам конвертировать температуры 
 +   
 +  push r16 
 +  lds r16,​bh_lux+1 
 +  cpi r16,0x82 
 +  brlo light 
 +  brsh no_light 
 +  light: 
 +  lds r16,​bh_lux 
 +  cpi r16,0x01 
 +  brsh light_exit 
 +  ldi r16,​0b00000100 
 +  out PORTD,r16 
 +  jmp light_exit 
 +  no_light: 
 +  ldi r16,​0b00000000 
 +  out PORTD,r16 
 +  jmp light_exit 
 +  light_exit:​ 
 +   
 +  pop r16 
 +  ldi ZL, LOW(adc_data);​ Производим косвенную адресацию на показания АЦП, чтобы потом их 
 +  ldi ZH, HIGH(adc_data);​ последовательно отправить по UART 
 +  clr r20 
 +  print_adc:; Цикл отправки показаний АЦП 
 +  inc r20 
 +  push r 
 +  ld r17,Z 
 +  adiw ZH:ZL,1 
 +  ld r16,Z 
 +  adiw ZH:ZL,1 
 +  rcall bin2ASCII15 
 +  popr 
 +  tabulate 
 +  cpi r20,4 
 +  brne print_adc; Закончили цикл 
 +  tabulate 
 +   
 +  push r 
 +  lds r17,​bmp_temp;​ Выводим показания датчика BMP180 
 +  lds r16,​bmp_temp+1 
 +  rcall bin2ASCII15 
 +  tabulate 
 +  lds r17,​bmp_pres 
 +  lds r16,​bmp_pres+1 
 +  rcall bin2ASCII15 
 +  tabulate 
 +  lds r17,​bh_lux 
 +  lds r16,​bh_lux+1 
 +  rcall bin2ASCII15 
 +  popr 
 +   
 +  inc r24; Увеличили счетчик кадров и отправили его значение по UART 
 +  newline 
 +   
 +  rcall i2c_start 
 +  ldi r16,0x47 
 +  rcall i2c_send 
 +  rcall i2c_receive 
 +  sts bh_lux,​r16 
 +  rcall i2c_receive_last 
 +  sts bh_lux+1,​r16 
 +  rcall i2c_stop 
 +  sei; Разрешили прерывания,​ чтобы микроконтроллер смог обработать 
 +  ; новые показания АПЦ, термометров и датчика BMP180 
 +  rcall i2c_start 
 +  rjmp main 
 +   
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  ;​Конец_основной_подпрограммы 
 +   
 +  ;​Прерывание_АЦП 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  adc_conv: 
 +  cli; Запрещаем прерывания 
 +   
 +  lds r17,ADCL; Снимаем показания сделанные во время нашего отсутствия в прерывании 
 +  lds r18,ADCH 
 +  cpi r25,0; Смотрим,​ какое число содержится в r25 
 +  breq adc0; Переходим по метке для этого числа 
 +  cpi r25,1 
 +  breq adc1 
 +  cpi r25,2 
 +  breq adc2 
 +  cpi r25,3 
 +  breq adc3 
 +  cpi r25,4 
 +  breq adc4 
 +   
 +  adc0: 
 +  sts adc_data+6,​r18;​ Записываем снятые в начале показания АЦП 
 +  sts adc_data+7,​r17 
 +  ldi r16,​0b01000000;​ Запускаем новое преобразования в зависимости от пина АЦП 
 +  sts ADMUX,r16 
 +  rjmp adc_ex; Переходим на выход 
 +   
 +  adc1: 
 +  sts adc_data,​r18 
 +  sts adc_data+1,​r17 
 +  ldi r16,​0b01000001 
 +  sts ADMUX,r16 
 +  rjmp adc_ex 
 +   
 +  adc2: 
 +  sts adc_data+2,​r18 
 +  sts adc_data+3,​r17 
 +  ldi r16,​0b01000010 
 +  sts ADMUX,r16 
 +  rjmp adc_ex 
 +   
 +  adc3: 
 +  sts adc_data+4,​r18 
 +  sts adc_data+5,​r17 
 +  ldi r16,​0b01000011 
 +  sts ADMUX,r16 
 +  rjmp adc_ex 
 +   
 +  adc4: 
 +  clr r25; Если r25 = 4, очищаем его и прыгаем на adc0 
 +  rjmp adc0 
 +   
 +  adc_ex:ldi r16,​0b11011111;​ Каждый раз повторно инициализируем АЦП 
 +  sts ADCSRA,​r16 
 +  inc r25 
 +  sei 
 +  reti 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  ;​Конец_прерывания_АЦП 
 +   
 +   
 +  ;​Прерывание_таймера1 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  W1_timer: 
 +  cli 
 +   
 +  ldi r16,0x54 
 +  check1 r16 
 +  tabulate 
 +  rcall W1_Sbros; Сбрасываем шину и проверяем есть ли датчик 
 +  ldi YL, LOW(Trm) 
 +  ldi YH, HIGH(Trm) 
 +  ldi ZL,​LOW(Addr1*2) 
 +  ldi ZH,​HIGH(Addr1*2) 
 +  rcall W1_ReadMem; Читаем в ОЗУ текущую температуру 
 +  ldi ZL,​LOW(Addr2*2) 
 +  ldi ZH,​HIGH(Addr2*2) 
 +  rcall W1_ReadMem 
 +  ldi ZL,​LOW(Addr3*2) 
 +  ldi ZH,​HIGH(Addr3*2) 
 +  rcall W1_ReadMem 
 +  ldi ZL,​LOW(Addr4*2) 
 +  ldi ZH,​HIGH(Addr4*2) 
 +  rcall W1_ReadMem 
 +  ldi ZL,​LOW(Addr5*2) 
 +  ldi ZH,​HIGH(Addr5*2) 
 +  rcall W1_ReadMem 
 +  ldi ZL,​LOW(Addr6*2) 
 +  ldi ZH,​HIGH(Addr6*2) 
 +  rcall W1_ReadMem 
 +  ldi ZL,​LOW(Addr7*2) 
 +  ldi ZH,​HIGH(Addr7*2) 
 +  rcall W1_ReadMem 
 +  push f; На всякий случай отправляем в стек SREG 
 +  ldi ZL, LOW(Trm); Делаем косвенную адресацию на массив данных температуры датчиков DS18B20 
 +  ldi ZH, HIGH(Trm) 
 +  clr r20 
 +  print1:; Цикл печати данных 
 +  inc r20 
 +  push r 
 +  ld r16,Z 
 +  adiwZH:​ZL,​1 
 +  ld r17,Z 
 +  adiwZH:​ZL,​1 
 +  rcall bin2ASCII15 
 +  tabulate 
 +  popr 
 +  cpi r20,7 
 +   
 +  brne print1 
 +  newline 
 +  ; Задаем число с которого таймер начнет считать до следующего прерывания 
 +  ldi r22,0xA0 
 +  sts TCNT1H,​r22 
 +  sts TCNT1L,​r22 
 +  popf; Возвращаем SREG из стека 
 +  sei; Разрешаем прерывания 
 +  reti 
 +   
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  ;​Конец_прерывания_таймера1 
 +   
 +  ;​Прерывание_таймера0 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  Board_timer:​ 
 +  cli 
 +   
 +  push f 
 +  mov r16,r2 
 +   
 +  cpi r16,0xFF 
 +  breq r2cap 
 +  inc r2 
 +  jmp btim_exit 
 +  r2cap: 
 +  clr r2 
 +  mov r16,r3 
 +  cpi r16,0xFF 
 +  breq r3cap 
 +  inc r3 
 +  jmp btim_exit 
 +  r3cap: 
 +  clr r3 
 +  mov r16,r4 
 +  cpi r16,0xFF 
 +  breq r4cap 
 +  inc r4 
 +  jmp btim_exit 
 +  r4cap: 
 +  clr r4 
 +  mov r16,r5 
 +  cpi r16,0xFF 
 +  breq r5cap 
 +  jmp btim_exit 
 +  inc r5 
 +  r5cap: 
 +  clr r5 
 +  jmp btim_exit 
 +   
 +  btim_exit:​ 
 +  ldi r22,0xE9 
 +  sts TCNT2,r22 
 +  popf 
 +  sei 
 +  reti 
 +   
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  ;​Конец_прерывания_таймера0 
 +   
 +   
 +   
 +   
 +   
 +  ;​Прерывание_TWI 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  TWI_int: 
 +  cli; Запрещаем прерывания 
 +  push r16; Отправляем в стек r16 
 +  lds r16,TWSR; Сравниваем Статус-регистр TWI  
 +  andi r16,0xF8 
 +  cpi r16,0x08; Если он равен 0x08, то нам надо запустить вычисление  
 +  breq TWI_start_samples_1 
 +  cpi r16,0x10; Если он равен 0х10, то нам надо считывать показания 
 +  breq TWI_read_samples_1 
 +  TWI_exit:​popr16;​ Возвращаем r16 из стека 
 +  sei; Разрешаем прерывания 
 +  reti 
 +   
 +  TWI_start_samples_1:;​ Запускаем вычисление некомпенсированной температуры 
 +  ; Проверяем содержимое переменной try 
 +  cpi try,1; Если 1, то прыгаем на запуск вычисления давления 
 +  breq TWI_start_samples_2 
 +  ldi r16,0xEE; Если нет, то остаемся этой процедуре 
 +  rcall i2c_send 
 +   
 +  ldi r16,0xF4 
 +  rcall i2c_send 
 +   
 +  ldi r16,0x2E 
 +  rcall i2c_send 
 +  rcall i2c_start 
 +  rjmp TWI_exit 
 +   
 +  TWI_start_samples_2:;​ Запускаем вычисление некомпенсированного давления 
 +  ldi r16,0xEE 
 +  rcall i2c_send 
 +   
 +  ldi r16,0xF4 
 +  rcall i2c_send 
 +   
 +  ldi r16,0x34 
 +  rcall i2c_send 
 +  rcall i2c_start 
 +  rjmp TWI_exit 
 +  TWI_read_samples_1:;​ Считываем показания некомпенсированной температуры 
 +  ; Снова проверяем try 
 +  cpi try,1 
 +  breq TWI_read_samples_2 
 +  ldi r16,0xEE 
 +  rcall i2c_send 
 +   
 +  ldi r16,0xF6 
 +  rcall i2c_send 
 +   
 +  rcall i2c_start 
 +   
 +  ldi r16,0xEF 
 +  rcall i2c_send 
 +   
 +  rcall i2c_receive 
 +  sts bmp_temp,​r16 
 +  rcall i2c_receive_last 
 +  sts bmp_temp+1,​r16 
 +  ldi try,​0b00000001 
 +  rcall i2c_stop 
 +  rjmp TWI_exit 
 +  TWI_read_samples_2:​ 
 +  ldi r16,0xEE 
 +  rcall i2c_send 
 +   
 +  ldi r16,0xF6 
 +  rcall i2c_send 
 +   
 +  rcall i2c_start 
 +   
 +  ldi r16,0xEF 
 +  rcall i2c_send 
 +   
 +  rcall i2c_receive 
 +  sts bmp_pres,​r16 
 +  rcall i2c_receive_last 
 +  sts bmp_pres+1,​r16 
 +  ldi try,​0b00000000;​ Уменьшаем try до 0 
 +  rcall i2c_stop 
 +  rjmp TWI_exit 
 +  ;​-------------------------------------------------------------------------------------------------------------- 
 +  ;​Конец_прерывания_TWI 
 +   
 +   
 +  ​Addr1:.db0x28,​0xFF,​0x41,​0x3,​0xA3,​0x15,​0x1,​0xBB;​ Адреса датчиков DS18B20 
 +  Addr2:.db0x28,​0xFF,​0xE2,​0x1A,​0xA2,​0x15,​0x4,​0xF9 
 +  Addr3:.db0x28,​0xFF,​0x91,​0xF,​0xA3,​0x15,​0x4,​0xC8 
 +  Addr4:.db0x28,​0xFF,​0x90,​0x82,​0xA3,​0x15,​0x4,​0x41 
 +  Addr5:.db0x28,​0xFF,​0xC6,​0xB,​0xA3,​0x15,​0x4,​0x2 
 +  Addr6:.db0x28,​0xFF,​0x9,​0x5D,​0xA3,​0x15,​0x4,​0x9E 
 +  Addr7:.db0x28,​0xFF,​0x7F,​0x83,​0xA3,​0x15,​0x4,​0x7B 
 +   
 +   
 +   
 +  Delay: ; Стандартная задержка 
 +  push f 
 +  ldi razr1, 50 
 +  ldi razr2, 10 
 +  Pdelay: 
 +  dec razr1 
 +  brne Pdelay 
 +  dec razr2 
 +  brne Pdelay 
 +  popf 
 +  ret 
 +  Delay1: ; Стандартная задержка 1 
 +  push f 
 +  ldi razr1, 50 
 +  ldi razr2, 50 
 +  ldi razr3, 1 
 +  Pdelay1: 
 +  dec razr1 
 +  brne Pdelay1 
 +  dec razr2 
 +  brne Pdelay1 
 +  dec razr3 
 +  brne Pdelay1 
 +  popf 
 +  ret 
 +  </​code>​ 
 +</​hidden>​
  
 +\\
 +====Текст модуля 1wire.asm====
 +<hidden развернуть>​
 +<code asm>
 +  ;​1-wire_подпрограммы
 +  ;​--------------------------------------------------------------------------------------------------------------
 +  ​
 +  ​
 +  W1_Sbros: ​    ; Сброс шины и проверка датчик на месте ли
 +  lds r16, W1_BIT ; Записываем в r16 ножку где датчик
 +  sbi W1_DDR, W1_BIT ; Ногу на выход
 +  cbi W1_PORT, W1_BIT ; Опрокидываем вывод на землю
 +  rcall W1_DelayH ; Задержка 480 мкс, для сброса
 +  cbi W1_DDR, W1_BIT ; Ногу на вход
 +  rcall W1_DelayI ; Ждем тайм слот 70 мкс
 +  sbis W1_PIN, W1_BIT ; Пропускаем следующую строку,​ если бит порта в 1
 +  ldi r17, 1  ; И установим сигнальный регистр в 1
 +  sbic W1_PIN, W1_BIT ; Пропускаем следующую строку,​ если бит порта в 0
 +  ldi r17, 0  ; И установим сигнальный регистр в 0
 +  rcall W1_DelayJ ; Ждем тайм слот 410 мкс
 +  ret    ; Если датчик на месте, в r17 по выходу отсюда будет 1, в противном случае 0
 +  ​
 +  W1_Address:
 +  clr r20
 +  read:
 +  inc r20  ; Процедура считывания адреса датчиков DS18B20
 +  in r10,SREG
 +  push r10
 +  lpm r16,Z
 +  rcall ds_byte_wr
 +  pop r10
 +  out SREG,r10
 +  adiw ZH:ZL,1
 +  cpi r20,8
 +  brne read
 +  ret
 +  ​
 +  W1_ReadMem: ​    ; Чтение памяти регистров температуры
 +  ldi  r16, 0x55  ; Пошлем команду 0x55, это сравнить уникальный номер датчика
 +  rcall  ds_byte_wr ​ ; Так как он у нас один на проводе
 +  rcall  W1_Address ; Отправляем адрес датчика
 +  ldi  r16, 0xBE  ; Говорим датчику,​ что мы сейчас будем читать
 +  rcall  ds_byte_wr ​ ; Запуливаем байт
 +  rcall ds_byte_rd ​ ; А тут уже начинаем читать,​ прочитали первый
 +  st Y, r16  ; И запулили его в память,​ по метке Trm
 +  adiw YH:YL,1
 +  rcall ds_byte_rd ​ ; Читаем второй
 +  st Y, r16  ; И запулили его в память,​ по метке Trm+1
 +  adiw YH:YL,1
 +  rcall W1_Sbros ​ ; Сбрасываем шину и проверяем есть ли датчик
 +  ;ldi ZL,​LOW(Addr2*2)
 +  ;ldi ZH,​HIGH(Addr2*2)
 +  ;clr r20
 +  ret
 +  ​
 +  W1_ConvTemp: ​    ; Подпрограмма конвертирования температуры
 +  ldi r16, 0xCC  ; Пропускаем уникальный номер датчика
 +  rcall ds_byte_wr
 +  ldi r16, 0x44  ; Говорим что надо бы сконвертировать температуру,​ этот процесс занимает 750
 +  rcall ds_byte_wr ​ ; миллисекунд,​ поэтому идем что-то делать,​ или ленится
 +  ret
 +  ​
 +  W1_Init_12bit: ​    ; Подпрограмма перестройки на 12 бит температуры
 +  ldi r16, 0xCC   ; Пропускаем уникальный номер датчика
 +  rcall ds_byte_wr ​ ; Спуливаем в датчик
 +  ldi r16, 0x4E  ; Говорим что сейчас будем писать в RAM регистры датчика
 +  rcall ds_byte_wr ; Спуливаем в датчик
 +  ldi r16, 0xFF ; 0xFF записываем в первые 2 регистра,​ это регистры температуры,​ он нам не 
 +  rcall ds_byte_wr ; нужен, поэтому их оставляем в стандартном состоянии
 +  ldi r16, 0xFF ; 0xFF второй байт температуры
 +  rcall ds_byte_wr ; Спуливаем на порт
 +  ldi r16, 0x7F ; А вот тут говорим что 12 бит - 7F, или 1F  - 9бит, 3F - 10 бит, 5F - 11 бит ​
 +  rcall ds_byte_wr ; Спуливаем на порт
 +  ret
 +  ​
 +  ds_byte_rd: ​    ; Подпрограмма чтения данных в регистр r16 с 1 Wire
 +  ldi r17, 8   ; Пишем в r17 - 8, т.к. у нас в бит в регистре
 +  clr r16   ;​Чистим r16, сюда будем читать данные
 +  ds_byte_rd_0:​
 +  sbi W1_DDR, W1_BIT ; Вывод на выход
 +  cbi W1_PORT, W1_BIT ; Опрокидываем вывод на землю
 +  rcall W1_DelayA ; Ждем 6 микросекунд
 +  cbi W1_DDR, W1_BIT ; Вывод на вход
 +  rcall W1_DelayE ; Ждем 9 микросекунд
 +  sbis W1_PIN, W1_BIT
 +  clc   ; Очищаем бит C = 0
 +  sbic W1_PIN, W1_BIT
 +  sec   ; Очищаем бит C = 1
 +  ror r16  ; Производим циклический сдвиг вправо через С
 +  rcall W1_DelayF ; Ждем 55 микросекунд
 +  dec r17  ;​Понижаем на 1 регистр r17
 +  brne ds_byte_rd_0 ; если не равен 0 вращаемся в цикле
 +  ret
 +  ​
 +  ds_byte_wr: ​    ; Подпрограмма записи данных из регистра r16 в датчик ​
 +  ldi r17, 8  ; Пишем в r17 - 8, т.к. у нас в бит в регистре
 +  ds_byte_wr0: ​
 +  sbi W1_DDR, W1_BIT ; Вывод на выход
 +  cbi W1_PORT, W1_BIT ; Опрокидываем вывод на землю
 +  sbrc r16, 0  ; Проверим,​ в r16 бит 0 очищен или установлен ​
 +  rjmp ds_byte_write_1 ; Если установлен перейдем по этой метке
 +  rjmp ds_byte_write_0 ; Если очищен перейдем по этой метке
 +  ds_byte_wr1:​
 +  lsr r16  ; Логический сдвиг вправо
 +  dec r17  ; Понижаем r17 на 1 
 +  brne ds_byte_wr0 ; Если не равен 0, вращаемся в цикле
 +  ret   ; Выход из подпрограммы
 +  ​
 +  ds_byte_write_0: ​   ; Запись 0
 +  rcall W1_DelayC ; Ждем 60 микросекунд
 +  cbi W1_DDR, W1_BIT ; Вывод на вход
 +  rcall W1_DelayD ; Ждем 10 микросекунд
 +  rjmp ds_byte_wr1
 +  ​
 +  ds_byte_write_1: ​  ; Запись 1
 +  rcall W1_DelayA ; Ждем 6 микросекунд
 +  cbi W1_DDR, W1_BIT ; Вывод на вход
 +  rcall W1_DelayB ; Ждем 64 микросекунд
 +  rjmp ds_byte_wr1
 +  ​
 +  W1_DelayA: ​    ; Задержка 6 mcs
 +  ldi XH, high(FREQ/​2000000)
 +  ldi XL, low(FREQ/​2000000)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayB: ​    ; Задержка 64 mcs
 +  ldi XH, high(FREQ/​130000)
 +  ldi XL, low(FREQ/​130000)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayC: ​    ; Задержка 60 mcs
 +  ldi XH, high(FREQ/​136000)
 +  ldi XL, low(FREQ/​136000)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayD: ​    ; Задержка 10 mcs
 +  ldi XH, high(FREQ/​1000000)
 +  ldi XL, low(FREQ/​1000000)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayE: ​    ; Задержка 9 mcs
 +  ldi XH, high(FREQ/​1200000)
 +  ldi XL, low(FREQ/​1200000)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayF: ​    ; Задержка 55 mcs
 +  ldi XH, high(FREQ/​150000)
 +  ldi XL, low(FREQ/​150000)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayH: ​    ; Задержка 480 mcs
 +  ldi XH, high(FREQ/​16664)
 +  ldi XL, low(FREQ/​16664)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayI: ​    ; Задержка 70 mcs
 +  ldi XH, high(FREQ/​116000)
 +  ldi XL, low(FREQ/​116000)
 +  rcall W1_Delay
 +  ret
 +  W1_DelayJ: ​    ; Задержка 410 mcs
 +  ldi XH, high(FREQ/​19512)
 +  ldi XL, low(FREQ/​19512)
 +  rcall W1_Delay
 +  ret
 +  W1_Delay: ​    ; Подпрограмма воспроизведения задержки
 +  sbiw XH:XL, 1 ; Вычитаем единицу из регистровой пары
 +  brne W1_Delay ; Если не равно 0 крутимся в цикле
 +  ret   ; Выход из подпрограммы
 +  ;​--------------------------------------------------------------------------------------------------------------
 +  ;​Конец_1-wire_подпрограмм
 +</​code>​
 +</​hidden>​
 +\\
 +====Текст модуля hextobcd.asm====
 +<hidden развернуть>​
 +<code asm>
 +  .def fASCIIL =r16
 +  .def tASCII0 =r16
 +  .def fASCIIH =r17
 +  .def tASCII2 =r25
 +  .def tASCII3 =r19
 +  .def tASCII4 =r20
 +  .def tASCII1 =r21
 +  .def cnt16a =r21
 +  .def tmp16a =r22
 +  .def tmp16b =r23
 +  ​
 +  ;***** Код
 +  print_ascii:​
 +  check1 r20
 +  check1 r19
 +  check1 r25
 +  check1 r21
 +  check1 r16
 +  ret
 +  bin2ASCII15: ​
 +  ldi tmp16a, low(10000)
 +  ldi tmp16b, high(10000)
 +  rcall bin2ASCII_digit
 +  mov tASCII4, cnt16a
 +  ldi tmp16a, low(1000)
 +  ldi tmp16b, high(1000)
 +  rcall bin2ASCII_digit
 +  mov tASCII3, cnt16a
 +  ldi tmp16a, low(100)
 +  ldi tmp16b, high(100)
 +  rcall bin2ASCII_digit
 +  mov tASCII2, cnt16a
 +  ldi tmp16a, low(10)
 +  ldi tmp16b, high(10)
 +  rcall bin2ASCII_digit
 +  ldi r17,0x30
 +  add r16,r17
 +  add r21,r17
 +  add r25,r17
 +  add r19,r17
 +  add r20,r17
 +  rcall print_ascii
 +  ret
 +  bin2ASCII_digit: ​
 +  ldi cnt16a, -1
 +  bin2ASCII_digit_loop: ​
 +  inc cnt16a
 +  sub fASCIIL, tmp16a
 +  sbc fASCIIH, tmp16b
 +  brsh bin2ASCII_digit_loop
 +  add fASCIIL, tmp16a
 +  adc fASCIIH, tmp16b
 +  ​
 +  ret
 +</​code>​
 +</​hidden>​
 +\\
 +====Текст модуля iterrupts.asm====
 +<hidden развернуть>​
 +<code asm>
 +  ;​Векторы_прерываний
 +  ;​-----------------------------------------------------------------------
 +  ​
 +  .org 0x0000 ​   ; Reset
 +  jmp RESET
 +  .org 0x0002 ​   ; External Interrupt Request 0
 +  reti
 +  .org 0x0004 ​   ; External Interrupt Request 1
 +  reti
 +  .org 0x0006 ​   ; Pin Change Interrupt Request 0
 +  reti
 +  .org 0x0008 ​   ; Pin Change Interrupt Request 1
 +  reti
 +  .org 0x000A ​   ; Pin Change Interrupt Request 2
 +  reti
 +  .org 0x000C ​   ; Watchdog Time-out Interrupt
 +  reti
 +  .org 0x000E ​   ; Timer/​Counter 2 Compare Match A
 +  reti
 +  .org 0x0010 ​   ; Timer/​Counter 2 Compare Match B
 +  reti
 +  .org 0x0012 ​   ; Timer/​Counter 2 Overflow
 +  jmp Board_timer
 +  .org 0x0014 ​   ; Timer/​Counter 1 Capture Event
 +  reti
 +  .org 0x0016 ​   ; Timer/​Counter 1 Compare Match A
 +  reti
 +  .org 0x0018 ​   ; Timer/​Counter 1 Compare Match B
 +  reti
 +  .org 0x001A ​   ; Timer/​Counter 1 Overflow
 +  rjmp W1_timer
 +  ;reti
 +  .org 0x001C ​   ; Timer/​Counter 0 Compare Match A
 +  reti
 +  .org 0x001E ​   ; Timer/​Counter 0 Compare Match B
 +  reti
 +  .org 0x0020 ​   ; Timer/​Counter 0 Overflow
 +  reti
 +  .org 0x0022 ​   ; SPI Serial Transfer Complete
 +  reti
 +  .org 0x0024 ​   ; USART, Rx Complete
 +  reti
 +  .org 0x0026 ​   ; USART, UDR Empty
 +  reti
 +  .org 0x0028 ​   ; USART, Tx Complete
 +  reti
 +  .org 0x002A ​   ; ADC Conversion Complete
 +  jmp adc_conv
 +  .org 0x002C ​   ; EEPROM Ready
 +  reti
 +  .org 0x002E ​   ; Analog Comparator
 +  reti
 +  .org 0x0030 ​   ; Two-wire Serial Interface
 +  jmp TWI_int
 +  ;reti
 +  .org 0x0032 ​   ; Store Program Memory Read
 +  reti
 +  ​
 +  .org INT_VECTORS_SIZE
 +</​code>​
 +</​hidden>​
 +\\
 +====Текст модуля macr.asm====
 +<hidden развернуть>​
 +<code asm>
 +  ;​Макросы
 +  ;​-----------------------------------------------------------------------
 +  .macro pushf
 +  push r10
 +  in r10,SREG
 +  push r10
 +  .endm
 +  .macro popf
 +  pop r10
 +  out SREG,r10
 +  pop r10
 +  .endm
 +  .macro pushr
 +  push r10
 +  in r10,SREG
 +  push r10
 +  push r16
 +  push r17
 +  push r18
 +  push r19
 +  push r20
 +  push r21
 +  push r22
 +  push r23
 +  push r25
 +  push r26
 +  push r27
 +  push r28
 +  push r29
 +  .endm
 +  .macro popr
 +  pop r29
 +  pop r28
 +  pop r27
 +  pop r26
 +  pop r25
 +  pop r23 
 +  pop r22
 +  pop r21
 +  pop r20
 +  pop r19
 +  pop r18
 +  pop r17
 +  pop r16
 +  pop r10
 +  out SREG,r10
 +  pop r10
 +  .endm
 +  .macro check
 +  push @0
 +  lds @0,@1
 +  sts UDR0,@0
 +  check_loop: ldi @0,UCSR0A
 +  sbrs @0,TXC0
 +  rjmp check_loop
 +  pop @0
 +  rcall Delay
 +  .endm
 +  ​
 +  .macro check_kosv
 +  push @0
 +  ld @0,@1
 +  sts UDR0,@0
 +  check_loop1:​ ldi @0,UCSR0A
 +  sbrs @0,TXC0
 +  rjmp check_loop1
 +  pop @0
 +  rcall Delay
 +  .endm
 +  .macro check1
 +  sts UDR0,@0
 +  check_loop1:​ ldi @0,UCSR0A
 +  sbrs @0,TXC0
 +  rjmp check_loop1
 +  rcall Delay
 +  .endm
 +  ​
 +  .macro tabulate
 +  push r16
 +  ldi r16,0x09
 +  check1 r16
 +  pop r16
 +  .endm
 +  .macro newline
 +  push r16
 +  ldi r16,0x0D
 +  check1 r16
 +  ldi r16,0x0A
 +  check1 r16
 +  pop r16
 +  .endm
 +</​code>​
 +</​hidden>​
  
-  +\\ 
-Delay: ; Стандартная задержка +====Текст модуля twi_lib.asm==== 
- pushf +<​hidden ​развернуть> 
- ldi razr1,​ 50 +<code asm>
- ldi razr2,​ 10 +
-Pdelay: +
- dec razr1 +
- brne Pdelay +
- dec razr2 +
- brne Pdelay +
- popf +
- ret +
-Delay1: ; Стандартная задержка 1 +
- pushf +
- ldi razr1,​ 50 +
- ldi razr2,​ 50 +
- ldi razr3,​ 1 +
-Pdelay1: +
- dec razr1 +
- brne Pdelay1 +
- dec razr2 +
- brne Pdelay1 +
- dec razr3 +
- brne Pdelay1 +
- popf +
- ret +
-</code asm>+
  
 +  ;​Библиотека_TWI
 +  ;​-----------------------------------------------------------------------
 +  ​
 +  ;======= Стартовая посылка по шине i2c =================================================
 +  i2c_start:
 +  push r16 
 +  ldi r16,​(1<<​TWINT)|(1<<​TWSTA)|(1<<​TWEN)|(1<<​TWIE) ; Выполняем посылку стартовой комбинации
 +  sts TWCR,r16 ; Посылаем полученный байт в TWCR
 +  rcall i2c_wait ; Ожидание формирования start в блоке TWI
 +  pop r16 ; Возвращаем данные в r16 из стека
 +  ret
 +  ;======= Стоповая посылка по шине i2c ==================================================
 +  i2c_stop:
 +  push r16 
 +  ldi r16,​(1<<​TWINT)|(1<<​TWSTO)|(1<<​TWEN) ; Отправляем стоповую посылку
 +  sts TWCR,r16 ; Посылаем полученный байт в TWCR
 +  pop r16 ; Возвращаем данные в r16 из стека
 +  ret
 +  ;======= Посылка байта информации по шине i2c ==========================================
 +  i2c_send:
 +  push r16
 +  sts TWDR,r16 ; Записываем передаваемый байт в регистр TWDR
 +  ldi r16,​(1<<​TWINT)|(1<<​TWEN)|(1<<​TWIE) ; Формируем байт, отвечающий ​
 +  ; за пересылку информационного байта
 +  sts TWCR,r16 ; Посылаем полученный байт в TWCR
 +  rcall i2c_wait ; Ожидание окончания пересылки байта
 +  pop r16 ; Возвращаем данные в r16 из стека
 +  ret
 +  ;======= Приём информационного байта по шине i2c =======================================
 +  i2c_receive:​
 +  ; Принятый байт помещается в регистр r16, поэтому рекомендуется ​
 +  ; продумать программу так, чтобы в этот момент в нём не было ​
 +  ; важной информации,​ байт не сохраняется в стеке в коде данной ​
 +  ; процедуры
 +  ldi r16,​(1<<​TWINT)|(1<<​TWEN)|(1<<​TWEA)|(1<<​TWIE) ; Формируем байт, отвечающий за прием ​
 +  sts TWCR,r16 ; Посылаем полученный байт в TWCR
 +  rcall i2c_wait ; Ожидание окончания приёма байта
 +  lds r16,TWDR ; Считываем полученную информацию из TWDR
 +  ret
 +  ;======= Приём последнего байта (NACK) =================================================
 +  i2c_receive_last:​
 +  ; Принятый байт помещается в регистр r16, поэтому рекомендуется ​
 +  ; продумать программу так, чтобы в этот момент в нём не было ​
 +  ; важной информации,​ байт не сохраняется в стеке в коде данной ​
 +  ; процедуры
 +  ldi r16,​(1<<​TWINT)|(1<<​TWEN)|(1<<​TWIE) ; Формируем байт, отвечающий за прием информационного байта
 +  sts TWCR,r16 ; Посылаем полученный байт в TWCR
 +  rcall i2c_wait ; Ожидание окончания приёма байта
 +  lds r16,TWDR ; Считываем полученную информацию из TWDR
 +  ret
 +  ;======= Ожидание готовности TWI =======================================================
 +  i2c_wait:
 +  lds r16,TWCR ; Загружаем значение из TWCR в r16
 +  sbrs r16,TWINT ; Функция ожидания выполняется до тех пор, пока поднят флаг ​
 +  ; прерывания в 1
 +  rjmp i2c_wait
 +  ret
 +  ;​=======================================================================================
 +</​code>​
 +</​hidden>​
doc/1201/643.mgul.12013-01_12_01.1487027347.txt.gz · Последние изменения: 2018/04/28 23:47 (внешнее изменение)