реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Передача в качестве параметра порта ввода-вывода, как?
AlexMad
сообщение Oct 7 2007, 17:23
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 262
Регистрация: 18-02-05
Из: SPb
Пользователь №: 2 743



Есть набор функций работы с однопроводными устройствами,вроде
Код
#define ONEPIN       PINC // PIN register
#define ONEDDR       DDRC // Data Direction Register
#define ONEPORT      PORTC// PORT

unsigned char OneWireReset(unsigned char mask)
{
ONEPORT &= ~(mask);                 // Normal input no pull up
if (ONEPIN == 0) return 0;        // detect 0V on buss error
ONEDDR |= mask;                        // out at 0
  delay_us(500);
ONEDDR &= ~(mask);                  // Set to input
  delay_us(70);
if ((ONEPIN & mask) == 0)
   {
     delay_us(500);
   return mask;
   }
mask&=~ONEPIN;  
  delay_us(500);
return mask;
}

Работают замечательно, НО в железе есть восемь датчиков DS18b20, подключенных к одному порту (PORTC) и еще один датчик, подключенный к другому порту. Пробовал переделать функции так, чтобы рабочий порт можно было передавать, как параметр в функцию, но либо я чего-то не допер, либо это невозможно. На текущий момент предыдущим разработчиком просто сделан второй набор функций, где они работают с другим портом. На мой взгляд это не совсем правильно.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 7 2007, 17:55
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Почему это по-вашему неправильно? У вас нехватка памяти или какая-то другая причина извращаться с оптимизацией кода?
Go to the top of the page
 
+Quote Post
AlexMad
сообщение Oct 7 2007, 18:18
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 262
Регистрация: 18-02-05
Из: SPb
Пользователь №: 2 743



Цитата(rezident @ Oct 7 2007, 21:55) *
Почему это по-вашему неправильно? У вас нехватка памяти или какая-то другая причина извращаться с оптимизацией кода?

Неправильно - потому, что сделано несколько подобных устройств и хочется не то, чтобы оптимизировать, а скорее унифицировать код - то есть, сделать одинаковые функции для разных проектов. Потому что потом приходится путаться, какая функция из какого именно порта читает.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 7 2007, 18:40
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(AlexMad @ Oct 8 2007, 00:18) *
Неправильно - потому, что сделано несколько подобных устройств и хочется не то, чтобы оптимизировать, а скорее унифицировать код - то есть, сделать одинаковые функции для разных проектов. Потому что потом приходится путаться, какая функция из какого именно порта читает.

Дык если функция работает одинаково с портами, то чтобы не переписывать обе функции можно писать одну, но при включении ее в текст исходника манипулировать адресами портов с помощью макросов.
В противном случае в функцию придется передавать все три адреса. Либо передавать номер "набора" из адресов портов, но при этом добавить кучу ветвлений для проверки и вызова той или иной операции внутри вашей функции. Или вы считаете что куча ветвлений, лучше линейного кода?
Go to the top of the page
 
+Quote Post
AlexMad
сообщение Oct 7 2007, 18:54
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 262
Регистрация: 18-02-05
Из: SPb
Пользователь №: 2 743



Цитата(rezident @ Oct 7 2007, 22:40) *
Дык если функция работает одинаково с портами, то чтобы не переписывать обе функции можно писать одну, но при включении ее в текст исходника манипулировать адресами портов с помощью макросов.
В противном случае в функцию придется передавать все три адреса. Либо передавать номер "набора" из адресов портов, но при этом добавить кучу ветвлений для проверки и вызова той или иной операции внутри вашей функции. Или вы считаете что куча ветвлений, лучше линейного кода?

Так я в вопросе и писал про то, что хочу передать как параметры все три адреса (порт, пин, ддр). Проблема в том и заключается, что сами порты не передать, а если передавать условные значения, то придется делать кучу ветвлений. Просто хотелось сделать красиво - одна функция на все порты, только в параметре указывать, какие именно.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 7 2007, 19:58
Сообщение #6


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



В avr-gcc нормально передаются указатели на порты, думаю, что и у IAR должны передаваться, причём не удивлюсь, если там найдётся какое-то "волшебное слово" по типу __flash, которое ещё и делает это более удобным.

Для большинства портов идёт единый порядок PIN-DDR-PORT (не выполняется это, например, для порта F у меги64, который в наследство от меги103 достался как порт толькона чтение и его DDRF, PORTF улетели в memory-mapped IO, включаемое при стёртом фьюзе M103).

Учитывая это, можно (но осторожно) обойтись одним указателем.

Код
#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>

typedef struct {
    uint8_t pin;
    uint8_t ddr;
    uint8_t port;
} port_t;


uint8_t OneWireReset(volatile port_t *pport, uint8_t mask)
{
    pport->port &= ~mask;
    if( (pport->pin & mask) == 0) return 0;        // detect 0V on buss error
    pport->ddr |= mask;                        // out at 0
    _delay_ms(0.5);
    pport->ddr &= ~mask;                  // Set to input
    _delay_us(70);
    if( (pport->pin & mask) == 0) {
        _delay_ms(0.5);
        return mask;
    }
    mask &= ~pport->pin;
    _delay_ms(0.5);
    return mask;
}

uint8_t test(void) {
    return OneWireReset( (volatile port_t*)&PINB, 0x02);
}


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
prottoss
сообщение Oct 8 2007, 02:20
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Всем известно (надеюсь), что адреса портов находятся в пространстве памяти данных SRAM - следовательно к ним можно обращаться либо напрямую, как к ячейке памяти, либо через указатель на ячейку памяти


--------------------
Go to the top of the page
 
+Quote Post
AlexMad
сообщение Oct 8 2007, 04:48
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 262
Регистрация: 18-02-05
Из: SPb
Пользователь №: 2 743



Цитата(ReAl @ Oct 7 2007, 23:58) *
Учитывая это, можно (но осторожно) обойтись одним указателем.

Код
#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>

typedef struct {
    uint8_t pin;
    uint8_t ddr;
    uint8_t port;
} port_t;

}

Вот тут уже ближе. Я с ходу именно так и сделал, но, толи кодевижен это не хочет понимать, толи это все-таки не получится. У меня при инициализации
Код
pin=PINB
, а также по остальным двум портам матерно ругается, что PINB должно быть константой, указатель на PINB тоже не принимает, говорит порты нельзя передать sad.gif После этого я свой вопрос и задал.

А вот насчет обращения, как к памяти это интересно, попробую.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 8 2007, 08:36
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(AlexMad @ Oct 8 2007, 06:48) *
Я с ходу именно так и сделал, но, толи кодевижен это не хочет понимать,
...
А вот насчет обращения, как к памяти это интересно, попробую.

Ну или выбрось каку, или пробуй вручную адрес писать - как адрес памяти, из скобок в register summary.
В моём примере как раз и сделано через "обращения к памяти"

Код
#define MEGA8_PINB_ADR 0x36
uint8_t test(void) {
    return OneWireReset( (volatile port_t*)MEGA8_PINB_ADDR, 0x02);
}


У avr-gcc в h-файлах адреса портов как адреса памяти сразу и прописаны, а уж он потом смотрит - если попадает в достижимое по in/out или sbi/cbi - то оптимизирует до коротких команд. И если в приведенном мной примере объявить OneWireReset как inline - то он её по месту вставит именно с командами sbi/cbi/sbis/sbic даже если передать (volatile port_t*)0x36


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
prottoss
сообщение Oct 8 2007, 09:12
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(AlexMad @ Oct 8 2007, 12:48) *
А вот насчет обращения, как к памяти это интересно, попробую.


В ИАРе прокатывает вот такой код

Код


char* pPORTA = &PORTA;
*pPORTA = 0x55;
То бишь, при присвоении указателю адреса порта происходит прибавление к адресу IO 0х20


--------------------
Go to the top of the page
 
+Quote Post
defunct
сообщение Oct 8 2007, 10:54
Сообщение #11


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



В общем случае я бы вероятно сделал так:
создал бы структуру "канал", в которую бы вошли 3 указателя на функции ввода вывода (чтение конкретного бита из конкретного PIN / запись конкретного бита в конкретный PORT / и запись конкретного бита в конкретный DDR).
И сделал бы таблицу во флеш - массив "каналов". Ну а дальше тривиально - в функцию передается указатель на "канал", и там все требуемые функции ввода/вывода. Расширять можно как угодно.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 8 2007, 13:20
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



2 ReAl, в сообщении #6 вызывает сомнение, должен ли быть только указатель на структуру port_t типом volatile или все-таки все члены структуры должны быть volatile?
ИМХО более правильно было бы
Код
typedef struct {
    volatile uint8_t pin;
    volatile uint8_t ddr;
    volatile uint8_t port;
} port_t;
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 8 2007, 13:38
Сообщение #13


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(rezident @ Oct 8 2007, 15:20) *
должен ли быть только указатель на структуру port_t типом volatile или все-таки все члены структуры должны быть volatile?
volatile там не указатель, а тот объект, на который он указывает.
Ведь не
port_t * volatile pport;
написано.
Т.е. вся структура (все её поля) - volatile. Так же, как все они const, если вся структура const.
Вместо этого приписывать кавлификатор персонально к полям имеет смысл только тогда, когда часть полей volatile, часть - нет.

Собственно, квалификатор нужно было вообще в typedef включить и везде использовать просто port_t *

Код
typedef volatile struct {
    uint8_t pin;
    uint8_t ddr;
    uint8_t port;
} port_t;


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
singlskv
сообщение Oct 8 2007, 16:19
Сообщение #14


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(ReAl @ Oct 8 2007, 17:38) *
Собственно, квалификатор нужно было вообще в typedef включить и везде использовать просто port_t *

Код
typedef volatile struct {
    uint8_t pin;
    uint8_t ddr;
    uint8_t port;
} port_t;

Объясните мне пожалуйста, зачем эту структуру содержащую адреса регистров портов нужно
объявлять volatile ? Недопонимаю...
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 8 2007, 16:42
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(singlskv @ Oct 8 2007, 22:19) *
Объясните мне пожалуйста, зачем эту структуру содержащую адреса регистров портов нужно
объявлять volatile ? Недопонимаю...

Потому что порт это аппаратура, "железка" т.с., а не переменная. И оптимизировать обращение к порту компилятор не имеет права. В хидерах описаний аппаратных регистров volatile, может и неявно, но обычно всегда присутствует.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 00:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.01819 секунд с 7
ELECTRONIX ©2004-2016