Управление портами как в CodeVisionAvr
Наверное, многие, как и я, начинали обучение миру микроконтроллеров в такой замечательной среде программирования как CodeVisionAvr. И не спроста – компилятор предоставляет возможности, несколько упрощающие жизнь программисту. Одна из таких возможностей - обращение к конкретным ножкам определённого порта в явном виде.
Например, мы хотим включить ножку 5 порта C. В CVAvr это делается так:
PORTC.5 = 1;
А в WinAvr (avr-gcc) это делается так (что более правильно, я не спорю, но менее комфортно):
PORTC |= _BV(5);
И выключаем ту же ножку. CVAvr:
PORTC.5 = 0;
А в WinAvr:
PORTC &= ~_BV(5);
Не так наглядно, согласитесь? Так что попробуем добиться такого же вида обращения к портам как и в CVAvr.
Для этого нужно создать восьмибитную структуру:
struct port_byte { bool P0 : 1; bool P1 : 1; bool P2 : 1; bool P3 : 1; bool P4 : 1; bool P5 : 1; bool P6 : 1; bool P7 : 1; };
Дабы компилятор не ругался на bool нужно подключить заголовок stdbool.h
Теперь самое интересное. Нужно создать переменную-указатель для нужного порта и присвоить ей начальный адрес. В данном случае используем PORTC:
struct port_byte *CVPORTC = (struct port_byte *) &(PORTC);
Готово! Теперь можно обращаться к ножкам порта через эту переменную:
CVPORTC->P5 = 1; _delay_ms(500); CVPORTC->P5 = 0;
Для удобства я объединил переменные мне известных портов и несколько битовых функций в один заголовок. Для использования нужно либо добавить в флаги компилятора определение
-DCVPORTS
либо в программе явно объявить
#define CVPORTS
По умолчанию не включал в связи с тем, что указатели тоже место занимают.
/* * Author: MultiMote * Date: 03.06.2016 * URL: http://multimote.ru/avr-gcc-cvports */ #ifndef __BITS_OPS_H_ #define __BITS_OPS_H_ #define CVPORTS #include <stdbool.h> struct port_byte { bool P0 : 1; bool P1 : 1; bool P2 : 1; bool P3 : 1; bool P4 : 1; bool P5 : 1; bool P6 : 1; bool P7 : 1; }; #define _B_DECLPORT(port) struct port_byte *_##port = (struct port_byte *)&(port) #ifdef CVPORTS #ifdef PORTA struct port_byte *CVPORTA = (struct port_byte *) &(PORTA); struct port_byte *CVPINA = (struct port_byte *) &(PINA); struct port_byte *CVDDRA = (struct port_byte *) &(DDRA); #endif #ifdef PORTB struct port_byte *CVPORTB = (struct port_byte *) &(PORTB); struct port_byte *CVPINB = (struct port_byte *) &(PINB); struct port_byte *CVDDRB = (struct port_byte *) &(DDRB); #endif #ifdef PORTC struct port_byte *CVPORTC = (struct port_byte *) &(PORTC); struct port_byte *CVPINC = (struct port_byte *) &(PINC); struct port_byte *CVDDRC = (struct port_byte *) &(DDRC); #endif #ifdef PORTD struct port_byte *CVPORTD = (struct port_byte *) &(PORTD); struct port_byte *CVPIND = (struct port_byte *) &(PIND); struct port_byte *CVDDRD = (struct port_byte *) &(DDRD); #endif #endif #define bit_on(dest, pos) ((dest) |= (1 << (pos))) #define bit_off(dest, pos) ((dest) &= ~(1 << (pos))) #define bit_set(dest, pos, val) ((dest)^= (-(val) ^ (dest)) & (1 << (pos))) #define bit_get(dest, pos) (((dest) & (1 << (pos))) != 0) #endif
Тем не менее, использовать данную вещь не собираюсь :)
