Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение dr.doc »

Мой аналитический склад ума дошел до того, что это либо импульсы на тахометр идут не ровно, а у меня замеряет между двух импульсов период...
Скорее всего идут от датчика положения коленвала. А на нем, как правило, несколько "зубов" отсутствуют. Поэтому без фильтрации и гистерезиса и будет "дергать". Фильтр позволит уменьшить гистерезис.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Я же скорость считываю, а не обороты... :roll:
Возможно и там может быть тот факт, что где-то импульсы пропускает. Спидометр на это не реагирует, т.к. там инерционность большая, конденсаторы стоят какие-нибудь.
А у меня реагирует на каждый чих.
Станислав
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение dr.doc »

Точно. Попутал. просто недавно знакомый про своего американца данные искал и у него получалось 4000 имп/миля. Но последовательность была неравномерной. Возможно мозг выдавал пачки, использую что-либо вроде ABS.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Вот. Уже ближе к делу! У меня Тойота, на ней, как мне удалось найти, 2548 импульсов на километр. Схемку хочу сделать универсальную. На Тойотах самые меделнные импульсы (их меньше всего). На других автопромах их больше.
Чтобы измерить такие медленные импульсы я и сделал две переменные, т.к. у ТИНИ13 нет 16 разрядного таймера. Как и посоветовали, при каждом переполнении таймера делаю инкремент переменной. Получился таймер 16 разрядный. ))) По сохраненным значениям в памяти МК видно, что их достаточно, да и в ручную я посчитал, что при 4,8 МГц и делителе таймера на 256, один тик таймера будет 0,000213 секунды.
Станислав
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Demiurg »

Я асм почти окончательно забросил. Делюсь некоторыми советами для тех кто еще верен асму животворящему :)))
Шаблон. Главный файл. pattern.asm:
Спойлер

Код: Выделить всё

//==================
.nolist
.include   "m32def.inc"
.list
//==================

//=============== Функции и глобальные определения проекта ===============
//----------
#define NO   0
#define YES 1
//----------

//----------
#define TINY 0
#define MEGA 1
//----------

//----------
#define NO_CHANGE 0
#define CHANGE 1
//----------

//----------
#define tab_h(x) HIGH(x), LOW(x)
#define tab_l(x) LOW(x), HIGH(x)
//----------

//----------
#define WORK   0
#define DEBUG   1
//==================

//==================
#define PROJECT         DEBUG // WORK //

#define CPU_TYPE      MEGA

#define WATCH_DOG      NO_CHANGE

#define EEPROM         YES
//==================

//==================
.equ   XTAL   = 8000000
//==================

//==================
//---------- List used register ----------
//                           n/u - Not Used
//                     = r0   result multiply
//                     = r1   result multiply
.def   RCLR            = r2
.def   RSER            = r3
.def   RSREG            = r4
.def   EEDREG            = r5
.def   KEYS_PREV         = r6
.def   KEYS_CURRENT      = r7
.def   ADC_PUMP_SPEED      = r8
//                     = r9
//                     = r10
//                     = r11
//                     = r12
//                     = r13   n/u
//                     = r14   Used.
//                     = r15   Used.
//----------
.def   TEMP            = r16 // Used. Everywhere
//                     = r17   Used. Everywhere
//                     = r18   Used. Everywhere
//                     = r19   Used. Everywhere
.def   FSM_STATE         = r20
.def   FSM_FLAGS         = r21
.def   CNT               = r22
.def   FLAGS            = r23
.def   POINT_ENTRY_L      = r24 // adiw/sbiw
.def   POINT_ENTRY_H      = r25 // adiw/sbiw
//                     = r26   XL
//                     = r27   XH
//                     = r28   YL
//                     = r29   YH
//                     = r30   ZL
//                     = r31   ZH
//==================

//==================
.set   NUM_FLG = -1

.macro Def_Flag
.set NUM_FLG = (NUM_FLG+1)
.set @0 = NUM_FLG
.if   (NUM_FLG<=7)
.message "Flag Defined!"
.else
.error "Flag Not Defined"
.endif
.endmacro

.set   NUM_ERR = 0

.macro Def_Err_ID
.set NUM_ERR = (NUM_ERR+1)
.set @0 = NUM_ERR
.message "Number Error Defined!"
.endmacro

.macro   End_Table
.db      0xFF, 0xFF
.endmacro
//==================

#if (PROJECT==DEBUG)

//==================
.equ   TEST_LED_PORT   = PORTD
.equ   TEST_LED_DDR   = DDRD
.equ   TEST_LED_PIN   = PIND

.equ   TEST_LED      = PD7
//----------

//----------
.macro   test_led_on
   in         r16, TEST_LED_DDR
   setb      r16, TEST_LED
   out         TEST_LED_DDR, r16
.endmacro

.macro   test_led_off
   in         r16, TEST_LED_DDR
   clrb      r16, TEST_LED
   out         TEST_LED_DDR, r16
.endmacro
//==================

#endif

//==================
.include   "vectors_m32.inc"

.include   "library.inc"

.include   "proc_errors.inc"

.include   "system_timer.inc"

.include   "fsm.inc"

.include   "prototreads.inc"

.include   "in_out_def.inc"

.include   "in_out_lib.inc"

.include   "val_def.inc"

.include   "kbd_drv_def.inc"

.include   "kbd_drv.inc"

.include   "proc_menu.inc"
//************************************************************************

.dseg
.org 0x200

rdata:
.byte 6

.cseg

//************************************************************************
Reset:
//----------
   Clear_Registers
//----------

//----------
   clr      RCLR
   ser      r16
   mov      RSER, r16
   clr      FLAGS
//----------

//----------
   Init_Stack // Инициализация стека.
//----------

//----------
   Clear_SRAM // Очистка ОЗУ.
//----------

//----------
   Init_System_Timer // Инициализация системного таймера.
//----------

//----------
   Init_WDT
//----------

//----------
   Init_Sleep_Mode
//----------

//---------- Отладка ----------
#if (PROJECT==DEBUG)

#endif
//==================

   sei

//==================
Main:
   wdr
   rcall   Service_Timers
   rcall   KBD_DRV
   rcall   Proc_Menu
   rjmp   Main
//==================



В конце заголовочный файлов на конкретные МК есть таблицы векторов. Для каждого используемого МК делаем отдельный файл по этому примеру. vectors_m32.inc:
Спойлер

Код: Выделить всё

.cseg

.org   0x0000
      rjmp   Reset

; ***** INTERRUPT VECTORS ************************************************
.org   INT0addr            ; External Interrupt Request 0
      reti

.org   INT1addr            ; External Interrupt Request 1
      reti

.org   INT2addr            ; External Interrupt Request 2
      reti

.org   OC2addr               ; Timer/Counter2 Compare Match
      reti

.org   OVF2addr            ; Timer/Counter2 Overflow
      reti

.org   ICP1addr            ; Timer/Counter1 Capture Event
      reti

.org   OC1Aaddr            ; Timer/Counter1 Compare Match A
      reti

.org   OC1Baddr            ; Timer/Counter1 Compare Match B
      reti

.org   OVF1addr            ; Timer/Counter1 Overflow
      reti

.org   OC0addr               ; Timer/Counter0 Compare Match
      rjmp   Sys_Timer_Comp

.org   OVF0addr            ; Timer/Counter0 Overflow
      reti

.org   SPIaddr               ; Serial Transfer Complete
      reti

.org   URXCaddr            ; USART, Rx Complete
      reti

.org   UDREaddr            ; USART Data Register Empty
      reti

.org   UTXCaddr            ; USART, Tx Complete
      reti

.org   ADCCaddr            ; ADC Conversion Complete
      reti

.org   ERDYaddr            ; EEPROM Ready
      reti

.org   ACIaddr               ; Analog Comparator
      reti

.org   TWIaddr               ; 2-wire Serial Interface
      reti

.org   SPMRaddr            ; Store Program Memory Ready
      reti
;----------

;----------
.org   INT_VECTORS_SIZE      ; size in words
;===================



Шаблон конечного автомата (этакое ядро конечного автомата) с переходом по индексу-состоянию.
Спойлер

Код: Выделить всё

.cseg

//==================
.macro Proc_FSM
   ldz      @0*2
   rjmp   _Proc_FSM
.endmacro

_Proc_FSM:
   lpm      XH, Z+ ; Считывание старшего байта адреса состояния автомата.
   lpm      XL, Z+ ; Считывание младшего байта адреса состояния автомата.
   ld      r16, X ; Считывание состояния автомата.
   lpm      r17, Z+ ; Считывание количества состояний автомата.
   cp      r16, r17
   brsh   Process_Errors_FSM
   lpm      XH, Z+
   lpm      XL, Z
   movw   ZH:ZL, XH:XL
   add      ZL, r16
   adc      ZH, RCLR
   shiftlwz
   lpm      r17, Z+
   lpm      r16, Z
   movw   ZH:ZL, r17:r16
   ijmp
Process_Errors_FSM:
   cli
   adiw   ZL, 2
   lpm      r16, Z
   rjmp   Proc_Errors
//==================

//==================
Set_FSM_State:
   st         Y, FSM_STATE
   ret
//==================

//==================
//Proc_FSM_Exit:
//   st         Y, FSM_FLAGS
//   std         Y+1, FSM_STATE
//   ret
//==================


Пример использования шаблона конечного автомата:
Спойлер

Код: Выделить всё

KBD_DRV:
   pushiwl      Kbd_Drv_Save_Val // Эти две строки - манипуляция со стеком. В стек загоняется эта подпрограмма.
                                                            // После выхода из конечного автомата прыгаем сюда, сохраняем данные,
                                                            // после этого возвращаемся в место, откуда вызвали конечный автомат.
                                                            // если толком не знаете как работает стек, и как им манипулировать,
                                                            // не используйте этот прием.
   pushiwl      Define_Keys          //

   ldy         _KEYS
   ldd         FSM_STATE, Y+DISP_KEYS
   ldd         FSM_FLAGS, Y+DISP_KEYS_FLAGS

   Scan_Keys // Макрос сканирование кнопок. Дефайнами подставляются нужные функции. Порт\Матрица\Несколько портов.
   Proc_FSM   Tab_FSM_KBD_DRV

//==================
Kbd_Drv_Save_Val:
   std      Y+DISP_KEYS, FSM_STATE
   std      Y+DISP_KEYS_FLAGS, FSM_FLAGS
   ret
//==================

Keys_Init:
   ser         r16
   mov         KEYS_PREV, r16
   mov         KEYS_CURRENT, r16
   std         Y+DISP_KEYS_BUF, r16
   Set_State   _KEYS_NONE
   ret

Tab_FSM_KBD_DRV:
.db      tab_h(_KEYS), MAX_FSM_KBD_DRV_STATES, tab_h(Tab_Jmp_KBD_DRV), ERR_ID_KBD_DRV

Tab_Jmp_KBD_DRV:
.equ   MAX_FSM_KBD_DRV_STATES   = 5 // Количество состояний автомата.

.equ   _KEYS_INIT            = 0
.db      tab_h(Keys_Init)

.equ   _KEYS_NONE            = 1
.db      tab_h(Keys_None)

.equ   _KEYS_DOWN            = 2
.db      tab_h(Keys_Down)

.equ   _KEYS_WAIT_UP         = 3
.db      tab_h(Keys_Wait_Up)

.equ   _KEYS_UP            = 4
.db      tab_h(Keys_Up)


До кучи набор макросов, подпрограмм.
Спойлер

Код: Выделить всё

.macro   clrb
   cbr      @0,1<<@1
.endmacro

.macro   setb
   sbr      @0,1<<@1
.endmacro

.macro sfbs
   lds      r16,@0
   sbrs   r16,@1
.endmacro

.macro sfbc
   lds      r16,@0
   sbrc   r16,@1
.endmacro

.macro stfb
   lds      r16,@0
   sbr      r16,@1
   sts      @0,r16
.endmacro

.macro clfb
   lds      r16,@0
   cbr      r16,@1
   sts      @0,r16
.endmacro

.macro   ldiw
   ldi      @0,High(@2)
   ldi      @1,Low(@2)
.endmacro

.macro   ldx
   ldi      XH,High(@0)
   ldi      XL,Low(@0)
.endmacro

.macro   ldy
   ldi      YH,High(@0)
   ldi      YL,Low(@0)
.endmacro

.macro   ldz
   ldi      ZH,High(@0)
   ldi      ZL,Low(@0)
.endmacro

.macro   pushx
   push   XL
   push   XH
.endmacro

.macro   pushy
   push   YL
   push   YH
.endmacro

.macro   pushz
   push   ZL
   push   ZH
.endmacro

.macro   popx
   pop      XH
   pop      XL
.endmacro

.macro   popy
   pop      YH
   pop      YL
.endmacro

.macro   popz
   pop      ZH
   pop      ZL
.endmacro

.macro   stsi
   ldi      r16,@1
   sts      @0,r16
.endmacro

.macro   stsiw
   ldi      r16,high(@1)
   sts      @0+1,r16
   ldi      r16,low(@1)
   sts      @0,r16
.endmacro

.macro   outi
   ldi      r16,@1
   out      @0,r16
.endmacro

.macro outiw
   ldi      r16,high(@1)
   out      @0H,r16
   ldi      r16,low(@1)
   out      @0L,r16
.endmacro

.macro adi
   subi   @0,-@1
.endmacro

.macro adci
   sbci   @0,-@1
.endmacro

.macro addiw
   subi   @0L,LOW(-@1)
   sbci   @0H,HIGH(-@1)
.endmacro

.macro cpw
   cp      @0,@1
   cpc      @2,@3
.endmacro

.macro subiw
   subi   @0L,LOW(@1)
   sbci   @0H,HIGH(@1)
.endmacro

.macro addw
   add      @0L,@1
   adc      @0H,@2
.endmacro

.macro shiftlwz
   lsl      ZL
   rol      ZH
.endmacro

.macro shiftrw
   lsr      @0H
   ror      @0L
.endmacro

.macro         INIT_STACK
.ifdef   SPH
   outi   SPH,HIGH(RAMEND)
.endif
   outi   SPL,LOW(RAMEND)
.endmacro

.macro   INIT_WATCH_DOG
   outi   WDTCR,1<<WDTOE | 1<<WDE ;  | 1<<WDP2 | 1<<WDP1 | 1<<WDP0
.endmacro

.macro   INIT_SLEEP_MODE
   in      r16,MCUCR
   sbr      r16,1<<SE
   out      MCUCR,Temp
.endmacro

.macro   INIT_EXT_INT0
   in      r16,MCUCR
   sbr      r16,1<<ISC00 | 1<<ISC01
   out      MCUCR,Temp
   in      r16,GICR
   sbr      r16,1<<INT0
   out      GICR,r16
.endmacro

.macro   INIT_EXT_INT1
   in      r16,MCUCR
   sbr      r16,1<<ISC10 | 1<<ISC11
   out      MCUCR,Temp
   in      r16,GICR
   sbr      r16,1<<INT1
   out      GICR,r16
.endmacro

.macro   INIT_EXT_INT2
   in      r16,MCUCR
   sbr      r16,1<<SE
   out      MCUCR,Temp
   in      r16,MCUCSR
   sbr      r16,1<<ISC2
   out      MCUCSR,Temp
   in      r16,GICR
   sbr      r16,1<<INT2
   out      GICR,r16
.endmacro

.macro   INIT_TIMER0
   out      TCNT0,RCLR
   in      r16,TIMSK
   sbr      r16,1<<OCIE0
   out      TIMSK,r16
   outi   OCR0,(XTAL/64/1000)
   outi   TCCR0,1<<CS00 | 1<<CS01
.endmacro

.macro   INIT_TIMER1
   in      r16,TIMSK
   sbr      r16,1<<OCIE1A
   out      TIMSK,r16
   out      TCNT1H,Zero
   out      TCNT1L,Zero

   ldi      r16,High(36)
   out      OCR1AH,r16
   ldi      r16,Low(36)
   out      OCR1AL,r16 ; При частоте кварца 7,3728 Мгц число 72=10 мс.

   ldi      r16,0x05
   out      TCCR1B,r16
.endmacro

.macro   INIT_TIMER2
   out      TCNT2,RCLR
   in      r16,TIMSK
   sbr      r16,1<<OCIE2
   out      TIMSK,r16
   outi   OCR2,(XTAL/64/1000)
   outi   TCCR2,4
.endmacro

.macro   Case
   cpi      STREG,@0
   brne   Exit_Case
   rjmp   @1
Exit_Case:
.endmacro

.macro   Case_Not_Equal
   cpi      STREG,@0
   breq   Exit_Case
   rjmp   @1
Exit_Case:
.endmacro

.macro   Read_State
   lds      r16,@0
.endmacro

.macro   Set_State
   ldi      r16,@1
   sts      @0,r16
.endmacro

.macro   Set_Mode
   ldi      r16,@1
   sts      @0,r16
.endmacro

.macro   Check_States
   cpi      r16,@0
   brlo   Check_States_Exit
   rjmp   @1
Check_States_Exit:
.endmacro

.macro   Read_Last_State
   lds      r17,@0
.endmacro

.macro   ClearRegisters
   clr      r0
   clr      r1
   clr      r2
   clr      r3
   clr      r4
   clr      r5
   clr      r6
   clr      r7
   clr      r8
   clr      r9
   clr      r10
   clr      r11
   clr      r12
   clr      r13
   clr      r14
   clr      r15

   clr      r16
   clr      r17
   clr      r18
   clr      r19
   clr      r20
   clr      r21
   clr      r22
   clr      r23
   clr      r24
   clr      r25
   clr      r26
   clr      r27
   clr      r28
   clr      r29
   clr      r30
   clr      r31
.endmacro

.macro   Set_State
   ldi      FSM_STATE, @0
.endmacro

.macro Clear_Registers
   clr      ZH
   ldi      ZL, 30
Clear_Register_Cycle:
   dec      ZL
   st      Z, ZH
   brne   Clear_Register_Cycle
.endmacro

;*************************************************************************
;=========== SRAM ====================
;*************************************************************************

.macro   OUT_SRAM
   ldi      XH,HIGH(@0)
   ldi      XL,LOW(@0)
   ldi      Data_H,HIGH(@1)
   ldi      Data_L,LOW(@1)
   rcall   _OUT_SRAM
.endmacro

.macro   OUTI_SRAM
   ldi      XH,HIGH(@0)
   ldi      XL,LOW(@0)
   ldi      r17,@1
   ldi      r16,@2
   rcall   _OUT_SRAM
.endmacro

_OUT_SRAM:
   st      X+,r16
   dec      r17
   brne   _OUT_SRAM
   ret

.macro   Copy_SRAM
.if @3==YES
   push   YH
   push   YL
.endif
   ldi      XH,HIGH(@0)
   ldi      XL,LOW(@0)
   ldi      YH,HIGH(@1)
   ldi      YL,LOW(@1)
   ldi      r17,@2
   rcall   _Copy_SRAM
.if @3==YES
   pop      YL
   pop      YH
.endif
.endmacro

_Copy_SRAM:
   ld      r16,X+
   st      Y+,r16
   dec      r17
   brne   _Copy_SRAM
   ret

.macro   Clear_SRAM
   ldx      SRAM_START
Clear_SRAM_Cycle:
   st      X+,RCLR
   cpi      XL,LOW(SRAM_START+SRAM_SIZE)
   brne   Clear_SRAM_Cycle
   cpi      XH,HIGH(SRAM_START+SRAM_SIZE)
   brne   Clear_SRAM_Cycle
.endmacro
;*************************************************************************

;*************************************************************************
;========== EEPROM ===================
;*************************************************************************

;Так как возможна случайная запись в EEPROM в случае сбоя питания, то:
;1 - В микроконтроллере включить контроль снижения напряжения питания.
;2 - Первый (0x00) байт никогда не используется.
;3 - После ресета обнулить указатель адреса EEPROM.
;Решения для увеличения ресурса EEPROM:
;4 - Перед записью считывается байт, предназначенный для записи,
;проверяется на равенство с записываемым, если байты равны, то переход
;к записи следующего байта.
;5 - В конце работы с EEPROM обнулить указатель адреса.

#if (EEPROM==YES)

.macro Read_EEPROM
   ldix   @0 ; Указатель адреса EEPROM.
   ldiy   @1 ; Указатель адреса SRAM.
   ldi      r17,@2
   rcall   _Read_EEPROM
.endmacro

_Read_EEPROM:
   sbic   EECR,EEWE
   rjmp   _Read_EEPROM
.ifdef EEARH
   out      EEARH,XH
.endif
   out      EEARL,XL
   sbi      EECR,EERE
   sbi      EECR,EERE
   in      EEDREG,EEDR
   st      Y+,EEDREG
   adiw   XL,1
   dec      r17
   brne   _Read_EEPROM
_Read_EEPROM_0:
   sbic   EECR,EEWE
   rjmp   _Read_EEPROM_0
.ifdef EEARH
   out      EEARH,RCLR
.endif
   out      EEARL,RCLR
   ret

EERead:
   sbic   EECR,EEWE
   rjmp   EERead
.ifdef EEARH
   out      EEARH,XH
.endif
   out      EEARL,XL
   sbi      EECR,EERE
   sbi      EECR,EERE
   in      EEDREG,EEDR
EERead_1:
   sbic   EECR,EEWE
   rjmp   EERead_1
.ifdef EEARH
   out      EEARH,RCLR
.endif
   out      EEARL,RCLR
   ret

EEWrite:
   sbic   EECR,EEWE
   rjmp   EEWrite
.ifdef EEARH
   out      EEARH,XH
.endif
   out      EEARL,XL
   out      EEDR,EEDREG
   sbi      EECR,EEMWE
   sbi      EECR,EEWE
EEWrite_1:
   sbic   EECR,EEWE
   rjmp   EEWrite_1
.ifdef EEARH
   out      EEARH,RCLR
.endif
   out      EEARL,RCLR
   ret

.macro Write_EEPROM
   ldiy   @0 ; Указатель адреса SRAM.
   ldix   @1 ; Указатель адреса EEPROM.
   ldi      r17,@2
   rcall   _Write_EEPROM
.endmacro

_Write_EEPROM:
   sbic   EECR,EEWE
   rjmp   _Write_EEPROM
.ifdef EEARH
   out      EEARH,XH
.endif
   out      EEARL,XL
   ld      EEDREG,Y+
   out      EEDR,EEDREG
   sbi      EECR,EEMWE
   sbi      EECR,EEWE
   adiw   XL,1
   dec      r17
   brne   _Write_EEPROM
_Write_EEPROM_0:
   sbic   EECR,EEWE
   rjmp   _Write_EEPROM_0
.ifdef EEARH
   out      EEARH,RCLR
.endif
   out      EEARL,RCLR
   ret

.macro   Clear_EEPROM
   ldx      @0
   ldy      @1
   rcall   _Clear_EEPROM
.endmacro

_Clear_EEPROM:
   sbic   EECR,EEWE
   rjmp   _Clear_EEPROM
.ifdef EEARH
   out      EEARH,XH
.endif
   out      EEARL,XL
   out      EEDR,RCLR
   sbi      EECR,EEMWE
   sbi      EECR,EEWE
   adiw   XL,1
   sbiw   YL,1
   brne   _Clear_EEPROM
_Clear_EEPROM_0:
   sbic   EECR,EEWE
   rjmp   _Clear_EEPROM_0
.ifdef EEARH
   out      EEARH,RCLR
.endif
   out      EEARL,RCLR
   ret

#endif
;*************************************************************************

/************************************************************************/
#if (BCD==YES)

.dseg

HEX_DEC_BUFFER:
.equ   HEX_DEC_BUFFER_LENGHT = 5
.byte   HEX_DEC_BUFFER_LENGHT


.cseg

Hex_Dec:
   ldx      HEX_DEC_BUFFER
   ldi      r17,HIGH(10000)
   ldi      r16,LOW(10000)
   rcall   Digit
   st      X+,r18
   ldi      r17,HIGH(1000)
   ldi      r16,LOW(1000)
   rcall   Digit
   st      X+,r18
   ldi      r17,HIGH(100)
   ldi      r16,LOW(100)
   rcall   Digit
   st      X+,r18
   ldi      r17,HIGH(10)
   ldi      r16,LOW(10)
   rcall   Digit
   st      X+,r18
   mov      r16,r14
   ori      r16,0x30
   st      X+,r16
Hex_Dec_End:
   ret

Digit:
   ldi      r18,-1
Digit_Cycle:
   inc      r18
   sub      r14,r16
   sbc      r15,r17
   brsh   Digit_Cycle
   add      r14,r16
   adc      r15,r17
   ori      r18,0x30
   ret
#endif
/************************************************************************/

/************************************************************************/
Empty_Action:
   ret
/************************************************************************/

/************************************************************************/
Table_Bits:
.db 0b00000001, 0b00000010, 0b00000100, 0b00001000
.db 0b00010000, 0b00100000, 0b01000000, 0b10000000
/************************************************************************/

/************************************************************************/
.macro end_array
.db 0xFF,0xFF
.endmacro
/************************************************************************/

Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Вот устроили из темы срач холиварный. :facepalm: Эту часть надо вырезать и отнести в МЯЯЯУ.
А у меня тем временем глюки с моей программулиной даже в Протеусе. Не могу понять в чем дело. Возможно и прерывания гонят. Хотя, не должны. В эмуляторе же крутил много раз программу, там тупо крутится в главном цикле и выполняет условия. Однако, почему-то умудряется погасить один светодиод не тогда, когда надо, должен гасить оба сразу. А даже команды во всем тексте такой нет, где он гасит один светодиод... :facepalm:
Не пойму, как он умудряется это сделать.
и когда совсем импульсов нет, соответственно нет и прерываний. Почему тогда он не выключает их иной раз? :facepalm:

Код: Выделить всё

Start:   

      cp  ONBlL, PERIODL
      cpc  ONBlH, PERIODH
      brsh ONB

       rjmp T
      
   ONB: sbi PORTB, 2
 
   T:   cp  ONTumL, PERIODL    ; Если
      cpc  ONTumH, PERIODH
      brsh ONT

       rjmp O

   ONT: sbi PORTB, 0

   O:   cp  OFFL, PERIODL     ; Сравниваем с настоящим значением накопленного
      cpc  OFFH, PERIODH   ; Если начисленное больше, то выключаем (скорость сильно маленькая)
      brlo OFF

      rjmp Start      

   OFF: cbi PORTB, 0
       cbi PORTB, 2

   rjmp   Start   ; Конец программы, переход на начало
Станислав
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Z_h_e »

Когда все работает, но иногда глючит причиной зачастую является ошибка сохранения флагов в обработчике прерывания или регистров. Поверьте ка что там у Вас.
Сказочник писал(а):Вот устроили из темы срач холиварный. :facepalm:
Жирный плюс Вам за остановку этого беспредела.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Demiurg »

СКАЗОЧНИК писал(а):...

Программа не вся. У вас там строка есть, если начисленное больше, то выключаем, а команда стоит brlo. Или считается что если PERIOD больше?

Если происходит что-то необъяснимое, то локализуем ошибку. В вашем случае гаснет один светодиод. Значит, предполагаемые причины: в прерывании не сохраняется-восстанавливается SREG, какой-нибудь регистр. Работа с портом в прерывании и в основном цикле.

Какие функции еще выполняет пин? Может вы режим какой включаете, из-за чего гаснет светодиод.

Также следует не исключать ошибку самого протеуса. Для отладки программ лучше AVR-Studio 4.19 ничего нет. Так как это продукт самого ATMEL, то симулятор симулирует максимально приближенно к правде. Если же у студии и есть какие косяки с симулированием, то они известны.

Лично я пользуюсь всегда только студией, если нужно проверить программу. Протеусом пользовался для проверки пару раз максимум. Когда нужно было быстро проверить работоспособность связки. символьный дисплей, семисегментный дисплей.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19045
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Starichok51 »

СКАЗОЧНИК писал(а):Вот устроили из темы срач холиварный.

на правах модератора удалил весь устроенный срач холиварный...
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Z_h_e писал(а):ошибка сохранения флагов в обработчике прерывания или регистров

:dont_know: А там я делал по вашему совету. :) Т.е. использовал флаг прерывания таймера, т.к. он меньше по приоритету, чем внешнее прерывание по фронту/спаду.
Ой! Точно, в таймере флаги то используются! Сейчас исправлю! :beer:
Спойлер

Код: Выделить всё

; ----------
; ОБРАБОТЧИКИ ПРЕРЫВАНИЙ
; ----------

   INT0add:

      push temp                  ; Закидываем в стек темп
      in temp, SREG               ; Закидываем в стек СРЕГ
      push temp

         in temp, TIFR0            ; Проверка флага переполнения таймера
         andi temp, (1<<1)         ; Накладываем маску, если 1 бит был единицей, то он и останется, все остальные будут 0. Если он 0, то будет флаг Z
         breq NOFLAG               ; Нет флага (стоит Z), значит уходим, иначе обрабатываем флаг
            out TIFR0, temp         ; В темп уже есть этот флаг, как 1, снова его запихиваем и тем самым скинем флаг
            inc OVF               ; Добавляем еще одно переполнение к таймеру
            
            
      NOFLAG: in PERIODL, TCNT0      ; Считываем значение младшего
            mov PERIODH, OVF      ; Считываем занчение старшего
            
            clr OVF               ; Чистим все для очередного замера
            out TCNT0, OVF
      
      pop temp                  ; Вытаскиваем из стека СРЕГ
      out SREG, temp      
      pop temp                  ; Вытаскиваем из стека темп         

   reti

;----------

   OVF0add:

      inc OVF

      cpi OVF, 251
      brsh OVER
      reti

      OVER: ldi OVF, 250

   reti


Demiurg писал(а):а команда стоит brlo. Или считается что если PERIOD больше?

Да, именно так. Если период больше всего всего, то значит импульс слишком длинный и давно пора выключить все нагрузки. ))) Даже алгоритм пришлось рисовать для этого на листочке. Вообще все конспектирую и стараюсь рисовать. Так понятнее разбираться.
Demiurg писал(а):в прерывании не сохраняется-восстанавливается SREG, какой-нибудь регистр. Работа с портом в прерывании и в основном цикле.

Demiurg писал(а):Может вы режим какой включаете, из-за чего гаснет светодиод.

Вот. В прерывании сохраняю регистры. Во втором прерывании с ними не работаю, поэтому и не трогаю. С портами не работаю в прерывании, Тини13, там альтернативных функций не так много, поэтому использую порт как есть и всего один INT0. Все... :dont_know:
Demiurg писал(а):Для отладки программ лучше AVR-Studio 4.19 ничего нет.

Тоже так думаю. Но сама студия в отладке показывает = все прекрасно. Даже с эмуляцией прерываний и т.д. и т.п. Все значения обрабатывает идеально.
Глючить начинает Протеус и Железо. Причем, как-то одинаково почти. В Протеусе я подаю импульсы с генератора, а в реальной жизни от спидометра на Тойота Спасио. И там и там моргает... А когда частота спидометра/генератора снижается, то выключается ближний свет, в то время, когда выключиться должны только вместе при самой маленькой скорости. Даже в программе нет такой строчки, где отдельное выключение порта... Только одновременно. :dont_know:

В Протеусе начал проверять, просто от безысходности. Дома нет возможности реальное железо тестировать, т.к. нет датчика скорости (или его эмулятора). Обычно Протеусом вообще не пользуюсь...

Не знаю. Буду сидеть и думать до конца. Хочу доделать это устройство. Результатами обязательно всеми поделюсь. Может кто полезное для себя возьмет или найдет.
Если кому будет интересно, выложу проект Протеуса и Прошивку.

Благодарю всех за проявленный интерес!

Starichok51 писал(а):на правах модератора

:) :beer:

З.Ы. В верху неправильный подсчет написал по времени периода таймера.
Вот правильный:
СпойлерЧастота МК 4,8 МГц. Тмк = 0,000000208 с.
Частота таймера 4,8 МГц/256 = 18750 Гц. Ттайм = 0,000053333 с.
Полный счет таймера 256 TCNT0 и еще 250 переполнений (так ограничивает прерывание), получается за примерно 3,4 с.
Минимальный период импульса указан выше = 0,0000533333 с.
Т.е. таймер может считать от f = 0.294 Гц, до f = 18750 Гц.
Мои подсчеты по замерам на реальном автомобиле при скорости в районе 5 км/ч fимп. = 8,75 Гц или Тимп. = 0,1143 с.
А при скорости 200 км/ч fимп. = 141,844 Гц или Тимп. = 0,007 с.
Запас есть, как не крути. :roll:


Думаю, надо считать несколько импульсов за период времени... или несколько импульсов измерять период, а потом вычислять среднее арифметическое, как и раньше говорил(и).
Станислав
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Z_h_e »

СКАЗОЧНИК писал(а):В Протеусе начал проверять, просто от безысходности.
Протеус отлично средство отладки, просто надо понимать что это всего лишь эмулятор, но Вашу задачу он легко съест.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

У меня еще комп его плохо тянет. и иной раз виснет. :)
Станислав
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Z_h_e »

Виснет часто тоже. Тут приходится играться, бывает добавляешь резистор не в тему, просто не подключенный и опять все заработало. А по скорости, если убрать аналоговую часть, то работает в реальном режиме времени.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Все. Тема моя походу умерла сама собой. )))) Я только что осознал, что в городе есть светофоры и пешеходные переходы... И каждое снижение скорости или остановка будут гасить туманки и второй ближний свет. Лампам придет писец еще быстрее... :facepalm: Вот блин.

У кого есть предложения, куда еще можно применять эту плату? Может использовать ее как отсечку для Жигулей? А то у меня просили. :)))
Станислав
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Demiurg »

СКАЗОЧНИК писал(а):...

Смириться, успокоив себя тем, что получил бесценный опыт. Отрицательный результат - тоже результат.
А наработки когда-нибудь пригодятся в другом устройстве.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение WiseLord »

А ввести два режима - город и трасса? В одном ничего такого не делать (или делать иначе), в другом - переключать фары как задумано.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Хороший вариант. ))) Все равно решили эту схему доделывать, но изменили немного критерии и включили в работу задержки, т.е. если стоим более 10 секунд, то выключить свет. А город-трасса - тоже есть, можно включить в ручную все. А можно в автоматическом режиме через эту конструкцию.
Сейчас буду додумывать.
Спасибо.
Станислав
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение ILYAUL »

Код: Выделить всё

;----------

   OVF0add:

      inc OVF

      cpi OVF, 251
      brsh OVER
      reti


   reti

Команда CPI меняет регистр SREG. Когда Вы научитесь сохранять этот регистр , если применяете команды его изменяющие?
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

В прерываниях у меня сохраняется этот регистр. Уже )))) :dont_know:
Станислав
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение akl »

СКАЗОЧНИК писал(а): ...Мои подсчеты по замерам на реальном автомобиле при скорости в районе 5 км/ч fимп. = 8,75 Гц или Тимп. = 0,1143 с. А при скорости 200 км/ч fимп. = 141,844 Гц или Тимп. = 0,007 с.
Уточню. Если при скорости 200 км/3600сек измерено 141,844 имп./сек, то датчик выдает 2553 имп/км. В общем, ожидаемо. Чего нельзя сказать про скорость 5км/час. Должно получиться 3,54 имп./сек.
Ответить

Вернуться в «AVR»