Я хотел бы реализовать что-то похожее на номера контактов Arduino для Atmel ATMega32U4. Я посмотрел на команду Arduino digitalWrite
и связанные с ней исходные файлы, чтобы посмотреть, как они это делают, но я думаю, что это немного запутанно, поэтому я хотел реализовать более базовую версию.Реализация номеров выводов в микроконтроллере AVR, аналогичном Arduino
Идея состоит в том, чтобы иметь целые числа от 1 до n, которые представляют каждый вывод I/O на микросхеме AVR. Я начал с массивом указателей на адреса регистров DDR/PORT, где индекс будет представлять чеку:
volatile uint8_t *pin_port_dir_regs[] = {
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&DDRE, // PIN_7
&DDRB, // PIN_8
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&DDRB, // PIN_15
&DDRB // PIN_16
};
volatile uint8_t *pin_port_out_regs[] = {
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&PORTE, // PIN_7
&PORTB, // PIN_8
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&PORTB, // PIN_15
&PORTB // PIN_16
};
мне также нужно знать битовые числа в каждой из/PortX регистров DDRx, так Я создал еще один массив:
const uint8_t pin_bits[] = {
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(6), // PIN_7
_BV(4), // PIN_8
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // PIN_14
_BV(1), // PIN_15
_BV(3) // PIN_16
};
чтобы установить режим контактов и писать к выводам, я создал следующие функции:
void pin_mode(uint8_t pin, uint8_t direction) {
// defeference the pointer to the direction register
uint8_t port_dir_register = *(pin_port_dir_regs[pin]);
// get pin mask
uint8_t mask = pin_bits[pin];
// set its mode
if (direction == INPUT) {
port_dir_register &= ~mask;
} else {
port_dir_register |= mask;
}
}
void pin_write(uint8_t pin, uint8_t level) {
// defeference the pointer to the output register
uint8_t port_out_register = *(pin_port_out_regs[pin]);
// get pin mask
uint8_t mask = pin_bits[pin];
// set output
if (level == LOW) {
port_out_register &= ~mask;
} else {
port_out_register |= mask;
}
}
что должно произойти в том, что вы могли бы назвать, например, pin_mode(7, OUTPUT)
, чтобы установить вывод 7 в качестве вывода, а затем pin_write(7, HIGH)
, чтобы установить выход в 1 (где OUTPUT и HIGH являются предопределенными макросами). Код компилируется и загружается в AVR успешно, но когда я тестирую вывод, он не отвечает. Наверное, я должен написать памяти, но не тот, который соответствует указанным регистрам. Кто-нибудь видит проблему с тем, как я пытаюсь это сделать?
Почему вы не используете стандартные файлы, поставляемые с gcc для avr? Кроме того: если вы пишете некоторую инициализацию для контактов с чем-то вроде вашего метода pin_write, вы тратите много кода только на начальную фазу своей проги. Все это можно сделать с помощью кода шаблона во время компиляции вместо того, чтобы действовать с каждым выводом. Установите регистр ddr и port один раз не 8 раз для одной и той же работы. – Klaus
@Klaus, в каких стандартных файлах вы ссылаетесь? Я не знал о существующем коде, чтобы делать то, что хочу. Кроме того, на этом этапе меня не интересует оптимизация запуска, но спасибо за совет. – Sean
Это выглядит довольно пустой тратой драгоценного RAM и ROM пространства для меня. Ваш вопрос здесь не по теме. Мы - дискуссионный сайт noi, и это слишком похоже. Изменить: извините, что у меня был последний смысл. Пожалуйста, предоставьте более подробную информацию о том, что не так. См. [Ask]. – Olaf