|
|
| ||||||||
|
|
|
|
80493
149
0
0
|
|
Опции темы | Поиск в этой теме |
|
41
|
|
Увлеченный
|
|
|
|
|
|
42
|
|
Увлеченный
|
Разобрался с АЦП. Всем спасибо за ответы.
|
|
|
|
|
|
43
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Код:
_main:
LDI R27, 255
OUT SPL+0, R27
LDI R27, 0
OUT SPL+1, R27
;Migalka.c,1 :: void main() {
;Migalka.c,3 :: PORTB.F0 = 0;
IN R27, PORTB+0
CBR R27, 1
OUT PORTB+0, R27
;Migalka.c,4 :: PORTB.F1 = 0;
IN R27, PORTB+0
CBR R27, 2
OUT PORTB+0, R27
;Migalka.c,5 :: PORTB.F2 = 0; // Выставляем все порты в 0.
IN R27, PORTB+0
CBR R27, 4
OUT PORTB+0, R27
;Migalka.c,6 :: PORTB.F3 = 0;
IN R27, PORTB+0
CBR R27, 8
OUT PORTB+0, R27
;Migalka.c,7 :: PORTB.F4 = 0;
IN R27, PORTB+0
CBR R27, 16
OUT PORTB+0, R27
;Migalka.c,9 :: DDRB.F0 = 1;
IN R27, DDRB+0
SBR R27, 1
OUT DDRB+0, R27
;Migalka.c,10 :: DDRB.F1 = 1;
IN R27, DDRB+0
SBR R27, 2
OUT DDRB+0, R27
;Migalka.c,11 :: DDRB.F2 = 1; // Выставляем направление порта на выход.
IN R27, DDRB+0
SBR R27, 4
OUT DDRB+0, R27
;Migalka.c,12 :: DDRB.F3 = 1;
IN R27, DDRB+0
SBR R27, 8
OUT DDRB+0, R27
;Migalka.c,13 :: DDRB.F4 = 1;
IN R27, DDRB+0
SBR R27, 16
OUT DDRB+0, R27
;Migalka.c,15 :: while( 1 ) { // Циклим программу.
L_main0:
;Migalka.c,16 :: PORTB.F0 = 1; // Включаем первый светодиод.
IN R27, PORTB+0
SBR R27, 1
OUT PORTB+0, R27
;Migalka.c,17 :: Delay_ms( 500 ); // Ждем 0.5 секунд.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main2:
DEC R16
BRNE L_main2
DEC R17
BRNE L_main2
DEC R18
BRNE L_main2
NOP
NOP
;Migalka.c,18 :: PORTB.F0 = 0; // Выключаем первый светодиод.
IN R27, PORTB+0
CBR R27, 1
OUT PORTB+0, R27
;Migalka.c,19 :: PORTB.F1 = 1; // Включаем второй светодиод.
IN R27, PORTB+0
SBR R27, 2
OUT PORTB+0, R27
;Migalka.c,20 :: Delay_ms( 500 ); // Ждем 0.5 секунд.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main4:
DEC R16
BRNE L_main4
DEC R17
BRNE L_main4
DEC R18
BRNE L_main4
NOP
NOP
;Migalka.c,21 :: PORTB.F1 = 0; // Выключаем второй светодиод.
IN R27, PORTB+0
CBR R27, 2
OUT PORTB+0, R27
;Migalka.c,22 :: PORTB.F2 = 1; // Включаем третий светодиод.
IN R27, PORTB+0
SBR R27, 4
OUT PORTB+0, R27
;Migalka.c,23 :: Delay_ms( 500 ); // Ждем 0.5 секунд.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main6:
DEC R16
BRNE L_main6
DEC R17
BRNE L_main6
DEC R18
BRNE L_main6
NOP
NOP
;Migalka.c,24 :: PORTB.F2 = 0; // Выключаем третий светодиод.
IN R27, PORTB+0
CBR R27, 4
OUT PORTB+0, R27
;Migalka.c,25 :: PORTB.F3 = 1; // Включаем четвертый светодиод.
IN R27, PORTB+0
SBR R27, 8
OUT PORTB+0, R27
;Migalka.c,26 :: Delay_ms( 500 ); // Ждем 0.5 секунд.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main8:
DEC R16
BRNE L_main8
DEC R17
BRNE L_main8
DEC R18
BRNE L_main8
NOP
NOP
;Migalka.c,27 :: PORTB.F3 = 0; // Выключаем четвертый светодиод.
IN R27, PORTB+0
CBR R27, 8
OUT PORTB+0, R27
;Migalka.c,28 :: PORTB.F4 = 1; // Включаем пятый светодиод.
IN R27, PORTB+0
SBR R27, 16
OUT PORTB+0, R27
;Migalka.c,29 :: Delay_ms( 500 ); // ЖЖдем 0.5 секунд.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main10:
DEC R16
BRNE L_main10
DEC R17
BRNE L_main10
DEC R18
BRNE L_main10
NOP
NOP
;Migalka.c,30 :: PORTB.F4 = 0; // Выключаем пятый светодиод.
IN R27, PORTB+0
CBR R27, 16
OUT PORTB+0, R27
;Migalka.c,32 :: PORTB.F3 = 1; // Включаем четвертый светодиод.
IN R27, PORTB+0
SBR R27, 8
OUT PORTB+0, R27
;Migalka.c,33 :: Delay_ms( 500 ); // Ждем 0.5 секунд.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main12:
DEC R16
BRNE L_main12
DEC R17
BRNE L_main12
DEC R18
BRNE L_main12
NOP
NOP
;Migalka.c,34 :: PORTB.F3 = 0; // Выключаем четвертый светодиод.
IN R27, PORTB+0
CBR R27, 8
OUT PORTB+0, R27
;Migalka.c,35 :: PORTB.F2 = 1; // Включаем третий светодиод.
IN R27, PORTB+0
SBR R27, 4
OUT PORTB+0, R27
;Migalka.c,36 :: Delay_ms( 500 ); // Ждем 0.5 секунд.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main14:
DEC R16
BRNE L_main14
DEC R17
BRNE L_main14
DEC R18
BRNE L_main14
NOP
NOP
;Migalka.c,37 :: PORTB.F2 = 0; // Выключаем третий светодиод.
IN R27, PORTB+0
CBR R27, 4
OUT PORTB+0, R27
;Migalka.c,38 :: PORTB.F1 = 1; // Включаем второй светодиод.
IN R27, PORTB+0
SBR R27, 2
OUT PORTB+0, R27
;Migalka.c,39 :: Delay_ms( 500 ); // Ждем 1 секунду.
LDI R18, lo_addr(R3)
LDI R17, 138
LDI R16, 86
L_main16:
DEC R16
BRNE L_main16
DEC R17
BRNE L_main16
DEC R18
BRNE L_main16
NOP
NOP
;Migalka.c,40 :: PORTB.F1 = 0; // Выключаем второй светодиод.
IN R27, PORTB+0
CBR R27, 2
OUT PORTB+0, R27
;Migalka.c,42 :: }
JMP L_main0
;Migalka.c,43 :: }
L_end_main:
JMP L_end_main
; end of _main
. В МК есть же таймеры, зачем считать интервалы программно? Это же полностью загружает камень, его и не отвлечь на другие операции...Не, не,не. Не заставите вы меня пересесть на язык высокого уровня. Это же жесть полная!.. Как освобожусь - напишу эту мигалку на ассемблере, для сравнения ...
|
|
|
|
|
|
44
|
|
Увлеченный
Регистрация: 12.02.2010 Последняя активность: 15.02.2011 20:41
Сообщений: 266
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
|
|
|
|
|
|
45
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
|
|
|
|
|
|
46
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Написал бегущий огонёк на ассемблере
:Код:
;Бегущий огонь на ATtiny13. Тактовая 128кГц. .INCLUDE "tn13def.inc" ;Векторы прерываний: rjmp RESET .ORG 0x0006 rjmp compA .ORG 0x000A ;Конфигурация: RESET: ldi R16, 0b10000000 ;Отключить аналоговый компаратор out ACSR, R16 ldi R16, 0b100000 ;Разрешить Sleep, режим idle out MCUCR, R16 ser R16 ;Все порты на выход out DDRB, R16 ldi R16, 0b100 ;Включить прерывание compA out TIMSK0, R16 ldi R16, 0b101 ;Предделитель таймера на 1024 out TCCR0B, R16 ldi R16, 1 ;Начинать с PB0 ;Программа: compA: out PORTB, R16 ;Вывести бит в порт lsl R16 ;Сдвинуть бит влево sbrc R16, 5 ;При зашкаливании переместить бит в начало ldi R16, 1 in R17, TCNT0 ;Установить компаратор на срабатывание через 125 тактов таймера subi R17, -125 out OCR0A, R17 sei ;Разрешить прерывания Sleep |
|
|
|
|
|
47
|
|
|
Завсегдатай Фонарёвки
|
Цитата:
|
|
|
|
|
|
|
48
|
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
Код:
#include <avr/io.h>
void main () {
PORTB.F3 = 0; // Выставляем ноль на выходе порта. F3 - это порт PB3.
DDRB.F3 = 1; // Выставляем порт на выход.
while (1) // Циклим прогу.
{
PORTB.F3 = 1; // Включаем светодиод
Delay_ms (600); // Ждем 600 мСек.
PORTB.F3 = 0; // Выключаем светодиод.
Delay_ms (600);
}
}
Код:
blinke.c:3: error: return type of ‘main’ is not ‘int’ blinke.c: In function ‘main’: blinke.c:4: error: request for member ‘F3’ in something not a structure or union blinke.c:4:19: error: C++ style comments are not allowed in ISO C90 blinke.c:4:19: error: (this will be reported only once per input file) blinke.c:5: error: request for member ‘F3’ in something not a structure or union blinke.c:9: error: request for member ‘F3’ in something not a structure or union blinke.c:10: error: implicit declaration of function ‘Delay_ms’ blinke.c:11: error: request for member ‘F3’ in something not a structure or union |
|
|
|
|
|
|
49
|
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
Что же касается таймеров, то загвоздка в том, что количество аппаратных таймеров ограничено. Если какая-то там мигалка светодиодом хавает целый таймер под свои нужды без возможностей заменить его на программную реализацию при необходимости, в сложной программе возможна катастрофа. К сожалению, реально решить эту проблему может только C++. Вот так на нем выглядит мигалка с аппаратным таймером: Код:
int main() {
PulseGenerator<OutSinglePin<PortB, 0>, HardwareDelay> generator;
generator.generate(500, 500);
return 0;
}
Код:
int main() {
PulseGenerator<OutSinglePin<PortB, 0>, SoftwareDelay> generator;
generator.generate(500, 500);
return 0;
}
Вот пример простейшего кода, демонстрирующий работу компилятора. Код:
#include <avr/io.h>
int main() {
DDRB |= (1 << 3);
while (1) {
PORTB |= (1 << 3);
asm volatile ("nop");
PORTB &= ~(1 << 3);
asm volatile ("nop");
}
return 0;
}
Код:
sbi 55-32,3
.L2:
sbi 56-32,3
nop
cbi 56-32,3
nop
rjmp .L2
|
|
|
|
|
|
|
50
|
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
#define - объявление макроса. Например: #define foo abc+def - примерно то же самое, что нажать в редакторе "найти foo, заменить везде на abc+def". Использование #define может привести к очень неочевидным результатам, поэтому его не рекомендуется использовать никогда (или почти никогда). |
|
|
|
|
|
|
51
|
|
Увлеченный
Регистрация: 12.02.2010 Последняя активность: 15.02.2011 20:41
Сообщений: 266
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Gall, какие есть стандартные библиотеки C++ для программирования авр, совместимые с avr-gcc, и где почитать к ним инструкции?
|
|
|
|
|
|
52
|
|
|
Увлеченный
Регистрация: 12.02.2010 Последняя активность: 15.02.2011 20:41
Сообщений: 266
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
Чтобы не было неочевидных результатов, достаточно писать #define foo (abc+def), и тогда никаких неочевидных результатов (типа foo*bar -> abc+def*bar) не будет. Вся avr-libc это почти что одни макросы, и ничего, работает. |
|
|
|
|
|
|
53
|
|
Завсегдатай Фонарёвки
|
Gall Хорошо, когда человек разбирается в предмете как ты. У него и Си может скомпилиться не хуже, чем человек напишет на ассемблере.
Но, как правило, многие пишут мигалки на Си, даже не зная про опции оптимизации компилятора. И общая тенденция такова, что средняя прошивка на Си - это нечто обьёмное, медленное, а программист даже понятия не имеет, что эти действия могли бы выполниться быстрее (даже если он и заглянет в листинг ассемблера (а большинство про него и не вспоминают), он всё равно не сможет оценить результат (потому что не знает, много это или мало для ассемблера. потому что и ассемблер большинство Сишников совершенно не знает!)). А вот на ассемблере прошивка никогда не получится слишком утяжелённой. Человек физически не сможет наплохокодить так, как может по дефолту Си
|
|
|
|
|
|
54
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
Код:
#define max(a,b) (a > b ? a : b) c = max(a++, b++); |
|
|
|
|
|
55
|
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
Что касается кода на Ассемблере, то основная его проблема - это то, что его тяжело переделывать. В процессе отладки схемы на макетке часто приходится, например, поменять местами пару проводов для удобства разводки платы - или наоборот, для удобства программирования. Иногда в программу приходится добавлять совершенно новую функциональность - подключили что-то дополнительное. Ассемблерный код тут плохой помощник. Не говоря уже про то, что на Си можно написать 100 строк нетривиальной программы, скомпилировать, прошить - и оно СРАЗУ начнет правильно работать, потому что ошибки отловит компилятор. Добавлено через 3 минуты Цитата:
Большое количество различных готовых библиотек можно скачать на http://avrfreaks.net |
|
|
|
|
|
|
56
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Gall прав. Ассемблер хорош, пока не приходилось перетаскивать код на другой процессор/ платформу. Любому поклоннику ассемблера oбычно хватает одного раза. Лучше сразу Си учить
|
|
|
|
|
|
57
|
|
Увлеченный
Регистрация: 12.02.2010 Последняя активность: 15.02.2011 20:41
Сообщений: 266
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
На avrfreaks именно плюсовых библиотек не густо, причём все они для AVR32. Сделать на основе avr-libc что-то вроде описанного таймера или драйвера UART можно, но не хотелось бы изобретать велосипед.
|
|
|
|
|
|
58
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Народ, кто-нибудь связывался с HV программированием? С протоколом разобрался, но не могу вывести МК в режим программирования. В даташите говорится, что надо плясать с бубном над временными интервалами. Мол включили 5V, подождали 20...60мкс, подали на ресет 12V, подождали ещё столько-то и т.д. Это получается мне надо городить огород на ключах, и ставить вместо 13-й тиньки сороконожку, чтоб ими рулить. У меня под рукой только 8-ми лапые МК, я могу включать преобразователь, но он явно за 20мкс не успеет набрать 12V (LM27313). Смотрю на готовые схемы HV программаторов - там особо с этим и не заморачиваются. +5V вообще не коммутируется. Просто я не хочу лепить лишний огород, если в нём нет необходимости. Кто что подскажет мне интересного по этому поводу?..
|
|
|
|
|
|
59
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
На самом деле важно, чтобы после подачи питания 5 вольт и до подачи 12 вольт контроллер успел "прогреться" и начать работать. Подавать 12 вольт надо резко, качать преобразователем нельзя, нужен отдельный ключ. В остальном ничего особенного нету. В принципе можно подавать 5 и 12 вольт через оптроны 4N35 в качестве реле, чтобы проще. Тока хватит. Или даже питать прошиваемый МК от обычного порта прошивающего.
Как правило, HV-программатор нужен для перепрошивки контроллера после неправильно прошитых фуз, чтобы не выбрасывать хорошую вещь. Поэтому можно сделать упрощенный программатор, который умеет только стирать контроллеры, а шить прошивку уже обычным внутрисхемным. Особенно это ценно для многоногих контроллеров, где такой подход позволяет не подключать индивидуально каждый вывод прошиваемого МК, а параллелить выводы. |
|
|
|
|
|
60
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Я восстановитель фьюзов и собрал. Просто мне нужно запрограммировать RSTDISBL, но к чему это приведёт думаю можно не объяснять...
Я уже влепил в схему два ключа на сдвоенном полевике. Рулить ими буду с одной лапы МК. Один закрывается, другой открывается. Преобразователь работает постоянно и МК программатора подождёт пока он накопит достаточное напряжение. Я подавал резко 12V. МК сбрасывается, но не шьётся. Как я понял - есть у него таймер на 64мс, который заводится при подаче питания, и если время истекло - МК не войдёт в режим программирования. Подавать же на ресет 12V, если на Vcc меньше вольта - недопустимо. Вот и приходится плясать с бубном. Во всяком случае так в даташите сказано. Соберу схему с ключами и думаю она заведётся . Спасибо за внимание, вопросов пока не имею...Добавлено: Запустил, работает . Фьюзы шьются и верифицируются за доли секунды.
|
|
|
|