R30, R31, R22, R23 для типов long & unsigned long.
Поэтому наша функция должна вернуть ее результат в регистрах R30, R31.
После возвращения из функции компилятор автоматически генерирует код, освобождающий стек от параметров функции, поэтому можно не задумываться об этом.
Директива #pragma warn запрещает компилятору генерировать предупреждения о том, что функция не возвращает результат.
Это необходимо, потому что компилятору не известно, что мы делаем в нашей написанной на ассемблере функции.
Использование встроенного EEPROM
Материал взят из демонстрационной версии компилятора CodeVisionAVR С Compiler, автором которого является Pavel Haiduc, HP InfoTech S.R.L.
Текст программы:
// Контроллер: AT90S2313
// Модель памяти: TINY
// Размер стека данных: 64 bytes
flash char f[]="This is a test";
#pragma warn-
eeprom char e[16];
#pragma warn+
char r[16];
void main (void)
{
Char flash *ptr_to_flash;
char eeprom *ptr_to_eeprom;
char *ptr_to_ran;
// Копировать строку f из FLASH в
// Строку e в EEPROM
ptr_to_flash=f;
ptr_to_eeprom=e;
while (*ptr_to_flash)
*ptr_to_eeprom++=*ptr_to_flash++;
// Копировать строку e из EEPROM в
// строку г в оперативной памяти
ptr_to_eeprom=e;
ptr_to_ram=r;
while (*ptr_to_eeprom)
*ptr_to_ram++=* ptr_to_eeprom++;
// Стоп (бесконечный цикл)
while (1);
}
Работа с клавиатурой 4x4
Материал взят из демонстрационной версии компилятора CodeVisionAVR С Compiler, автором которого является Pavel Haiduc, HP InfoTech S.R.L.
Рис. 4.11. Схема соединения клавиатуры 4x4
Для индикации использован 2х16 алфавитно-цифровой ЖКИ, подсоединенный к порту PORTC следующим образом:
Текст программы:
#asm
.equ __lcd_port=0x15
#endasm
#include <lcd.h>
#include <stdio.h>
#include <delay.h>
#include <90sB515.h>
// Частота кварцевого резонатора [Гц]
#define F_XTAL 4000000L
// Линии PINDO…3 будут входами строк
#define KEYIN PIND
// Линии PORTD4..7 будут выходами столбцов
#define KEYOUT P0RTD
// Инициализация использованного таймера TIMER0
#define INIT_TIMER0 TCNT0=0x100L-F_XTAL/64L/500L
#define FIRST_COLUMN 0x80
#define LAST_COLUMN 0x10
typedef unsigned char byte;
// Здесь в виде бита сохраняется состояние каждой нажатой клавиши,
// бит 0 будет KEY0, бит 1 KEY1….
unsigned keys;
// Буфер ЖКИ-индикатора
char buf[33];
// Прерывание по таймеру TIMER 0 каждые 2 мс
interrupt [TIM0_OVF] void timer0_int(void)
{
static byte key_pressed_counter=20;
static byte key_released_counter,column=FIRST_COLUMN;
static unsigned row_data,crt_key;
// Перезагрузить таймер TIMERO
INIT_TIMER0;
row_data<<=4;
// Получить группу из 4 клавиш в переменной row_data
row_data|=¯KEYIN&0xf;
column>>=1;
if (column==(LAST_C0LUHN>>1))
{
column=FIRST_COLUHN;
if (row_data==0) goto new_key;
if (key_released_counter) — key_released_counter;
else
{
if (-key_pressed_counter==9) crt_key=row_data;
else
{
if (row_data!=crt_key)
{
new_key:
key_pressed_counter=10;
key_released_counter=0;
goto end_key;
};
if (!key_pressed_counter)
{
keys=row_data;
key_released_counter =20;
};
};
};
end_key:;
row_data=0;
};
// Выбрать следующий столбец, входы будут притянуты к 5 В
KEY0UT=¯column;
}
// Проверить, были ли нажаты клавиши
unsigned inkey(void)
{
unsigned k;
if (k=keys) keys=0;
return k;
}
void init_keypad(void)
{
DDRD=0xf0;
INIT_TIHERO;
TCCR0=3;