Перед работой следует указать тип используемого программатора. На рис. 4.9 показан вид окна выбора типа программатора.
Рис. 4.9. Окно выбора типа программатора
После успешной трансляции должно появиться окно, подобное показанному на рис. 4.10. Для занесения программы в микроконтроллер, следует нажать кнопку «Program».
Рис. 4.10. Окно, появляющееся после успешной трансляции программы
Процедуры работы со встроенным АЦП AT90S8535 без прерываний
Текст программы:
// В данном примере определяются две функции для работы с АЦП:
// void ImtADC(void) инициализация АЦП
// int fieadADC(unsigned char) чтение значения напряжения на заданном входе
#include <ioB535.h>
void InitADC(void)
{
ADMUX = 0; // выбрать вход номер 0
ADCSfi = 0xC0; // включить АЦП и запустить первое "пустое" преобразование
}
int ReadADC(unsigned char channel)
{
int i;
ADMUX = channel; // Выбрать номер входа
ADCSR |= 0x40; // Начать преобразование
while (!(ADCSR & 0x10)); // Проверка завершения преобразования
ADCSR |= 0x10; //Очистка бита "Преобразование завершено" при помощи записи в него "1"
i = ADCL; // Чтение младших 8 битов ПЕРВЫМИ
i += (int)ADCH << 8; // Чтение старших 2 битов, умножение их на 256 и сложение с младшим байтом
return i;
}
void main(void)
{
unsigned int temp;
InitADC(); // Инициализация АЦП
temp=ReadADC(0); // Измерить напряжение на нулевом входе АЦП (линия РАО порта А)
}
Пример вызова написанных на ассемблере функций из С программы
Материал взят из демонстрационной версии компилятора CodeVisionAVR С Compiler, автором которого является Pavel Haiduc, HP InfoTech S.R.L.
Текст программы:
// Определение функции на ассемблере. Эта функция возвращает а+Ь+с
#pragma warn- // Запретить предупреждения
int sum_abc(int a, int b, unsigned char с) {
#asm
ldd r30, у+3;R30=LSB а
Idd r31,у+4;R31=MSB а
Idd r26,у+1;R26=LSB b
Idd r27,у+2;R27=MSB b
add r30,r26;(R31,R30)=a+b
adc r31,r27
Id r26,у;R26=c
clr r27; Преобразование с типа unsigned char в тип int
add r30,r26; (R31,R30)=(R31,R30)+C
adc r31,r27
#endasm
}
#pragma warn+ // Разрешить предупреждения
void main(void) {
int r;
// Теперь вызовем функцию и сохраним результат в r
r=sum_abc(2,4,6);
}
Некоторые пояснения.
Компилятор передает параметры функции с помощью стека данных. Первым он передаст целый параметр а, затем b и в завершение с типа unsigned char. При каждой передаче регистровая пара Y увеличивается на размер параметра (4 для типа long, 2 для int, 1 для char).
В случае параметров, состоящих из нескольких байтов, первым передается старший байт. Как вы видите, стек растет вниз. После того как все параметры функции были записаны в стек (pushed), регистр Y указывает на последний параметр с, поэтому мы можем прочитать его значение в R26, воспользовавшись командой Id r26,у.
Параметр b был записан в стек перед с, поэтому он находится по более высокому адресу в стеке данных. Мы можем прочитать его значение, воспользовавшись командами ldd r27,у+2 (старший байт) и ldd r26,у+1 (младший байт).
Старший байт был записан в стек первым, поэтому он находится по более высокому адресу.
Параметр а был записан в стек перед Ь, поэтому он находится по более высокому адресу в стеке данных. Мы можем прочитать его значение, воспользовавшись командами ldd r27,у+4 (старший байт) и ldd r26,у+3 (младший байт).
Старший байт был записан в стек первым, поэтому он находится по более высокому адресу.
Функции возвращают свои значения в следующих регистрах:
R30 для типов char & unsigned char;
R30, R31 для типов int & unsigned int;