Здесь показаны различия между двумя версиями данной страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
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==== |
+ | <hidden развернуть> | ||
<code asm> | <code asm> | ||
- | awdasd | + | ;---------------------------------------------------- |
+ | ; Program : telemetry_rev1-1 | ||
+ | ; Compiler : AVRA | ||
+ | ; Chip type : ATmega328P | ||
+ | ; 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> | ||
+ | |||
+ | \\ | ||
+ | ====Текст модуля twi_lib.asm==== | ||
+ | <hidden развернуть> | ||
<code asm> | <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> |