Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Исходники программ и библиотек
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Страницы: 1, 2, 3, 4
sansnotfor
Драйвер светодиодного семисегментного 4-ех разрядного индикатора. Работает с любым компилятором. Легко настраивается для индикаторов с общим катодом, анодом, включенных напрямую или через транзисторы.
aleksey_g
Может кому нибудь понадобится...
Драйвер трех шаговиков с шагом 1 градус (можно изменить, поменяв таблицу синусов-косинусов).
Задействован только один таймер и 6 линий одного порта.
Как-то пришлось переделать автомобильный щиток с тремя двухобмоточными шговыми движками в качестве показометров одометра, спидометра и уровня топлива. Какой-то масочный процессор, рулящий этим хозяйством, имеющий 12 PWM-выходов, не показывал никаких признаков жизни.
Упростил схему включения (прилагается) движков, выйдя на 6 PWM-выходов. Немного потерял в крутящем моменте, но для стрелок пойдет.
Таблица синусов-косинусов рассчитана с учетом некоторой нелинейности угла поворота роторов движков.
Сопротивление обмоток двигателей было более 2 килоом. Подключил прямо к ATMEGA162.
Сделано под ИАР. Легко ложится на любой контроллер, имеющий 1 таймер и 6 выходов одного порта.
Нажмите для просмотра прикрепленного файла
lsd2k
Реализация мастера и клиента для Wake протокола. Пример использования там же.


Готовый проект под EWAVR - модуль управления вентилятором охлаждения. 3 ступени температуры, 3 датчика DS18B20, гистерезис.
Леонид Иванович
Примеры реализации WAKE для AVR (EWAVR) и PC (C++ Builder).
Старая и новая версии.
В прежних реализациях Wake были две ошибки:

1. При передаче ответа микроконтроллером CRC вычислялась для адреса с установленным старшим битом, а не для истинного адреса, как требует спецификация. Ошибка не проявляется, если используется только нулевой адрес, который в пакете не передается.

2. При передаче ответа микроконтроллером всегда передавался установленный адрес устройства, даже если обратились по нулевому адресу (адрес коллективного вызова). А надо отвечать с тем же адресом, по которому обратились. Ошибка не проявляется, если используется только нулевой адрес.
aleksey_g
Может кому-то пригодится...
Сделал для себя небольшой графический визуализатор логов и стимулов Аврстудии.
Показывает графиком состояния любых двух пинов из лога или стимула.
Позволяет редактировать. После редактирования нажмите REPAINT.
Поддерживает имя открываемого файла из коммандной строки.
При любых манипуляциях с верхним графиком (увеличение, смещение вправо-влево, изменении размера окна...), нижний график по координатам подстраивается под верхний.
Манипуляции с нижним-независимы.
Думаю, будет полезным для анализа (к примеру) последовательных протоколов, шимов...
Нажмите для просмотра прикрепленного файла
SZ0
Цитата(aleksey_g @ Mar 18 2011, 19:06) *
Сделал для себя небольшой графический визуализатор логов и стимулов Аврстудии.


В своё время хотел подобное, но только для ввода данных для симулятора. Чтобы по графику генерировался файл и его скармливать студии. Вам осталось только инвертировать работы вашей программы sm.gif

В вашей программе предлагаю расширить до 8 полос графики, т.е. для 8 бит. И сделать так, чтобы пользователь мог задавать их кол-во от 1 до 8. А черодование выводимых ножка/график оставить так же, т.е. выбор бита в окне. Ещё можно добавить в настройки соответствие цикла частоте. И выводить время на графике. При этом при наведении перекрестия курсора показывать время, где стоит курсор. А для выделенного участка показывать его длительность.
ветерок
Исходник DELPHI программатора для ATMEL типа ATmega48
Собран на одной микрухе FT232rl +3 кондёра,частотка тож от неё
Пример заточень под ATmega48 но быстро переделывается под любой другой с подобными сигнатарами
так же показывает принципы работы FT232rl и помогает разобраться в протоколах программирования AVR микроконтроллеров
Если отсюда файл пропадёт можно скачать отсюда:
http://izhbazar.ru/viewtopic.php?f=48&t=43#p389
Нажмите для просмотра прикрепленного файла
pavel-pervomaysk
Код дл работы с 44780 на асме
CODE
// 25.04.2011
// Двухстрочный ЖКИ 16 х 2 (20 х 4) контроллер 44780 режим 4 бита 5 х 7 точек
// Выставляем нужные пины
// tmp1 - РОН
// data - передача данных / команд в ЖКИ
// loop - счетчик цикла при выводе текста
// Z - указатель адреса
// Частота МК 4 000 000 Hz
// если частота выше, в подпрограмме wait_lcd нужно вставить чуть больше nop-ов при дергании пинов

.equ rs = PC1 // Выбор регистра ЖКИ
.equ rw = PC2 // Чтение_запись данных в ЖКИ
.equ e = PC3 // Включение разрешения команд
.equ bf = PC7 // Флаг занятости ЖКИ
.equ LCD = PORTC // порт ЖКИ
.equ LCD_DDR = DDRC // направление порта ЖКИ
.equ LCD_PIN = PINC // вход порта ЖКИ
.equ Line1 = 0x80 // Адрес начала первой строки ЖКИ
.equ Line2 = 0xC0 // Адрес начала второй строки ЖКИ

.equ celsiy = 0x00 // код символа градуса цельсия
.equ antena = 0x01 // код символа антена


USER: // пользовательские символы ( максимум 8 штук )
.db 0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00 // символ градуса цельсия 0х00
.db 0x15,0x15,0x0E,0x04,0x04,0x04,0x04,0x00 // символ антены 0х01



init_lcd: // Инициализация ЖКИ
cbi LCD,rw // RW -> 0
nop //
cbi LCD,e // E -> 0
nop //
cbi LCD,rs // RS -> 0
rcall wait_20ms // ждем 20 милисекунд
ldi data,0x28 // 4 бита режим 5 х 7 точек 2 строки
rcall lcd_cmd_i // передаем команду в ЖКИ
rcall wait_20ms // ждем 20 милисекунд
ldi data,0x0C // 4 бита режим 5 х 7 точек 2 строки
rcall lcd_cmd_i // передаем команду в ЖКИ
rcall wait_20ms // ждем 20 милисекунд
ldi data,0x28 // 4 бита режим 5 х 7 точек 2 строки
rcall lcd_cmd_i // передаем команду в ЖКИ
rcall wait_20ms // ждем 20 милисекунд
rcall clr_lcd // очищаем жки
rcall set_simvols // Установка пользовательских символов
ret // выход

set_simvols: // Установка пользовательских символов для вывода на ЖКИ
ldi data,0x40 // загружаем константу
rcall lcd_cmd // посылаем команду адреса начала пользовательских символов
ldi zl,low (user*2) // загружаем адрес данных L
ldi zh,high(user*2) // загружаем адрес данных H
ldi loop,16 // загружаем количество символов * 8
celsiy_c: // начало цикла загрузки пользовательских символов
lpm data,Z+ // загружаем байт из FLASH с постинкрементом указателя адреса Z
rcall print_char // записываем байт в память ЖКИ
dec loop // счетчик цикла - 1
brne celsiy_c // если счетчик не = 0, то переходим на начало цикла
ret // выход

wait_lcd: // Готовность ЖКИ к приему
in tmp1,LCD_DDR // читаем
andi tmp1,0x0F // выделяем старшую тетраду
out LCD_DDR,tmp1 // выводы 4 5 6 7 порта ЖКИ - входы
cbi LCD,rs // RS -> 0
nop // холостой такт
sbi LCD,rw // RW -> 1
nop // холостой такт
lcd_busy: // E -> 1
sbi LCD,e // E -> 1
nop // холостой такт
in tmp1,LCD_PIN // Прочитать содержимое порта ЖКИ
cbi LCD,e // E -> 0
nop // холостой такт
sbi LCD,e // E -> 1
nop // холостой такт
cbi LCD,e // E -> 0
nop // холостой такт
sbrc tmp1,BF // пропуск след команды если сброшен BF флаг
rjmp lcd_busy // перейти на метку lcd_busy
cbi LCD,rw // RW -> 0
in tmp1,LCD_DDR // Прочитать содержимое порта ЖКИ
ori tmp1,0xF0 // выделяем младшую тетраду
out LCD_DDR,tmp1 // выводы 4 5 6 7 порта ЖКИ - выходы
ret // выход

clr_lcd: // Очистка ЖКИ
ldi data,0x01 // загружаем данные для очистки
rjmp lcd_cmd // подаем команду и очищаем ЖКИ

clr_line1: // Очистка line1
rcall lcd_line1 // выбираем начальный адрес очистки строки 1
ldi loop,16 // загружаем количество символов в строке
ldi data,' ' // загружаем пробел 0х20
rjmp clr_l // очищаем строку
clr_line2: // Очистка line2
rcall lcd_line2 // выбираем начальный адрес очистки строки 2
ldi loop,16 // загружаем количество символов в строке
ldi data,' ' // загружаем пробел 0х20
clr_l: // начало цикла очистки
rcall print_char // выводим на жки
dec loop // счетчик цикла -1
brne clr_l // если не = 0, переходим к началу цикла
ret // выход

print_char: // Вывод данных на ЖКИ
rcall wait_lcd // ждем готовности ЖКИ
sbi LCD,rs // RS -> 1
rjmp send_byte // передаем байт в ЖКИ

send_nibble: // Передача полубайта в ЖКИ
sbi LCD,e // E -> 1
in tmp1,LCD // прочитать содержимое порта
andi tmp1,0x0F // и выделить старшую тетраду
andi data,0xF0 // выделить младшую тетраду в регистре
or data,tmp1 // смешать регистр с данными
out LCD,data // выдать в порт ЖКИ результат
cbi LCD,e // E -> 0
ret // выход

lcd_line1: // Выбор адреса первой строки данных
ldi data,line1 // загружаем данные
rjmp lcd_cmd // передаем команду

lcd_line2: // Выбор адреса второй строки данных
ldi data,line2 // загружаем данные
rjmp lcd_cmd // передаем команду

lcd_cmd: // передача команды в ЖКИ
rcall wait_lcd // ждем готовности ЖКИ
lcd_cmd_i: // передача команды в ЖКИ при ините
cbi LCD,rs // RS -> 0
send_byte: // Передача байта в ЖКИ
push data // сохранить data в STACK
push data // сохранить data в STACK
rcall send_nibble // вызвать передачу полубайта
pop data // извлечь data из STACK
swap data // поменять нибблы местами
rcall send_nibble // вызвать передачу полубайта
pop data // извлечь data из STACK
ret // выход

out_text: // Вывод текста из флеш проца
lpm data,Z+ // загружаем ячейку памяти из флэш с постинкрементом адреса
rcall print_char // выводим данные на ЖКИ
dec loop // отнимаем 1 от счетчика
brne out_text // перейти если не равно
ret // выход
DiaS
Цитата(Kir85 @ Apr 4 2010, 16:28) *
Работа с графическим дисплеем MT-12232 на ATmega8.

Нажмите для просмотра прикрепленного файла

Кто пробовал запускать ?
Вроде косячок сразу нашел.

bool ReadByte(bool cd, bool l, bool r) {
char b;
if ((l==1)&&(r==1)) return 0; //Читать одновременно из обоих кристаллов недопустимо!
//При необходимости настроить здесь шину данных на ввод
DDRD = 0x00;
//LCD.RW=1; LCD.A0=cd; //Будем читать байт как команду или данные
PORTB_Bit1 = 1; PORTB_Bit6 = cd;
//Delay(>40ns); //Это время предустановки адреса (tAW)
__delay_cycles(1);
//LCD.E1=l; LCD.E2=r; //Выдать нужный строб в индикатор
PORTB_Bit7 = l; PORTB_Bit0 = r;
//Delay(>300ns); //Минимально допустимая длительность сигнала E=1 (время доступа (tACC) попало сюда)
__delay_cycles(1);
//b=LCD.D; //Прочитать данные с шины индикатора (они на ней уже минимум 120нс)
b = PINB; Непонятно что читает?
//LCD.E1=LCD.E2=0; //Сбросить сигналы E1 и E2
PORTB_Bit7 = PORTB_Bit0 = 0;
//Delay(>(2000ns-40ns-300ns)); //Минимально допустимый интервал между сигналами E=1
__delay_cycles(2);
return b; //Вернуть прочитанный байт
}

//Прочитать байт данных из левой половины индикатора
bool ReadDataL(void){
return ReadByte(1,1,0);
}

//Прочитать байт данных из правой половины индикатора
bool ReadDataR(void){
return ReadByte(1,0,1);
zumanah
Нормальные уроки по AVR с кодами программ. Примеры по процессорам AVR c кодами программ.
smk
Поскольку примеры от Atmel занимают много памяти в контроллерах, для которых они предназначены, простора для творчества практически не остается. На основе библиотеки Atmel сделал одну кнопочку на Tiny45. Можно что-то включать/выключать и донавернуть до простейшего интерфейса пользователя, например переходить в режим настройки при длительном удержании. Размер кода 2684 байта.
Нажмите для просмотра прикрепленного файла
Леонид Иванович
Помехоустойчивый декодер RC-5:
sansnotfor
Программный модуль позволяющий добавить функцию воспроизведения мелодий или последовательностей звуков практически в любой проект на микроконтроллере AVR.

- простая интеграция с готовым проектом
- задействован только 8-ми разрядный таймер т2, при этом остается возможность использовать его для опроса или формирования временных интервалов
- модуль настраивается практически на любую частоту тактового генератора
- высота нот задается в виде символических констант (С0, А2 и т.д) или в Герцах
- длительности задаются в стандартном виде (четверти, восьмые и т.д.) или в миллисекундах
- имеется возможность задавать темп воспроизведения мелодии и количество ее повторений
- в процессе воспроизведения мелодия может быть поставлена на паузу

подробное описание
http://chipenable.ru/index.php/programming...uka-na-avr.html

Исходники для трех компиляторов - IAR, GCC, CV
Нажмите для просмотра прикрепленного файла
pavel-pervomaysk
Последняя версия для работы с ЖКИ NOKIA 1110i / 1112i
Подключение ЖКИ на картинке ниже


CODE


// pavel-pervomaysk
// Final version Nokia 1110i LCD module
// Time 03.10.2011

// Lcd controller по командам частично совместимый с PCF8814
// SET X adress lcd
// 0x10,0x00 начало строки с 0 го адреса строки
// количество столбцов ЖКИ 96 , штук адрес установки с 0 - 95
// адрес столбца нам нужен 39 , 39 -> HEX = 0x27.
// Установка адреса будет иметь такой вид 0x12,0x07
// 3 старших бита адреса передаются в первой команде
// 4 младших бита адреса передаются во второй команде
// SET Y adress lcd
// Всего 8 полных строк и 9й не полный
// установка адреса Y происходит подачей команд
// 0xB0 первая - 0xB8 девятая строки.
// Дополнительные команды для управления и инициализации ЖКИ
// Сдвиг всей области ЖКИ вверх на 1 0x41
// Сдвиг всей области ЖКИ вверх на 2 0x42
// Сдвиг всей области ЖКИ вверх на 4 0x43
// Сдвиг всей области ЖКИ вверх на 8 0x44
// Сдвиг всей области ЖКИ вверх на 10 0x45
// Сдвиг всей области ЖКИ вверх на 16 0x48
// Сдвиг всей области ЖКИ вниз на 21 0x65
// Контрастность ЖКИ 0x90 ... 0x9F установка по дисплею в проекте
// Очистка картинки (данные соханяются) 0xA2
// Реверсное изображение с низу к верху 0xC8
// Позитивное изображение ЖКИ 0xA6
// Негативное изображение ЖКИ 0xA7
// Заполнение строки с лева на право 0xA1
// |||||||||||||||||||||||||||||||||
// lsb adress ->
// Заполнение строки с права на лево 0xA9
// |||||||||||||||||||||||||||||||||
// <- lsb adress
// Начальное значение курсора строка 0 0xAC
// ЖКИ выключен 0xAE
// ЖКИ включен 0xAF
// RESET lcd 0xE2
// Температурная компенсация включена 0xEB

// DSEG data reserved
.dseg // RAM
.org 0x70 // Set Ram adress begin
line_x: .byte 1 // Lcd line select
cmd_xll: .byte 1 // X address low byte
cmd_xlh: .byte 1 // X address high byte
cmd_yl: .byte 1 // X address low byte next string
cmd_yh: .byte 1 // X address high byte next string
display: .byte 864 // массив для вывода на ЖКИ



.cseg // FLASH

// LCD names pinouts
.equ LCD = PORTC // Порт ЖКИ
.equ dat = PC4 // вывод данных в ЖКИ
.equ clk = PC3 // вывод тактов в ЖКИ
.equ cs = PC5 // выбор чипа

.equ line1 = 0xB0 // 1
.equ line2 = 0xB1 // 2
.equ line3 = 0xB2 // 3
.equ line4 = 0xB3 // 4
.equ line5 = 0xB4 // 5
.equ line6 = 0xB5 // 6
.equ line7 = 0xB6 // 7
.equ line8 = 0xB7 // 8

init_lcd: // Инициализация ЖКИ модуля
ldi tmp,0xE2 // Internal reset
rcall lcd_cmd // выводим команду на ЖКИ
ldi tmp,0xEB // температурная компенсация включена
rcall lcd_cmd // выводим команду на ЖКИ
ldi tmp,0x2F // режим питания
rcall lcd_cmd // выводим команду на ЖКИ
ldi tmp,0xA1 // направление LSB -> MSB
rcall lcd_cmd // выводим команду на ЖКИ
ldi tmp,0x9F // Контрастность ЖКИ 0х90 ... 0х9F
rcall lcd_cmd // выводим команду на ЖКИ
ldi tmp,0xA4 // очистить все пиксели жки
rcall lcd_cmd // выводим команду на ЖКИ
ldi tmp,0xA6 // позитивное изображение
;ldi tmp,0xA7 // негативное изображение
rcall lcd_cmd // выводим команду на ЖКИ
ldi tmp,0xAF // включить дисплей
rcall lcd_cmd // выводим команду на ЖКИ
rcall clr_lcd // Очищаем ЖКИ от случайного мусора
ret // на выход


clr_line: // Очистка линии ЖКИ
ldi xl,low (96) // загружаем количество столбцов
ldi xh,high(96) //
ldi tmp,0 // загружаем данные
rjmp clr_c // очищаем их
clr_lcd: // Очистка ЖКИ
rcall lcd_line1 // выбираем начало ЖКИ
ldi xl,low (864) // количество столбцов ЖКИ = 864
ldi xh,high(864) //
ldi tmp,0 // загружаем данные
clr_c: // цикл очистки ЖКИ
rcall lcd_data // выводим данные на ЖКИ
sbiw xl,1 // счетчик цикла - 1
brne clr_c // если не равно 0 - то переходим к началу
ret // выход


print_data: // выводим 864 байта из RAM в ЖКИ
rcall lcd_line1 // выбираем начало ЖКИ
ldi xl,low (864) // количество байт ЖКИ = 864
ldi xh,high(864) //
ldi yl,low (display) // загружаем адрес L начала блока RAM
ldi yh,high(display) // загружаем адрес H начала блока RAM
print_c: // цикл вывода данных в ЖКИ
ld tmp,Y+ // загружаем данные в регистр из RAM с постинкрементом адреса
rcall lcd_data // выводим данные на ЖКИ
sbiw xl,1 // счетчик цикла - 1
brne print_c // если не равно 0 - то переходим к началу
ret // выход


lcd_cmd: // передача команды на ЖКИ
cbi lcd,cs // CS -> 0
cbi lcd,dat // DAT -> 0
sbi lcd,clk // CLK -> 1
cbi lcd,clk // CLK -> 0
rjmp out_byte // вывести 8 битов
lcd_data: // передача данных на ЖКИ
cbi lcd,cs // выбор чипа
sbi lcd,dat // DAT -> 1
sbi lcd,clk // CLK -> 1
cbi lcd,clk // CLK -> 0
out_byte: // вывод 8 битов из регистра
ldi loop,8 // bit counter
out_c: // цикл
clc // очищаем кари флаг
rol tmp // tmp << 1
brcc d_zer // если флаг очищен , до значит данные DATA -> 0
sbi lcd,dat // если установлен DATA -> 1
rjmp d_one //
d_zer: //
cbi lcd,dat // DATA=0
d_one: //
sbi lcd,clk // CLK -> 1 импульс
cbi lcd,clk // CLK -> 0
dec loop // счетчик цикла - 1
brne out_c //
sbi lcd,cs // CS -> 1
ret // выход


print_char: // Вывод на ЖКИ символа ASCII 5 х 7
push zl // сохранить zl регистр в стеке
push zh // сохранить zh регистр в стеке (последним зашел , первым вышел)
ldi tmp,5 // загрузить значение первого множителя
muls xl,tmp // Multiply signed xh and tmp
movw xl,r0 // Copy result back in xl:xh
ldi tmp,160 // загрузить число 160 DEC в регистр
sub xl,tmp // отнять от пары число 160 0x00 - 0x1F ненужная дата 0x1F * 5 (количество байтов в символе) = 160.
sbc xh,zero // число 160 - это количество сэкономленых и ненужных байт в флэш мк
ldi ZH,high(Code*2) // загрузить старший адрес строки данных
ldi ZL,low (Code*2) // загрузить младший адрес строки данных
add ZL,xl // выбираем нужный символ в строке
adc ZH,xh // путем прибавления данных к адресу строки
ldi tmp1,5 // загружаем счетчик цикла
flash_rc: // Чтение символа ASCII в цикле
lpm tmp,Z+ // загрузить в регистр данные по адресу Z с прибавлением 1 к Z
rcall lcd_data // вывести байт на ЖКИ
dec tmp1 // счетчик - 1
brne flash_rc // если не = 0 то опять по кругу
clr tmp // вывести пробел после символа
rcall lcd_data // вывести байт на ЖКИ
pop zh // извлечь zh из стека
pop zl // извлечь zl из стека
ret // выход

out_text: // Вывод текста из данных флэши
lpm xl,Z+ // загрузить в регистр данные по адресу Z с прибавлением 1 к Z
rcall print_char // вывести символ на ЖКИ
dec loop2 // счетчик символов - 1
brne out_text // если не равно 0 то опять все повторяем
ret // выход


print_char_b: // вывод на ЖКИ символа 9 х 14.
lds tmp,line_x // загружаем данные начальной строки вывода
sts cmd_yl,tmp // сохраняем данные команды адреса верхней строки
inc tmp // данные строки + 1
sts cmd_yh,tmp // сохраняем данные команды адреса нижней строки
lds tmp,cmd_xlh // загружаем старший байт адреса Х
rcall lcd_cmd // выводим команду
lds tmp,cmd_xll // загружаем младший байт адреса Х
rcall lcd_cmd // выводим команду
lds tmp,cmd_yl // загружаем адрес Y
rcall lcd_cmd // выводим команду
ldi tmp,18 // загрузить значение первого множителя
muls xl,tmp // Multiply signed xh and tmp
movw xl,r0 // Copy result back in xl:xh
ldi zh,high(Cod*2) // загрузить старший адрес строки данных
ldi zl,low (Cod*2) // загрузить младший адрес строки данных
add zl,xl // выбираем нужный символ в строке
adc zh,xh // путем прибавления данных к адресу строки
adiw xl,9 // прибавляем к адресу чтения данных 9
ldi tmp1,9 // загружаем счетчик цикла
flash_rc1: // Чтение символа ASCII в цикле
lpm tmp,z+ // загрузить в регистр данные по адресу Z с прибавлением 1 к Z
rcall lcd_data // вывести байт на ЖКИ
dec tmp1 // счетчик - 1
brne flash_rc1 // если не = 0 то опять по кругу
lds tmp,cmd_xlh // загружаем старший байт адреса Х
rcall lcd_cmd // выводим команду
lds tmp,cmd_xll // загружаем младший байт адреса Х
rcall lcd_cmd // выводим команду
lds tmp,cmd_yh // загружаем адрес Y+1
rcall lcd_cmd // выводим команду
ldi zh,high(Cod*2) // загрузить старший адрес строки данных
ldi zl,low (Cod*2) // загрузить младший адрес строки данных
add zl,xl // выбираем нужный символ в строке
adc zh,xh // путем прибавления данных к адресу строки
ldi tmp1,9 // загружаем счетчик цикла
flash_rc2: // Чтение символа ASCII в цикле
lpm tmp,z+ // загрузить в регистр данные по адресу Z с прибавлением 1 к Z
andi tmp,0x3F // чистим 2 ненужных бита
rcall lcd_data // вывести байт на ЖКИ
dec tmp1 // счетчик - 1
brne flash_rc2 // если не = 0 то опять по кругу
ret // выход



lcd_line1: // 1я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB0 //
rcall lcd_cmd //
ret //
lcd_line2: // 2я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB1 //
rcall lcd_cmd //
ret //
lcd_line3: // 3я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB2 //
rcall lcd_cmd //
ret //
lcd_line4: // 4я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB3 //
rcall lcd_cmd //
ret //
lcd_line5: // 5я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB4 //
rcall lcd_cmd //
ret //
lcd_line6: // 6я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB5 //
rcall lcd_cmd //
ret //
lcd_line7: // 7я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB6 //
rcall lcd_cmd //
ret //
lcd_line8: // 8я Линия ЖКИ для вывода информации
rcall lcd_line //
ldi tmp,0xB7 //
rcall lcd_cmd //
ret //
lcd_line: //
ldi tmp,0x10 //
rcall lcd_cmd //
ldi tmp,0x00 //
rcall lcd_cmd //
ret //



simvol_1: // установка адреса 1 символа 1
ldi tmp,0x10 //
sts cmd_xlh,tmp //
ldi tmp,0x01 //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход
simvol_2: // установка адреса 13 символа 2
ldi tmp,0x10 //
sts cmd_xlh,tmp //
ldi tmp,0x0d //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход
simvol_3: // установка адреса 25 символа 3
ldi tmp,0x11 //
sts cmd_xlh,tmp //
ldi tmp,0x09 //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход
simvol_4: // установка адреса 37 символа 4
ldi tmp,0x12 //
sts cmd_xlh,tmp //
ldi tmp,0x05 //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход
simvol_5: // установка адреса 49 символа 5
ldi tmp,0x13 //
sts cmd_xlh,tmp //
ldi tmp,0x01 //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход
simvol_6: // установка адреса 61 символа 6
ldi tmp,0x13 //
sts cmd_xlh,tmp //
ldi tmp,0x0d //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход
simvol_7: // установка адреса 73 символа 7
ldi tmp,0x14 //
sts cmd_xlh,tmp //
ldi tmp,0x09 //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход
simvol_8: // установка адреса 85 символа 8
ldi tmp,0x15 //
sts cmd_xlh,tmp //
ldi tmp,0x05 //
sts cmd_xll,tmp //
rcall print_char_b // вывести символ 9 х 14 на ЖКИ
ret // выход



demonstration: // Вывод текста из FLASH на ЖКИ
rcall lcd_line2 // выбираем строку
ldi zh,high(txt1*2) // загружаем начальный адрес строки текста
ldi zl,low (txt1*2) // умножаем указатель адреса на 2
ldi loop2,16 // загружаем количество символов в строке
rcall out_text // выводим текст на ЖКИ

rcall lcd_line4 // выбираем строку
ldi zh,high(txt2*2) // загружаем начальный адрес строки текста
ldi zl,low (txt2*2) // умножаем указатель адреса на 2
ldi loop2,16 // загружаем количество символов в строке
rcall out_text // выводим текст на ЖКИ

rcall lcd_line6 // выбираем строку
ldi zh,high(txt3*2) // загружаем начальный адрес строки текста
ldi zl,low (txt3*2) // умножаем указатель адреса на 2
ldi loop2,16 // загружаем количество символов в строке
rcall out_text // выводим текст на ЖКИ

rcall lcd_line8 // выбираем строку
ldi zh,high(txt4*2) // загружаем начальный адрес строки текста
ldi zl,low (txt4*2) // умножаем указатель адреса на 2
ldi loop2,16 // загружаем количество символов в строке
rcall out_text // выводим текст на ЖКИ

;rcall wait_075s
rcall wait_075s
rcall clr_lcd // очистка ЖКИ
ret // выход




Txt1: // Текст 1
.db "pavel-pervomaysk"
Txt2: // Текст 2
.db "www.cnc-lab.com "
Txt3: // Текст 3
.db "ATmega8A-PU cpu "
Txt4: // Текст 4
.db "Nokia 1110i LCD "



// ASCII CODE from lcd 5 x 7 pixels. Один символ = 5 байт
Code:.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00 ; 0x20 ' ' ; 0x21 '!'
.db 0x00,0x07,0x00,0x07,0x00,0x14,0x7f,0x14,0x7f,0x14 ; 0x22 '"' ; 0x23 '#'
.db 0x24,0x2a,0x7f,0x2a,0x12,0x23,0x13,0x08,0x64,0x62 ; 0x24 '$' ; 0x25 '%'
.db 0x36,0x49,0x55,0x22,0x50,0x00,0x05,0x03,0x00,0x00 ; 0x26 '&' ; 0x27 ''
.db 0x00,0x1c,0x22,0x41,0x00,0x00,0x41,0x22,0x1c,0x00 ; 0x28 '(' ; 0x29 ')'
.db 0x14,0x08,0x3e,0x08,0x14,0x08,0x08,0x3e,0x08,0x08 ; 0x2A '*' ; 0x2B '+'
.db 0x00,0x50,0x30,0x00,0x00,0x08,0x08,0x08,0x08,0x08 ; 0x2C ',' ; 0x2D '-'
.db 0x00,0x60,0x60,0x00,0x00,0x20,0x10,0x08,0x04,0x02 ; 0x2E '.' ; 0x2F '/'
.db 0x3e,0x51,0x49,0x45,0x3e,0x00,0x42,0x7f,0x40,0x00 ; 0x30 '0' ; 0x31 '1'
.db 0x42,0x61,0x51,0x49,0x46,0x21,0x41,0x45,0x4b,0x31 ; 0x32 '2' ; 0x33 '3'
.db 0x18,0x14,0x12,0x7f,0x10,0x27,0x45,0x45,0x45,0x39 ; 0x34 '4' ; 0x35 '5'
.db 0x3c,0x4a,0x49,0x49,0x30,0x01,0x71,0x09,0x05,0x03 ; 0x36 '6' ; 0x37 '7'
.db 0x36,0x49,0x49,0x49,0x36,0x06,0x49,0x49,0x29,0x1e ; 0x38 '8' ; 0x39 '9'
.db 0x00,0x36,0x36,0x00,0x00,0x00,0x56,0x36,0x00,0x00 ; 0x3A ':' ; 0x3B ';'
.db 0x08,0x14,0x22,0x41,0x00,0x14,0x14,0x14,0x14,0x14 ; 0x3C '<' ; 0x3D '='
.db 0x00,0x41,0x22,0x14,0x08,0x02,0x01,0x51,0x09,0x06 ; 0x3E '>' ; 0x3F '?'
.db 0x32,0x49,0x79,0x41,0x3e,0x7e,0x11,0x11,0x11,0x7e ; 0x40 '' ; 0x41 'A'
.db 0x7f,0x49,0x49,0x49,0x36,0x3e,0x41,0x41,0x41,0x22 ; 0x42 'B' ; 0x43 'C'
.db 0x7f,0x41,0x41,0x22,0x1c,0x7f,0x49,0x49,0x49,0x41 ; 0x44 'D' ; 0x45 'E'
.db 0x7f,0x09,0x09,0x09,0x01,0x3e,0x41,0x49,0x49,0x7a ; 0x46 'F' ; 0x47 'G'
.db 0x7f,0x08,0x08,0x08,0x7f,0x00,0x41,0x7f,0x41,0x00 ; 0x48 'H' ; 0x49 'I'
.db 0x20,0x40,0x41,0x3f,0x01,0x7f,0x08,0x14,0x22,0x41 ; 0x4A 'J' ; 0x4B 'K'
.db 0x7f,0x40,0x40,0x40,0x40,0x7f,0x02,0x0c,0x02,0x7f ; 0x4C 'L' ; 0x4D 'M'
.db 0x7f,0x04,0x08,0x10,0x7f,0x3e,0x41,0x41,0x41,0x3e ; 0x4E 'N' ; 0x4F 'O'
.db 0x7f,0x09,0x09,0x09,0x06,0x3e,0x41,0x51,0x21,0x5e ; 0x50 'P' ; 0x51 'Q'
.db 0x7f,0x09,0x19,0x29,0x46,0x46,0x49,0x49,0x49,0x31 ; 0x52 'R' ; 0x53 'S'
.db 0x01,0x01,0x7f,0x01,0x01,0x3f,0x40,0x40,0x40,0x3f ; 0x54 'T' ; 0x55 'U'
.db 0x1f,0x20,0x40,0x20,0x1f,0x3f,0x40,0x38,0x40,0x3f ; 0x56 'V' ; 0x57 'W'
.db 0x63,0x14,0x08,0x14,0x63,0x07,0x08,0x70,0x08,0x07 ; 0x58 'X' ; 0x59 'Y'
.db 0x61,0x51,0x49,0x45,0x43,0x00,0x7f,0x41,0x41,0x00 ; 0x5A 'Z' ; 0x5B '['
.db 0x02,0x04,0x08,0x10,0x20,0x00,0x41,0x41,0x7f,0x00 ; 0x5C '' ; 0x5D ']'
.db 0x04,0x02,0x01,0x02,0x04,0x40,0x40,0x40,0x40,0x40 ; 0x5E '^' ; 0x5F '_'
.db 0x00,0x01,0x02,0x04,0x00,0x20,0x54,0x54,0x54,0x78 ; 0x60 '' ; 0x61 'a'
.db 0x7f,0x48,0x44,0x44,0x38,0x38,0x44,0x44,0x44,0x20 ; 0x62 'b' ; 0x63 'c'
.db 0x38,0x44,0x44,0x48,0x7f,0x38,0x54,0x54,0x54,0x18 ; 0x64 'd' ; 0x65 'e'
.db 0x08,0x7e,0x09,0x01,0x02,0x0c,0x52,0x52,0x52,0x3e ; 0x66 'f' ; 0x67 'g'
.db 0x7f,0x08,0x04,0x04,0x78,0x00,0x44,0x7d,0x40,0x00 ; 0x68 'h' ; 0x69 'i'
.db 0x20,0x40,0x44,0x3d,0x00,0x7f,0x10,0x28,0x44,0x00 ; 0x6A 'j' ; 0x6B 'k'
.db 0x00,0x41,0x7f,0x40,0x00,0x7c,0x04,0x18,0x04,0x78 ; 0x6C 'l' ; 0x6D 'm'
.db 0x7c,0x08,0x04,0x04,0x78,0x38,0x44,0x44,0x44,0x38 ; 0x6E 'n' ; 0x6F 'o'
.db 0x7c,0x14,0x14,0x14,0x08,0x08,0x14,0x14,0x18,0x7c ; 0x70 'p' ; 0x71 'q'
.db 0x7c,0x08,0x04,0x04,0x08,0x48,0x54,0x54,0x54,0x20 ; 0x72 'r' ; 0x73 's'
.db 0x04,0x3f,0x44,0x40,0x20,0x3c,0x40,0x40,0x20,0x7c ; 0x74 't' ; 0x75 'u'
.db 0x1c,0x20,0x40,0x20,0x1c,0x3c,0x40,0x30,0x40,0x3c ; 0x76 'v' ; 0x77 'w'
.db 0x44,0x28,0x10,0x28,0x44,0x0c,0x50,0x50,0x50,0x3c ; 0x78 'x' ; 0x79 'y'
.db 0x44,0x64,0x54,0x4c,0x44,0x00,0x08,0x36,0x41,0x00 ; 0x7A 'z' ; 0x7B '{'
.db 0x00,0x00,0x7f,0x00,0x00,0x00,0x41,0x36,0x08,0x00 ; 0x7C '|' ; 0x7D '}'
.db 0x10,0x08,0x08,0x10,0x08,0x06,0x09,0x09,0x06,0x00 ; 0x7E '->'; 0x7F ' ' градус цельсия



// ASCII CODE from lcd 9 x 14 pixels. Один символ = 18 байт
Cod: .db 0xff,0xff,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x3f,0x3f ; '0'
.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x3f,0x3f ; '1'
.db 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xff,0xff,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x30,0x30 ; '2'
.db 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xff,0xff,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x3f,0x3f ; '3'
.db 0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x3f,0x3f ; '4'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x3f,0x3f ; '5'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x3f,0x3f ; '6'
.db 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x3f,0x3f ; '7'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xff,0xff,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x3f,0x3f ; '8'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xff,0xff,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x3f,0x3f ; '9'
.db 0xfc,0xfe,0xc3,0xc3,0xc3,0xc3,0xc3,0xfe,0xfc,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,
0x3f,0x3f ; 'A'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0x3c,0x3c,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x0f,0x0f ; 'B'
.db 0xfc,0xfc,0x03,0x03,0x03,0x03,0x03,0x0c,0x0c,0x0f,0x0f,0x30,0x30,0x30,0x30,0x30,
0x0c,0x0c ; 'C'
.db 0xff,0xff,0x03,0x03,0x03,0x03,0x03,0xfc,0xfc,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x0f,0x0f ; 'D'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x03,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x30,0x30 ; 'E'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x03,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,
0x00,0x00 ; 'F'
.db 0xfc,0xfe,0x03,0x03,0x83,0x83,0x83,0x8e,0x8c,0x0f,0x1f,0x30,0x30,0x31,0x31,0x31,
0x1f,0x0f ; 'G'
.db 0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xff,0xff,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,
0x3f,0x3f ; 'H'
.db 0x00,0x03,0x03,0xff,0xff,0x03,0x03,0x00,0x00,0x00,0x30,0x30,0x3f,0x3f,0x30,0x30,
0x00,0x00 ; 'I'
.db 0x00,0x00,0x00,0x03,0x03,0xff,0xff,0x03,0x03,0x0c,0x1c,0x30,0x30,0x30,0x1f,0x0f,
0x00,0x00 ; 'J'
.db 0xff,0xff,0xc0,0xe0,0x30,0x18,0x0c,0x07,0x03,0x3f,0x3f,0x00,0x01,0x03,0x06,0x0c,
0x38,0x30 ; 'K'
.db 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,
0x30,0x30 ; 'L'
.db 0xff,0xff,0x06,0x0c,0x18,0x0c,0x06,0xff,0xff,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,
0x3f,0x3f ; 'M'
.db 0xff,0xff,0x30,0x60,0xc0,0x80,0x00,0xff,0xff,0x3f,0x3f,0x00,0x00,0x00,0x01,0x03,
0x3f,0x3f ; 'N'
.db 0xfc,0xfe,0x03,0x03,0x03,0x03,0x03,0xfe,0xfc,0x0f,0x1f,0x30,0x30,0x30,0x30,0x30,
0x1f,0x0f ; 'O'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0x7e,0x3c,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,
0x00,0x00 ; 'P'
.db 0xfc,0xfe,0x03,0x03,0x03,0x03,0x03,0xfe,0xfc,0x0f,0x1f,0x30,0x30,0x34,0x2c,0x18,
0x37,0x2f ; 'Q'
.db 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0x7e,0x3c,0x3f,0x3f,0x01,0x03,0x06,0x0c,0x18,
0x30,0x20 ; 'R'
.db 0x3c,0x7e,0xc3,0xc3,0xc3,0xc3,0xc3,0x83,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,
0x1f,0x0f ; 'S'
.db 0x03,0x03,0x03,0xff,0xff,0xff,0x03,0x03,0x03,0x00,0x00,0x00,0x3f,0x3f,0x3f,0x00,
0x00,0x00 ; 'T'
.db 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0f,0x1f,0x30,0x30,0x30,0x30,0x30,
0x1f,0x0f ; 'U'
.db 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x03,0x07,0x0c,0x18,0x30,0x18,0x0c,
0x07,0x03 ; 'V'
.db 0xff,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0x0f,0x1f,0x30,0x30,0x1f,0x30,0x30,
0x1f,0x0f ; 'W'
.db 0x07,0x0f,0x18,0xf0,0xe0,0xf0,0x18,0x0f,0x07,0x38,0x3c,0x06,0x03,0x01,0x03,0x06,
0x3c,0x38 ; 'X'
.db 0x3f,0x7f,0xc0,0xc0,0xc0,0xc0,0xc0,0x7f,0x3f,0x00,0x00,0x00,0x3f,0x3f,0x3f,0x00,
0x00,0x00 ; 'Y'
.db 0x03,0x03,0x03,0x83,0xc3,0x63,0x33,0x1f,0x0f,0x3c,0x3e,0x33,0x31,0x30,0x30,0x30,
0x30,0x30 ; 'Z'


.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00 ; ' '
.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x00,
0x00,0x00 ; '.'
.db 0x00,0x00,0x00,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x00,
0x00,0x00 ; ':'
.db 0x00,0x1c,0x3e,0x63,0x63,0x63,0x3e,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00 ; 'o' градус цельсия
.db 0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00 ; '-' минус
.db 0xc0,0xc0,0xc0,0xf8,0xf8,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,
0x00,0x00 ; '+' плюс
.db 0x80,0x40,0x40,0x40,0x80,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x01,0x01,
0x01,0x00 ; '~' переменка


; .db 0x,0x,0x,0x,0x,0x,0x,0x,0x, ; здесь добавляем свои символы 9 х 14
; .db 0x,0x,0x,0x,0x,0x,0x,0x,0x ; ' '


s_black
Исходники на Си для работы МК с симистором, ЖКИ, клавиатурами, энкодером, I2C, UART и многое другое
Spider
Собрал библиотеку avr-libc-1.7.1 с патчем far pointer для WInAVR. Пытался найти готовую на просторах, но не нашёл. Вдруг кому будет интересно.
Источник: http://savannah.nongnu.org/patch/?6352
ESN
Flash память AT25080,AT25160,AT25320,AT25640
В программе, написанной на ассемблере, данные пишутся и читаются по SPI интерфейсу из AT25080. Было бы полезно, дополнять описания на микросхемы чем-либо подобным.
Deka
Ассемблер! Как много в этом слове... В общем сделал для себя небольшой комплект макросов для работы с сигналами, событиями и флагами. Сигналы - эл.сигналы подключенные к МК. За описанием сигнала скрыт реальный пин порта к которому тот подключен. Вариант небольшого HAL. События и флаги - то, что происходит в программе и её состояние. 8 флагов и 8 событий. Это просто биты в двух выделенных регистрах, но я сделал макросы удобной работы с ними. Теперь сложнее ошибиться и код читабельнее получается. По крайней мере для меня. Ну и ещё сделал немного доп.команд. Что-то сам придумал, а что-то из инета почерпнул. Все макросы объединил в файл MyMacros.inc и подключаю во все свои проекты. Далее для всего сделанного реализовал подсветку синтаксиса для студии 4 (файл AvrStudio_asm.ini). Им надо переписать дефолтный файл и после этого можно будет изменять цвет в IDE. Ну и последнее что сделал - расширил и перекомпилировал хелп файл студии (опять-же Avr Studio 4) для поддержки справкой добавленных макросов и команд. Кому всё ещё интересно матёрое программирование на асме - прошу заценить. Жду Ваши комментарии и пожелания. biggrin.gif
Deka
Комментариев и пожеланий к моему прошому посту не последовало - выкладываю новую версию. В ней исправлены некоторые ошибки и добавлено описание как это использовать.
uni
Шаблоны проектов на 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 (в железе тоже работает и куда шустрее модели):

Нажмите для просмотра прикрепленного файла

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

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

Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла
BigallS
Цитата(uni @ Apr 21 2013, 14:03) *
Шаблоны проектов на C++ для AVR [GCC, IAR]

Шаблоны: https://mysvn.ru/avr/templates/
Примеры: https://mysvn.ru/avr/examples/

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

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

Очень интересно, спасибо будем пробовать!
bob1
32-х битная библиотека с плавающей точкой для AVR (ассемблер).
AI7
Цитата(Deka @ Dec 4 2012, 06:32) *
Ассемблер! Как много в этом слове... В общем сделал для себя небольшой комплект макросов для работы с сигналами, событиями и флагами. Кому всё ещё интересно матёрое программирование на асме - прошу заценить. Жду Ваши комментарии и пожелания. biggrin.gif


Deka, для AVR есть графический ассемблер Algorithm Builder (АБ), раз в 5 удобней, чем классический ассемблер.
Поэтому не имеет смысла писать на классическом ассемблере, тем более, что сейчас АБ бесплатный.
Похоже, некоторые Ваши предложения там сделаны на уровне компилятора.
При написании на АБ быстро пришел к тому, что практически не использую имен регистров, бит.
Скажем, у меня команда для включения вентилятора будет выглядеть так:
vkl_FAN, а для выключения, естественно, vykl_FAN.
Если вентилятор подключен к PORTB.0, эти команды представляют собой макросы:
1 -> PORTB.0 и 0 -> PORTB.0.

В АБ масса удобств, например, подпрограммы с параметрами.
При их использовании, например, умножение двух двухбайтных переменных А и В можно записать одной строчкой:
Umnojenie(A,cool.gif

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

Игoрь
ага, конечно нет смысла писать на классическом ассемблере sm.gif
Как-то разбирался я со схемой, которая должна была формировать импульсы длительностью 0,8 мкс частотой 200 Гц и измерять время между этими импульсами и ответами от другого устройства. Так вот нагородили там огород из атмеги256 и плисины. На вопрос зачем так сложно последовал ответ- на одном микроконтроллере невозможно точно отсчитать время. А всё почему? Потому что подсели на С и не знают теперь сколько по времени выполняются команды. Реально можно вполне было обойтись атмегой8 без всяких плисин.
Сергей Борщ
Цитата(Игoрь @ Dec 21 2013, 11:04) *
Потому что подсели на С и не знают теперь сколько по времени выполняются команды. Реально можно вполне было обойтись атмегой8 без всяких плисин.
Зависит от того, с какой точностью надо было измерять задержку. Если не менее 1/Fcpu, то подумав и задействовав модули захвата и сравнения таймера процессор мог бы делать еще какую-то полезную работу кроме измерения количества потраченных впустую тактов. Даже если программу написать на Си. Легко. А если нужна бОльшая точность, то без внешних элементов не обойтись хоть в машинных кодах пишите.
pavel-pervomaysk
NEC IR приемник для AVR

CODE

; 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 ();

скачать

Принимаются комментарии по реализации и работе.
Xln
Мой пример формирователя задержек с разрешением в 1 такт для микроконтроллеров AVR на ассемблере.
Всего 12 команд / 24 байта.

CODE

; Процедура формирования программируемых задержек с разрешением 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
Xln
В догонку.
Библиотека математических функций для микроконтроллеров Mega (часть функций не используют команд умножения – они применимы и для Tiny) на ассемблере.
Оформлена в виде макросов, переопределения регистров также выполнены в виде макросов.
Краткий перечень содержимого:
Умножение с накоплением для знаковых 24-х битных чисел (результат 48 бит).
Умножение с накоплением для знаковых 32-х битных чисел (результат 64 бита).
Деление беззнаковых 32-х битных чисел.
Преобразования вида: число с фиксированной точкой -> строка, строка -> число с фиксированной точкой.
Код сопровождён пояснениями.
Понятно, что если задача насыщенна 32-х битными вычислениями то проще выбрать 32-х битный микроконтроллер, но если в существующий проект на AVR понадобилось внести такие операции – библиотека есть. Да и 20 МГц AVR в частности вполне достаточно для выполнения несложных фильтров (рекурсивный 2, 4, 6 порядки) на частотах дискретизации 3-5 кГц.
dm37
Демонстрационный пример AVR_Menu2

Описание примера:
Пример, показывает вариант построения многоуровневого меню для текстовых LCD
индикаторов на базе контроллера HD44780, управление с помощью клавиатуры
(8 кнопок), приём 16 дискретных сигналов, передача 16 дискретных сигналов.
В состав проекта входят исходные коды на языке C и проект для Proteus.

Оборудование:
- ATmega32;
- LCD 1604 (HD44780);
- клавиатура (8 кнопок: Up, Down, Left, Right, Enter, Escape, Menu, Reserve);
- 2 регистра ввода (74HC245);
- 2 регистра вывода (74HC573);
- зуммер.

Программное обеспечение:
- среда разработки: IAR Embedded Workbench 6.70.4 (AVR)
- среда эмулирования: Proteus 7.10

-------------------------------------------------------------------------------
Пароль для доступа в меню настроек:
нажать кнопку Menu
и последовательно нажать кнопки Left -> Right -> Up -> Left -> Right


avr_menu1 (LCD4004) - вариант с LCD индикатором 40x4 (2xHD44780)

Дополнительно небольшое видео работы проекта в proteus по ссылке: https://ru.files.fm/u/a2sfccuf#/list/
dm37
В проектах avr_menu исправлена небольшая ошибка (из-за copy/paste), которая не позволяла вывести регистры вывода 74HC573 из третьего состояния.
Также добавил видео демонстрирующее функционал проекта avr_menu https://ru.files.fm/u/a2sfccuf#/list/
Gorby
Цитата(dm37 @ Aug 15 2016, 16:13) *
В проектах avr_menu исправлена небольшая ошибка


Ну, раз началася работа над ошибками, то сделайте, будьте добры так, чтобы меню управлялось пятермыми кнопками: лево-право, верх-низ и Меню.
Имею обоснованное сомнение что Ваши восемь кнопок кому-то понравятся.

"Напишите программу, которой может пользоваться даже идиот, и только идиот захочет ею воспользоваться" 'c'
dm37
Изначально кнопок было 6 (влево-вправо-вверх-вниз-ENTER-ESCAPE). Количество кнопок можно сделать любое от 1 до 8. Функции на кнопки назначаются в каждом меню отдельно, так что всё зависит от вашей фантазии. Если вам нужно именно ваше сочетание кнопок, могу подкорректировать и выслать вам на почту, чтобы не плодить версии.
Во вложении проект с 6-ю кнопками (выжимка из одного проекта) + работа с датчиком DS18B20 + RTC DS1307 (i2c soft).
fenakit
dm37, запускаю проект avr_menu1 (ничего не меняя), и вот такая картинкаНажмите для просмотра прикрепленного файла. Нету кодировки кириллицы. В чем может быть проблема? Уже пробовал разные версии IAR и Proteus. А так заготовка для проектов понравилась, сделано професионально.
fenakit
Уже нашел причину - нужна патченая модель LCD для Proteus.
dm37
Мои наработки по использованию языка C++ для микроконтроллеров:
-микроконтроллеры ATtiny2313, ATmega32
-компилятор IAR Embedded Workbench for Atmel AVR 6.80
-симулятор Proteus 7.10

Что получилось можно посмотреть здесь
https://ru.files.fm/u/a2sfccuf#/list/
файл uC_cpp.7z

Внутри:
- пример с динамической индикацией (исходники + proteus)
- пример с LCD на HD44780 (исходники + proteus)
- небольшое описание
dm37
по С++ обновил описание
https://ru.files.fm/u/a2sfccuf#/list/
файл uC_cpp.7z
technik-1017
Добрый день,
предлагаю свой вариант конвертера текста для индикатора на контроллере HD44780 (CP1251 -> HD44780).
Преобразование производится на уровне компиляции и строится на использовании макроса LCD_TEXT_XX (файл lcd_conv.h). Данный макрос может быть использован с любым компилятором языка Си.

Во вложении файл lcd_conv.h и описание.
demiurg1978
Цитата(dm37 @ Aug 15 2016, 21:13) *
...

Слишком сложно. Лучше MicroMenu для микроконтроллеров не нашел для себя.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.