Выбрать главу

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;