Перейти к содержанию
    

Исходники программ и библиотек

Исходники на Си для работы МК с симистором, ЖКИ, клавиатурами, энкодером, I2C, UART и многое другое

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Собрал библиотеку avr-libc-1.7.1 с патчем far pointer для WInAVR. Пытался найти готовую на просторах, но не нашёл. Вдруг кому будет интересно.

Источник: http://savannah.nongnu.org/patch/?6352

avr_libc_1.7.1_fp.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Flash память AT25080,AT25160,AT25320,AT25640

В программе, написанной на ассемблере, данные пишутся и читаются по SPI интерфейсу из AT25080. Было бы полезно, дополнять описания на микросхемы чем-либо подобным.

Flash_AT25080.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ассемблер! Как много в этом слове... В общем сделал для себя небольшой комплект макросов для работы с сигналами, событиями и флагами. Сигналы - эл.сигналы подключенные к МК. За описанием сигнала скрыт реальный пин порта к которому тот подключен. Вариант небольшого HAL. События и флаги - то, что происходит в программе и её состояние. 8 флагов и 8 событий. Это просто биты в двух выделенных регистрах, но я сделал макросы удобной работы с ними. Теперь сложнее ошибиться и код читабельнее получается. По крайней мере для меня. Ну и ещё сделал немного доп.команд. Что-то сам придумал, а что-то из инета почерпнул. Все макросы объединил в файл MyMacros.inc и подключаю во все свои проекты. Далее для всего сделанного реализовал подсветку синтаксиса для студии 4 (файл AvrStudio_asm.ini). Им надо переписать дефолтный файл и после этого можно будет изменять цвет в IDE. Ну и последнее что сделал - расширил и перекомпилировал хелп файл студии (опять-же Avr Studio 4) для поддержки справкой добавленных макросов и команд. Кому всё ещё интересно матёрое программирование на асме - прошу заценить. Жду Ваши комментарии и пожелания. :biggrin:

ExtCmd.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Комментариев и пожеланий к моему прошому посту не последовало - выкладываю новую версию. В ней исправлены некоторые ошибки и добавлено описание как это использовать.

ExtCmd.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Шаблоны проектов на C++ для AVR [GCC, IAR]

 

Шаблоны: https://mysvn.ru/avr/templates/

Примеры: https://mysvn.ru/avr/examples/

 

Экспортировать из репозитория к себе можно при помощи плагина к проводнику: TortoiseSVN.

 

Шаблоны для микроконтроллеров: ATtiny2313, ATmega48, ATmega16, ATmega32, ATmega128.

 

Особенности шаблонов:

1. Проекты шаблонов собраны таким образом, что компилируются в двух C++ компиляторах: avr-gcc и iar.

2. Каждый шаблон имеет класс CMCU, который является программной моделью микроконтроллера AVR.

3. Обработка событий (прерываний) осуществляется через соответствующие методы класса CMCU, которые имеют соответствующие названия (обработчики "включаются" в файле Configuration.h).

4. Код максимально самодокументирован, вплоть до отдельных настроечных битов конфигурационных регистров.

5. В каждый проект шаблона включён заголовочный файл с классом CVersion. Этот класс создаётся автоматически перед каждой компиляции проекта (и в iar, и в gcc). Его назначение - автоматически отслеживать номер версии прошивки в стиле: Major.Minor.Revision.Build, где первое число изменяется от 0 до 9, второе от 0 до 99, а последние два от 0 до 9999. Также в классе есть метод, возвращающий дату билда в виде строки. Строка находится во флеш.

6. Первоначально проекты шаблонов настроены для работы с WinAVR-20100110 и IAR 6.10.

7. Каждый шаблон имеет возможность однообразного описания декларации переменных и одномерных массивов, которые должны находится во флеш. При использовании специального C++ шаблона умного указателя (SmartPtr.h) можно забыть про функции типа pgm_read_byte() и eeprom_read_byte(). С++ компилятор автоматически вызовет эти функции для чтения данных из флеш или eeprom.

8. Для тех, кто умеет пользоваться VS2008, в каждой папке есть GCC проект для этой IDE, в котором можно работать над проектом. Сборка идёт через Makefile.

 

Назначение:

1. Переход на C++ с C или ассемблера.

2. Небольшие проекты без сильных требований к быстродействию, т.е. там где не нужны в большом количестве ассемблерные вставки. Их можно подключать и в шаблонах, но только в качестве исключения (обработка прерываний, к примеру).

3. Для тех, кому нравится ООП или хочет писать с использованием ООП на AVR.

 

Ограничения и недостатки:

1. При использовании двумерных массивов, которые должны находится во флеш, теряется кросс-компиляция (возможно в новых версиях GNU компилятора это можно будет делать также как в IAR, тогда доделаю).

2. Шаблоны пока ещё не готовы на 100%, в них могут быть неточности в плане описания регистров или битов. Нужно быть внимательными.

 

Дополнительная информация:

 

1. По ссылке на шаблоны проектов можно найти проекты, которые настроены по дефолту, где практически всё закомментировано (инициализация). Проекты собираются и в IAR, и в WinAVR и имеют самый минимальный размер. Потренироваться можно, к примеру, на ATtiny2313. В AVR Studio 4.xx загрузить плагин Proteus'а и там исследовать прошивку, используя виртуальную внутрисхемную отладку. Либо можно взять модуль Console.cpp из демо-примеров и в том же Proteus'е по виртуальному нуль модему общаться с моделируемым мк. Это чтобы не городить схем, очень удобно всё можно посмотреть в реальном времени, только в последнем случае рекомендую выставлять частоту 4 МГц и скорость 9600, хотя это в зависимости от мощности ПК, я думаю.

 

2. Поддержка двух компиляторов ведена также и для экспериментальных целей. Почти все исходники по ссылкам компилируются в обоих компиляторах и прошивки должны работать почти идентично. Раньше мне нравилось отлаживать по JTAG'у в IAR, теперь вот в AVR Studio или Proteus это делаю. Получается более широкое поле по исследованию работы различных версий программы мк.

 

3. В Makefile включены специальные директивы, которые выбрасывают из объектного файла все неиспользуемые функции. Будьте внимательны, если вдруг размер кода будет меньше или наоборот больше, если закомментируете их.

 

4. Переходник ISRList.cpp для методов, которые обрабатывают прерывания, кушает до полукилобайта кода, если включить все прерывания (т.е. просто включить и больше ничего). Это связано с тем, что методы класса CMCU при этом не могут быть inline. Поэтому в мк, где размер флеша мал, этот модуль отсутствует и его содержимое перенесено в конец модуля MCU.cpp. Это значительно экономит место.

 

5. Автоматическая работа с версией работает только в Windows-системе, т.е. для генерации файла Version.h используется WSH. Для IAR скрипты запускаются в настройке проекта: пре- и постбилд, для WinAVR это прописано в Makefile. Можно увидеть в исходниках во всех проектах файл Version.h в нём содержится информация о дате последнего билда проекта и собственно номер версии.

 

6. Все проекты настроены для работы в VS2008. Этому есть причины: Visual Assist, Visual SVN, DevExpress ... и ещё много чего, что есть для этой IDE, которая заточена под разработку C++ проектов. Это удобно, что не мешает использовать что-то своё (IAR, к примеру, его проект находится в папке iar6). Проект VS2008 настроен так, что позволяет перепрыгивать на ошибки из окна вывода (вывод компилятора преобразуется потоковым фильтром).

 

7. Примеры использования шаблонов в связке с C или ассемблером можно увидеть в демо-примерах. Некоторые из них (uSD) работают в Proteus в реальном времени и можно общаться с контроллером через терминал, что позволяет лучше понять работу программы, можно увидеть и "потрогать" всё прямо почти живьём.

 

В общем и целом, я хотел какого-то единообразия для всех своих проектов и получил его. Можете пользоваться, если мой подход кому-то будет интересен. Самый интересный более менее демо-проект, который можно попробовать ничего не собирая - это микро файловый менеджер на ATmega16 - проект uSD. Вот как выглядит окно терминала при подключении к моделируемой схеме в Proteus (в железе тоже работает и куда шустрее модели):

 

post-15809-1366538381_thumb.png

 

По-проще можно посмотреть на проект PhaseControl. Это фазовое управление коллекторным двигателем с использованием симистора. Схема моделировалась в Proteus на мк ATtiny2313, потом собирался действующий макет. К сожалению, коллекторного движка пока не нашлось, поэтому управлял асинхронником на 250 Вт. Работать работает, но нужно ещё доделывать программу управления, а точнее регулировку угла и слежение за нулём на каждом периоде синусоиды. Если не считать нестабильной работы движка, то расчётные и реальные осциллограммы практически совпадают, хотя модель та ещё (реальные измерения производились развязанным цифровым осциллографом, и вообще, трансформатора нет, поэтому думайте, прежде чем что-то подключать к реальной такой схеме).

 

Вот можно посмотреть на модель и графики. Даже на ATtiny2313 я тоже пишу на C++ с использованием шаблона проекта.

 

post-15809-1366555027_thumb.png post-15809-1366555071_thumb.png

Изменено пользователем uni

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Шаблоны проектов на C++ для AVR [GCC, IAR]

 

Шаблоны: https://mysvn.ru/avr/templates/

Примеры: https://mysvn.ru/avr/examples/

 

Экспортировать из репозитория к себе можно при помощи плагина к проводнику: TortoiseSVN.

 

Шаблоны для микроконтроллеров: ATtiny2313, ATmega48, ATmega16, ATmega32, ATmega128.

.....

Очень интересно, спасибо будем пробовать!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ассемблер! Как много в этом слове... В общем сделал для себя небольшой комплект макросов для работы с сигналами, событиями и флагами. Кому всё ещё интересно матёрое программирование на асме - прошу заценить. Жду Ваши комментарии и пожелания. :biggrin:

 

Deka, для AVR есть графический ассемблер Algorithm Builder (АБ), раз в 5 удобней, чем классический ассемблер.

Поэтому не имеет смысла писать на классическом ассемблере, тем более, что сейчас АБ бесплатный.

Похоже, некоторые Ваши предложения там сделаны на уровне компилятора.

При написании на АБ быстро пришел к тому, что практически не использую имен регистров, бит.

Скажем, у меня команда для включения вентилятора будет выглядеть так:

vkl_FAN, а для выключения, естественно, vykl_FAN.

Если вентилятор подключен к PORTB.0, эти команды представляют собой макросы:

1 -> PORTB.0 и 0 -> PORTB.0.

 

В АБ масса удобств, например, подпрограммы с параметрами.

При их использовании, например, умножение двух двухбайтных переменных А и В можно записать одной строчкой:

Umnojenie(A,B)

 

Думаю, при наличии хорошего отладчика писать и отлаживать программы на АБ проще и быстрее, чем на СИ.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ага, конечно нет смысла писать на классическом ассемблере :)

Как-то разбирался я со схемой, которая должна была формировать импульсы длительностью 0,8 мкс частотой 200 Гц и измерять время между этими импульсами и ответами от другого устройства. Так вот нагородили там огород из атмеги256 и плисины. На вопрос зачем так сложно последовал ответ- на одном микроконтроллере невозможно точно отсчитать время. А всё почему? Потому что подсели на С и не знают теперь сколько по времени выполняются команды. Реально можно вполне было обойтись атмегой8 без всяких плисин.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Потому что подсели на С и не знают теперь сколько по времени выполняются команды. Реально можно вполне было обойтись атмегой8 без всяких плисин.
Зависит от того, с какой точностью надо было измерять задержку. Если не менее 1/Fcpu, то подумав и задействовав модули захвата и сравнения таймера процессор мог бы делать еще какую-то полезную работу кроме измерения количества потраченных впустую тактов. Даже если программу написать на Си. Легко. А если нужна бОльшая точность, то без внешних элементов не обойтись хоть в машинных кодах пишите.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

NEC IR приемник для AVR

 

; DATE: 12.01.2014
; Модуль для работы с  NEC IR пультами 
; Результат по завершению приема находится в
; четырех регистрах Address L, Address H,Data N, Data Invert ! 
; Пока держим кнопку, данные сохраняются в регистрах ! 




; NEC IR receive bytes 
;.def   bytei = R11   ; Инвертированный байт команды
;.def   byten = R12   ; Нормальный байт команды
;.def   adrh  = R13   ; Адрес старший
;.def   adrl  = R14   ; Адрес младший 


; OSC 10.000 MHz   
; NEC IR constants init 
; all constants are true ms values ! 
.equ   FCLK      = 10000000            ; Тактовая частота в герцах 10 МГц NEC IR DECODER ! 
.equ   IR_pin    = PIND                ; регистр порта D входы
.equ   IR        = PD2                 ; IR receiver INT0 pin 
.equ   pre       = 8                   ;  Прескаллер таймера 1 
.equ   const     = (FCLK/10000)/pre    ; 125 (1.25 real) 1 тик таймера = 1,25 мкс
.equ   starth    = (9000*const)/100    ; первая посылка 9,0мс  
.equ   startl    = (4500*const)/100    ; вторая посылка 4,5мс    
.equ   log1      = (2250*const)/100    ; прием логической 1  (2,250мс)
.equ   restart   = log1                ; Посылка 4,5ms + 2.250ms = повтор  
.equ   log0      = (1125*const)/100    ; прием логического 0 (1,125мс)
.equ   IRcL      = (100*const)/100     ; Константа погрешности 100uS  
.equ   IRcH      = (200*const)/100     ; Константа погрешности 200uS  
.equ   repeat    = 65535-((110000*const/8)/100) ; рестарт посылка после принятых данных через 110 ms


; Это вписываем после инициализации STACK  
;************************;
;**** INIT T1 & INT0 ****;

; INT0 falling mode     ; 
;ldi     tmp,(1<<ISC01)|(0<<ISC00)  ; 
;out     MCUCR,tmp        ; 
;ldi     tmp,(1<<INT0)    ; 
;out     GICR,tmp         ; 
; TIMER_1                 ; 
;                         ; 0-STOP, 1-/1, 2-/8, 3-/64, 4-/256, 5-/1024. OVF mode 
;ldi     tmp,0x01         ; ICNC1, ICES1, –, WGM13, WGM12, CS12, CS11, CS10.
;out     TCCR1B,tmp       ; 
;clr     tmp              ; clear TIMER1 registers 
;out     TCCR1A,tmp       ; 
;out     TCNT1H,tmp       ;
;out     TCNT1L,tmp       ;
;out     OCR1AH,tmp       ; 
;out     OCR1AL,tmp       ; 
;out     OCR1BH,tmp       ; 
;out     OCR1BL,tmp       ; 
;out     ICR1H,tmp        ; 
;out     ICR1L,tmp        ; 
;out     TIFR,tmp         ; 
;in      tmp,TIMSK        ; OCIE2, TOIE2, TICIE1, OCIE1A, OCIE1B, TOIE1, –, TOIE0. 
;ori     tmp,(1<<TOIE1)   ; 
;out     TIMSK,tmp        ; ;out     TIMSK,tmp        ;  



;*******************************************************************************
****
IR_read:                 ; Регистры cnt,tmp,X,Z !
push    tmp              ; сохранить tmp в STACK
in      tmp,SREG         ; прочитать содержимое SREG в tmp 
push    tmp              ; сохранить tmp в STACK
push    xl               ; сохранить XL в STACK
push    xh               ; сохранить XH в STACK
push    zl               ; сохранить ZL в STACK
push    zh               ; сохранить ZH в STACK
cli                      ; выключить прерывания 
inc     cnt              ; INT0 counter + 1
cpi     cnt,1            ; IF cnt  = 1 -> goto IR_9ms 
breq    IR_9ms           ; сброс T1, запуск счета, прерывание по фронту, ловим 9мс ! 

cpi     cnt,2            ; IF cnt  = 2 -> goto IR_start 
breq    IR_start         ; принимаем старт 9 мс (+ - 200us) ! 

cpi     cnt,3            ; IF cnt  = 3 -> goto IR_repeat_OR_normal start ! 
breq    IR_repeat        ; Проверяем повтор команды ! Или передача посылки с данными !  

cpi     cnt,4            ; IF cnt >= 4 -> goto IR_data
brsh    GET_data         ; то принимаем данные 

rjmp    IR_error         ; если 0 - выходим из прерывания 

Get_data:                ; метка перехода
rjmp    GET_IR_data      ; прием данных 32 бита ! LSB first 


IR_9ms:                  ; 
ldi     tmp,(1<<ISC01)|(1<<ISC00)  ;  INT0 - rising 
out     MCUCR,tmp        ;              
ldi     flags,0x01       ; Flags = 1
rcall   read_T1          ; Z = TCNT1    
rjmp    IR_ok            ; выходим из прерывания WAIT Hi level on INT0 ! 

IR_start:                ; 9.136 ms NORMAL !  INT0 - rising cnt=1 !
ldi     tmp,(1<<ISC01)|(0<<ISC00)  ;  INT0 - falling
out     MCUCR,tmp        ;  
rcall   read_T1          ; Z = TCNT1 
ldi     xl,byte1(starth-IRcL) ; load 9.000 ms - 100us
ldi     xh,byte2(starth-IRcL) ; 
cp      zl,xl            ;  comparing  TCNT1 with starth constant ! 
cpc     zh,xh            ;  
brlo    IR_error         ; если меньше, чем 8,8 мс то ошибка, не наш протокол ! 
ldi     xl,byte1(starth+IRcH) ; load 9.000 ms + 200us
ldi     xh,byte2(starth+IRcH) ; 
cp      zl,xl            ; comparing  TCNT1 with starth constant ! 
cpc     zh,xh            ; 
brsh    IR_error         ; если больше, чем 9,25 мс то ошибка, не наш протокол ! 
ldi     flags,0x02       ; Flags = 2
rjmp    IR_ok            ; 

IR_repeat:               ; 
rcall   read_T1          ; Z = TCNT1 
ldi     xl,byte1(restart-IRcL) ; 2.250 ms - 100us
ldi     xh,byte2(restart-IRcL) ; 
cp      zl,xl            ;  comparing  TCNT1 with starth constant ! 
cpc     zh,xh            ;  
brlo    IR_error         ; если меньше, чем 8,8 мс то ошибка, не наш протокол ! 
ldi     xl,byte1(restart+IRcL) ; 2.250 ms + 100us
ldi     xh,byte2(restart+IRcL) ; 
cp      zl,xl            ; comparing  TCNT1 with starth constant ! 
cpc     zh,xh            ; 
brsh    IR_N_start       ; если больше, чем 2.375 мс то проверяем нормальный старт 
ldi     flags,0x03       ; Flags = 3 (REPEAT command)
rcall   write_T1         ; T1 = f.osc / 64 
rjmp    IR_check         ; 


IR_N_start:              ; NEC normal start 9 ms + 4.5 ms ! FLAGS = 3 ! 
ldi     xl,byte1(startl-IRcH) ; load 4.500 ms - 200us
ldi     xh,byte2(startl-IRcH) ; 
cp      zl,xl            ;  comparing  TCNT1 with starth constant ! 
cpc     zh,xh            ;  
brlo    IR_error         ; если меньше, чем 4.3 мс то ошибка, не наш протокол ! 
ldi     xl,byte1(startl+IRcH) ; load 4.500 ms + 200us
ldi     xh,byte2(startl+IRcH) ; 
cp      zl,xl            ; comparing  TCNT1 with starth constant ! 
cpc     zh,xh            ; 
brsh    IR_error         ; если больше, чем 4.7 мс то ошибка, не наш протокол ! 
ldi     flags,0x04       ; Flags = 4

IR_ok:                   ; Успешный прием
cpi     cnt,35           ; максимальное количество прерываний посылки пульта = 35 ! далее повторы по 2 прерывания
brsh    IR_check         ; => 35 - проверяем флаг повтора ! 

; IR ADDRESS CHECK ! 
ldi     zl,low (IR_adr*2) ; IR address pointer
ldi     zh,high(IR_adr*2) ;
lpm     xl,z+            ;  X = NEC IR ADR  
lpm     xh,z             ;  xl <-- ADRL, xh <-- ADRH
cp      adrl,xl          ; 
cpc     adrh,xh          ; 
brne    IR_adr_err       ; если адрес не совпадает,с указанным в программе, то в команду пишем 255
Exit:                    ; метка выхда из прерывания
pop     zh               ; извлечь ZH из STACK
pop     zl               ; извлечь ZL из STACK
pop     xh               ; извлечь XH из STACK
pop     xl               ; извлечь XL из STACK
pop     tmp              ; извлечь tmp из STACK
out     SREG,tmp         ; восстановить SREG
pop     tmp              ; извлечь tmp из STACK
reti                     ; выход из внешнего прерывания INT0 

IR_adr_err:              ; Ошибка принятого адреса от пульта IR 
ser     tmp              ; 
sts     nec,tmp          ; сохраняем 255 в команду
rjmp    Exit             ; на выход из прерывания 


IR_error:                ; Не наш протокол, ошибка приема ! 
clr     cnt              ; счетчик прерываний  = 0 
ser     tmp              ;  
mov     bytei,tmp        ; NEC IR Command_INV  = FFH 
mov     byten,tmp        ; NEC IR Command_Nor  = FFH
mov     adrh,tmp         ; NEC IR Address High = FFH
mov     adrl,tmp         ; NEC IR Address Low  = FFH
ldi     tmp,(1<<ISC01)|(0<<ISC00)  ;  INT0 - falling 
out     MCUCR,tmp        ; прерывание по спаду ! 
ldi     flags,0b01000000 ; ERROR - 0x40  
out     TCCR1B,zero      ; STOP Timer1 
out     TCNT1H,zero      ; 
out     TCNT1L,zero      ; TCNT1=0 
in      tmp,TIFR         ; tmp = TIFR
andi    tmp,0xFD         ; TOV1 --> 2 bit (FD)
out     TIFR,tmp         ; сброс флага переполнения T1
rjmp    Exit             ; на выход 

IR_check:                ; Проверка статусов и адреса пульта !!! 
sts     nec,byten        ; сохраняем байт команды ! 
clr     cnt              ; ITNT0 counter = 0 
cpi     flags,0x03       ; если статус = 0x03 то приняты данные 
breq    IR_ok            ; идем на OK!
cpi     flags,0x05       ; если статус = 0x05 то приняты данные 
breq    IR_ok            ; идем на OK!
rjmp    IR_error         ; если флаг установлен, то не стираем данные 



GET_IR_data:             ; GET data 
rcall   read_T1          ; Z = TCNT1 
IR_data_0:               ; Прием бита 0 (1.125ms) 
ldi     xl,byte1(log0-IRcL) ; load 1.125 ms - 100us
ldi     xh,byte2(log0-IRcL) ;
cp      zl,xl            ; comparing  TCNT1 with log0 constant ! 
cpc     zh,xh            ; 
brlo    IR_error         ; если меньше, чем 1,025 то не наш протокол, ошибка 
ldi     xl,byte1(log0+IRcL) ; load 1.125 ms + 100us
ldi     xh,byte2(log0+IRcL) ;
cp      zl,xl            ; comparing  TCNT1 with log0 constant ! 
cpc     zh,xh            ; 
brsh    IR_data_1        ; если больше, чем 1,225 то принимаем лог 1
clc                      ; 
lsr     bytei            ; DATA 32 bits = >> 1 LSB first
ror     byten            ; 
ror     adrh             ; 
ror     adrl             ; 
ldi     flags,5          ; принят бит 0 Flags = 5 
rjmp    IR_ok            ; return 

IR_data_1:               ; Прием бита 1 (2,25ms) 
ldi     xl,byte1(log1-IRcL) ; load 2.25 ms - 100us
ldi     xh,byte2(log1-IRcL) ;
cp      zl,xl            ; comparing  TCNT1 with log0 constant ! 
cpc     zh,xh            ; 
brlo    IR_error         ; если меньше чем 2.15ms то не наш протокол, ошибка 
ldi     xl,byte1(log1+IRcL) ; load 2.25 ms + 100us
ldi     xh,byte2(log1+IRcL) ;
cp      zl,xl            ; comparing  TCNT1 with log0 constant ! 
cpc     zh,xh            ; 
brsh    IR_error         ; если больше чем 2.35ms то не наш протокол, ошибка 
ldi     tmp,0b10000000   ; установка бита 7 в регистрах 
clc                      ; 
lsr     bytei            ; DATA 32 bits = >> 1 LSB first ! 
ror     byten            ; 
ror     adrh             ; 
ror     adrl             ; 
or      bytei,tmp        ; DATA = | 1 
ldi     flags,5          ; принят бит 1 Flags = 5 
rjmp    IR_ok            ; return 

read_T1:                 ; Читаем данные счетчика Timer1 и ставим прескаллер 8 !  
in      zl,TCNT1L        ; Z = TCNT1 
in      zh,TCNT1H        ; Low conter must be read FIRST ! 
out     TCCR1B,zero      ; STOP Timer1 
out     TCNT1H,zero      ; 
out     TCNT1L,zero      ; TCNT1=0 
in      tmp,TIFR         ; tmp = TIFR
andi    tmp,0xFD         ; TOV1 --> 2 bit (FD)
out     TIFR,tmp         ; сброс флага переполнения T1
ldi     tmp,0x02         ; f.osc / 8
out     TCCR1B,tmp       ; 
ret                      ; return 

write_T1:                ; Timer1 переполнится через 110ms !
out     TCCR1B,zero      ; STOP Timer1 
ldi     zl,low (repeat)  ; 
ldi     zh,high(repeat)  ; Z = repeat ~(110ms) 
out     TCNT1H,zh        ; 
out     TCNT1L,zl        ; TCNT1=repeat  
in      tmp,TIFR         ; tmp = TIFR
andi    tmp,0xFD         ; TOV1 --> 2 bit (FD)
out     TIFR,tmp         ; сброс флага переполнения T1
ldi     tmp,0x03         ; f.osc / 64
out     TCCR1B,tmp       ; 
ret                      ; return 


;************************;
; TIMER 1 Overflow       ;
T1_ovf:
push    tmp              ; сохранить tmp в STACK
in      tmp,SREG         ; прочитать содержимое SREG в tmp 
push    tmp              ; сохранить SREG в STACK
cli                      ; выключаем прерывания
clr     cnt              ; CNT = 0 
clr     flags            ; FLAGS = 0
out     TCCR1B,zero      ; STOP Timer1 
out     TCNT1H,zero      ; 
out     TCNT1L,zero      ; TCNT1=0 
in      tmp,TIFR         ; tmp = TIFR
andi    tmp,0xFD         ; TOV1 --> 2 bit (FD)
out     TIFR,tmp         ; сброс флага переполнения T1
ser     tmp              ;  
sts     nec,tmp          ; RAM NEC IR Command_Nor  = FFH
mov     bytei,tmp        ; NEC IR Command_INV  = FFH 
mov     byten,tmp        ; NEC IR Command_Nor  = FFH
mov     adrh,tmp         ; NEC IR Address High = FFH
mov     adrl,tmp         ; NEC IR Address Low  = FFH
pop     tmp              ; извлечь tmp из STACK
out     SREG,tmp         ; восстановить SREG
pop     tmp              ; извлечь tmp из STACK
reti                     ; выход из прерывания  T1_ovf

;************************; 
; END of NEC IR_receiver code 



;.org 0xFC0
; IR data Команды от пульта
; LG remote control 

; NEC IR Address   L    H    ; 
IR_adr:     .db 0x04,0xFB    ; Адрес пульта первый байт, второй байт 

; NEC IR Commands  N    I    ; 
power:      .db 0x08,0xF7    ; команда управления ВКЛ / ВЫКЛ
mute:       .db 0x09,0xF6    ; команда управления звук выкл 
left:       .db 0x02,0xfd    ; команда управления громкость + (вправо)
right:      .db 0x03,0xfc    ; команда управления громкость - (влево)
up:         .db 0x00,0xff    ; команда управления вверх 
down:       .db 0x01,0xfe    ; команда управления вниз 
center:     .db 0x44,0xbb    ; команда управления OK по центру джойстика.
menu:       .db 0x43,0xbc    ; команда управления MENU

; Keys 0...9                 ;  
key0:       .db 0x10,0xef    ; команда управления 0
key1:       .db 0x11,0xee    ; команда управления 1 
key2:       .db 0x12,0xed    ; команда управления 2
key3:       .db 0x13,0xec    ; команда управления 3
key4:       .db 0x14,0xeb    ; команда управления 4
key5:       .db 0x15,0xea    ; команда управления 5
key6:       .db 0x16,0xe9    ; команда управления 6
key7:       .db 0x17,0xe8    ; команда управления 7
key8:       .db 0x18,0xe7    ; команда управления 8
key9:       .db 0x19,0xe6    ; команда управления 9

; Colour keys                ; 
keyred:     .db 0x72,0x8d    ; команда управления красная
keygreen:   .db 0x71,0x8e    ; команда управления зеленая
keyyello:   .db 0x63,0x9c    ; команда управления желтая
keyblue:    .db 0x61,0x9e    ; команда управления синяя





Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очень понравилась идея таймеров. Подходит под любой проц, надо только прерывание настроить. Сейчас на мегу8 реализовано.

 

Идея в том, что в прерывании каждую мс постоянно увеличивается переменная. Идея не нова, но обыграть можно так:

 

инициализация

uint8_t timer_test = -1;

 

timer_test  = timer_create (TIMER_REPEAT_START, 1000, timer_test_callback);

 

а вот сама ф-я

void timer_test_callback (uint8_t index)
{
  cpl (LED);
}

 

итак, есть ф-я timer_test_callback, которая передается как указатель на ф-ю при инициализации.

инициализируем таймер

timer_create (TIMER_REPEAT_START, 1000, timer_test_callback);

первое- режим- повторяющийся в данном случае, 1000 мс, и ф-я, в которую попадем после установленного времени. Там, например, можно менять на противоположное состояние LED.

 

в вечном цикле крутим постоянно ф-ю

timer_handle ();

 

скачать

 

Принимаются комментарии по реализации и работе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мой пример формирователя задержек с разрешением в 1 такт для микроконтроллеров AVR на ассемблере.

Всего 12 команд / 24 байта.

 

; Процедура формирования программируемых задержек с разрешением 1 такт.
; Формируемая задержка равна (XH:XL + 13) тактов.
; т.е. XL:XH = 0 -> задержка минимальна и равна 13 тактам,
; и XL:XH = 65535 -> задержка максимальна и равна 65548 тактам.

; Формирование дополнительной задержки 8..11 тактов.
; Необходимость дополнительной задержки связана с тем, что
; основной цикл формирования задержки обеспечивает 
; дискретность 4 такта.
; Дополнительная задержка имеет разрешение 1 такт.
LSR		XH
ROR		XL
BRCC	APs0_AD_Lab1
RJMP	APs0_AD_Lab1
APs0_AD_Lab1:
LSR		XH
ROR		XL
BRCC	APs0_AD_Lab2
NOP
RJMP	APs0_AD_Lab2
APs0_AD_Lab2:

; Инкремент для установки минимальной задержки нулём входного значения.
ADIW	XH:XL, 1

; Цикл формирования основной задержки.
APs0_AD_Loop:
SBIW	XH:XL, 1
BRNE	APs0_AD_Loop

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В догонку.

Библиотека математических функций для микроконтроллеров Mega (часть функций не используют команд умножения – они применимы и для Tiny) на ассемблере.

Оформлена в виде макросов, переопределения регистров также выполнены в виде макросов.

Краткий перечень содержимого:

Умножение с накоплением для знаковых 24-х битных чисел (результат 48 бит).

Умножение с накоплением для знаковых 32-х битных чисел (результат 64 бита).

Деление беззнаковых 32-х битных чисел.

Преобразования вида: число с фиксированной точкой -> строка, строка -> число с фиксированной точкой.

Код сопровождён пояснениями.

Понятно, что если задача насыщенна 32-х битными вычислениями то проще выбрать 32-х битный микроконтроллер, но если в существующий проект на AVR понадобилось внести такие операции – библиотека есть. Да и 20 МГц AVR в частности вполне достаточно для выполнения несложных фильтров (рекурсивный 2, 4, 6 порядки) на частотах дискретизации 3-5 кГц.

ATmega_Math.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...