07-11-2014, 05:03 AM
(Сообщение последний раз редактировалось: 07-11-2014, 07:06 AM БендеровецЪ.)
Если начинать с задачи "зажечь светодиод", то наверное стоит начать с конфигурации портов. В данном МК есть два порта, А и В. У каждого порта есть несколько восьмибитныз конфигурационных регистров. Для начала нужно два из них, один который задает направление (вход или выход) DDRx (DDRA для порта А и DDRB для порта В) и второй PORTx (тоже А и В).
Для того что бы сконфигурировать порт как выход в соотв бит DDRx регистра надо записать единицу (нулевой бит порта DDRA соотв пину PA0, первый - PA1 и т.д.)
С одной стороны в порт можно сразу записать число, написав DDRA = 0xff (что соотв всем единицам), ну или DDRA = 0x01 (нулевой бит в единицу), но так делать нерационально, хоть и кажется что так проще всего. Это сделает код нечитаемым. Для этого я сначала присваиваю понятные мне псевдонимы битам, например вот так:
#define REL PA0
#define DC PA1
#define LED0 PA5
#define LED1 PA4
#define FAULT PA7
#define ADC_IN3 PA3
#define ADC_IN2 PA2
#define RESET PB3
В библиотеке io.h, которую надо предварительно подключить написав #include <avr\io.h> (деректива компилятора) названиям PA0, PA1 и т.д. соотв номера пинов в порту, например PA0 на самом деле имеет значение 0 (нулевая позиция).
Написав #define REL PA0 я присваиваю REL значение которое было ранее присвоено PA0, т.е. 0, и теперь компилятор, встретив в коде REL будет подставлять это присвоеное значение.
Теперь подумав какие порты будут выходами, можно "собрать" число которое будет записано в регистр DDRA, приблизительно вот так:
#define DDRA_RESET_VALUE ( (1 << REL) + (1 << LED0) + (1 << LED1) + (0 << ADC_IN3) + (0 << ADC_IN2) + (0 << FAULT) + (0 << DC))
Т.е. там где я хочу выход, я ставлю 1, если не хочу - 0 (можно опустить поскольку это ничего не меняет)
<< это сдвиг влево, т.е. я беру единицу (в двоичной записи 00000001) и сдвигаю влево на позицию которая соотв нужному мне биту. например (1 << LED0) дает 0001000, поскольку LED0 я присвоил то что было присвоено PA4 ранее, т.е. 4.
Далее число DDRA_RESET_VALUE записывается в регистр DDRA
DDRA = DDRA_RESET_VALUE; (Достаточно ожидаемо)
Далее если мы хотим установить пины LED0 и REL в единицу нам надо записать единицу в соотв бит регистра PORTA, например вот так:
PORTA |= (1 << REL) + (1 << LED0);
запись типа a |= b; эквивалентна a = a | b;
В целом написаный код будет выглядить приблизительно вот так:
#include <avr\io.h>
#define REL PA0
#define DC PA1
#define LED0 PA5
#define LED1 PA4
#define FAULT PA7
#define ADC_IN3 PA3
#define ADC_IN2 PA2
#define RESET PB3
#define DDRA_RESET_VALUE ( (1 << REL) + (1 << LED0) + (1 << LED1) + (0 << ADC_IN3) + (0 << ADC_IN2) + (0 << FAULT) + (0 << DC))
int main(void)
{
DDRA = DDRA_RESET_VALUE;
PORTA |= (1 << REL) + (1 << LED0);
while(1)
{
}
}
Если ничего не заыбл то должно работать
N.B.
while(1)
{}
Это безконечный нулевой цикл в котором остается контроллер после установки портов.
Для того что бы сконфигурировать порт как выход в соотв бит DDRx регистра надо записать единицу (нулевой бит порта DDRA соотв пину PA0, первый - PA1 и т.д.)
С одной стороны в порт можно сразу записать число, написав DDRA = 0xff (что соотв всем единицам), ну или DDRA = 0x01 (нулевой бит в единицу), но так делать нерационально, хоть и кажется что так проще всего. Это сделает код нечитаемым. Для этого я сначала присваиваю понятные мне псевдонимы битам, например вот так:
#define REL PA0
#define DC PA1
#define LED0 PA5
#define LED1 PA4
#define FAULT PA7
#define ADC_IN3 PA3
#define ADC_IN2 PA2
#define RESET PB3
В библиотеке io.h, которую надо предварительно подключить написав #include <avr\io.h> (деректива компилятора) названиям PA0, PA1 и т.д. соотв номера пинов в порту, например PA0 на самом деле имеет значение 0 (нулевая позиция).
Написав #define REL PA0 я присваиваю REL значение которое было ранее присвоено PA0, т.е. 0, и теперь компилятор, встретив в коде REL будет подставлять это присвоеное значение.
Теперь подумав какие порты будут выходами, можно "собрать" число которое будет записано в регистр DDRA, приблизительно вот так:
#define DDRA_RESET_VALUE ( (1 << REL) + (1 << LED0) + (1 << LED1) + (0 << ADC_IN3) + (0 << ADC_IN2) + (0 << FAULT) + (0 << DC))
Т.е. там где я хочу выход, я ставлю 1, если не хочу - 0 (можно опустить поскольку это ничего не меняет)
<< это сдвиг влево, т.е. я беру единицу (в двоичной записи 00000001) и сдвигаю влево на позицию которая соотв нужному мне биту. например (1 << LED0) дает 0001000, поскольку LED0 я присвоил то что было присвоено PA4 ранее, т.е. 4.
Далее число DDRA_RESET_VALUE записывается в регистр DDRA
DDRA = DDRA_RESET_VALUE; (Достаточно ожидаемо)
Далее если мы хотим установить пины LED0 и REL в единицу нам надо записать единицу в соотв бит регистра PORTA, например вот так:
PORTA |= (1 << REL) + (1 << LED0);
запись типа a |= b; эквивалентна a = a | b;
В целом написаный код будет выглядить приблизительно вот так:
#include <avr\io.h>
#define REL PA0
#define DC PA1
#define LED0 PA5
#define LED1 PA4
#define FAULT PA7
#define ADC_IN3 PA3
#define ADC_IN2 PA2
#define RESET PB3
#define DDRA_RESET_VALUE ( (1 << REL) + (1 << LED0) + (1 << LED1) + (0 << ADC_IN3) + (0 << ADC_IN2) + (0 << FAULT) + (0 << DC))
int main(void)
{
DDRA = DDRA_RESET_VALUE;
PORTA |= (1 << REL) + (1 << LED0);
while(1)
{
}
}
Если ничего не заыбл то должно работать
N.B.
while(1)
{}
Это безконечный нулевой цикл в котором остается контроллер после установки портов.
"Найкраще сало то ковбаса." (с)