А знали ли вы, что...

Доступность этого сайта зависит от наличия интернета у меня дома?

Прочее

Сайт больше не работает
на Raspberry Pi

Спасибы

Управление портами как в 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

 

По умолчанию не включал в связи с тем, что указатели тоже место занимают.

 

bits.h

/*
* 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

 

Тем не менее, использовать данную вещь не собираюсь :)