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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Научите красиво дергать ножками STM32
Atlantis-
сообщение Jul 6 2016, 15:40
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Здравствуйте!
У меня на плате полно разных сигналов управления от STM32F429. В программе нужно ими всеми манипулировать. Использовать стандартные функции HAL неудобно, при написании программы придется часто отвлекаться на плату, чтобы посмотреть, где ножки реально расположены. Даже если дефайном присвоить имя какому то выводу, непонятно на каком он порте - надо смотреть плату.
Код
HAL_GPIO_WritePin(GPIOA,DAC_RESET,GPIO_PIN_SET);

Коллега оборачивает такие вещи в функции
Код
void gpioDACRESET(void)
{
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
}

Но это тоже не дело. Подскажите, как вы решаете такие проблемы?
Go to the top of the page
 
+Quote Post
HardEgor
сообщение Jul 6 2016, 15:57
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 223
Регистрация: 3-03-06
Из: Tomsk
Пользователь №: 14 925



Определите понятные названия и используйте тот же HAL_GPIO_WritePin:
Код
#define  DACRESET GPIO_PIN_5
#define  DACRESET_port GPIOA
#define  DACRESET_active GPIO_PIN_SET
#define  DACRESET_deactive GPIO_PIN_RESET

HAL_GPIO_WritePin(DACRESET_port, DACRESET, DACRESET_active);


Цитата(Atlantis- @ Jul 6 2016, 22:40) *
Коллега оборачивает такие вещи в функции

Коллега не умеет пользоваться определениями, можно записать так:
Код
#define gpioDACRESET HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)

и потом просто вызывать:
gpioDACRESET;
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 6 2016, 16:01
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Сильно доработанные напильником макросы имени Аскольда Волкова:
CODE
// pin define examples:
//      LED on GPIOA, bit 1, active level high,
//      key on GBIOB, bit 6, active level low
#define  LED    A, 1, H
#define  KEY    B, 6, L
#define  CS1    C, 1, L
#define  CS2    C, 2, L
//            usage example:
#include "pin_macros.h"
void send_spi(uint32_t volatile * cs_pin_bitband);

void test()
{
    DRIVER(LED, OUTPUT);
    TOGGLE(LED);        // toggle LED

    if ( ACTIVE(KEY) )  // if key pressed
    {
        ON(LED);        // turn LED on
    }

    if ( !ACTIVE(KEY) ) // if key not pressed
    {
        OFF(LED);       // turn LED off
    }

    // works on Cortex-M3 and higher
    send_spi(BITBAND_OUT(CS1));    
    send_spi(BITBAND_OUT(CS2));
}

void send_spi(uint32_t volatile * cs_pin_bitband)
{
     cs_pin_bitband = 0;
     .....
     cs_pin_bitband = 1;
}

разумеется, определения всех ног и #include < pin_macros.h > вынесены в заголовочный файл (hardware.h).
Прикрепленные файлы
Прикрепленный файл  STM32_pin_macros.zip ( 2.17 килобайт ) Кол-во скачиваний: 34
 


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 6 2016, 16:49
Сообщение #4


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Юзаю регистры сброса и установки, можно даже одновременно (приоритет у сброса). Никакими дополнительными макросами-шмакросами не пользуюсь, кроме тех, которыми манипулирую битами регистра. Тем более, функциями-...
Читайте Референс мануал.

Код
#define LED_ON()    (GPIOB->BSRR = 1 << 1 + 16)    //!< Включить светодиод (Low)
#define LED_OFF()    (GPIOB->BSRR = 1 << 1)        //!< Выключить светодиод (High)
Go to the top of the page
 
+Quote Post
x893
сообщение Jul 6 2016, 18:12
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Цитата(ViKo @ Jul 6 2016, 19:49) *
Юзаю регистры сброса и установки, можно даже одновременно (приоритет у сброса). Никакими дополнительными макросами-шмакросами не пользуюсь, кроме тех, которыми манипулирую битами регистра. Тем более, функциями-...
Читайте Референс мануал.

Код
#define LED_ON()    (GPIOB->BSRR = 1 << 1 + 16)    //!< Включить светодиод (Low)
#define LED_OFF()    (GPIOB->BSRR = 1 << 1)        //!< Выключить светодиод (High)


Особенно если надо код с HAL ужать или надо быстро - через BRR/BSRR самое то.
Go to the top of the page
 
+Quote Post
timurey
сообщение Jul 6 2016, 18:44
Сообщение #6





Группа: Участник
Сообщений: 11
Регистрация: 10-05-07
Пользователь №: 27 628



Определяю ножки и порты дефайнами:
Код
#define IPNUT_PIN_0 GPIO_PIN_0
#define IPNUT_PORT_0 GPIOA

#define IPNUT_PIN_1 GPIO_PIN_3
#define IPNUT_PORT_1 GPIOA

#define IPNUT_PIN_2 GPIO_PIN_0
#define IPNUT_PORT_2 GPIOB

#define IPNUT_PIN_3 GPIO_PIN_1
#define IPNUT_PORT_3 GPIOB

#define IPNUT_PIN_4 GPIO_PIN_0
#define IPNUT_PORT_4 GPIOC

, объединяю их в массивы:
Код
const uint16_t inputPin[]={IPNUT_PIN_0, IPNUT_PIN_1, IPNUT_PIN_2, IPNUT_PIN_3,
   IPNUT_PIN_4, IPNUT_PIN_5, IPNUT_PIN_6, IPNUT_PIN_7, IPNUT_PIN_8, IPNUT_PIN_9,
   IPNUT_PIN_10, IPNUT_PIN_11, IPNUT_PIN_12, IPNUT_PIN_13, IPNUT_PIN_14, IPNUT_PIN_15};

const GPIO_TypeDef* inputPort[]={ IPNUT_PORT_0, IPNUT_PORT_1, IPNUT_PORT_2, IPNUT_PORT_3,
   IPNUT_PORT_4, IPNUT_PORT_5, IPNUT_PORT_6, IPNUT_PORT_7, IPNUT_PORT_8, IPNUT_PORT_9,
   IPNUT_PORT_10, IPNUT_PORT_11, IPNUT_PORT_12, IPNUT_PORT_13, IPNUT_PORT_14, IPNUT_PORT_15};


инициализацию делаю с помощью HAL:
Код
GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.Pin = inputPin[gpioNum];
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = gpioContext[gpioNum].pull;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(inputPort[gpioNum], &GPIO_InitStruct);

читаю и устанавливаю через bit-banding:
Код
#define GPIO_PIN_ISTATE(PORT,PIN)  &(*(__I uint32_t *)(PERIPH_BB_BASE + ((((uint32_t)&((PORT)->IDR)) - PERIPH_BASE) << 5) + ((PIN) << 2)))
#define GPIO_PIN_ISET(PORT,PIN)  (*(__I uint32_t *)(PERIPH_BB_BASE + ((((uint32_t)&((PORT)->ODR)) - PERIPH_BASE) << 5) + ((PIN) << 2)))

#define IPNUT_PIN_STATE(a)   GPIO_PIN_ISTATE(inputPorts[a], inputPin[a])
#define IPNUT_PIN_SET(a)   GPIO_PIN_ISET(inputPorts[a], inputPin[a])

const uint32_t * inputState[]={
   GPIO_PIN_ISTATE(IPNUT_PORT_0, (IPNUT_PIN_0)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_1, (IPNUT_PIN_1)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_2, (IPNUT_PIN_2)>>1),
   GPIO_PIN_ISTATE(IPNUT_PORT_3, (IPNUT_PIN_3)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_4, (IPNUT_PIN_4)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_5, (IPNUT_PIN_5)>>1),
   GPIO_PIN_ISTATE(IPNUT_PORT_6, (IPNUT_PIN_6)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_7, (IPNUT_PIN_7)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_8, (IPNUT_PIN_8)>>1),
   GPIO_PIN_ISTATE(IPNUT_PORT_9, (IPNUT_PIN_9)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_10, (IPNUT_PIN_10)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_11, (IPNUT_PIN_11)>>1),
   GPIO_PIN_ISTATE(IPNUT_PORT_12, (IPNUT_PIN_12)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_13, (IPNUT_PIN_13)>>1), GPIO_PIN_ISTATE(IPNUT_PORT_14, (IPNUT_PIN_14)>>1),
   GPIO_PIN_ISTATE(IPNUT_PORT_15, (IPNUT_PIN_15)>>1)};


Код
if (*inputState[i])
               {
                ...
               }



--------------------
timurey.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jul 6 2016, 19:12
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Atlantis- @ Jul 6 2016, 18:40) *
Подскажите, как вы решаете такие проблемы?

У меня два подхода
1) В сложных контроллерах типа ARM использую осмысленные макросы.
Код
#define INIT_RS_DIR_PIN()        do                                        \
                        {    PORTE_PCR16 = PORT_PCR_MUX(1) |PORT_PCR_DSE_MASK;     \
                            GPIOE_PSOR = 0x01 << 16;                     \
                            GPIOE_PDDR |= 0x01 << 16;                     \
                        }    while (0)
#define SET_TRANSMIT()       GPIOE_PCOR = 0x01 << 16
#define SET_RECEIVE()      GPIOE_PSOR = 0x01 << 16

2) В простых контроллерах типа MSP430 использую более сложные макросы, определяющие назначение портов, их направление и т.д.
Но этот вариант сложный, и он требует высшего уровня оптимизации, оправдан, если много проектов на одной плате.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
turnon
сообщение Jul 6 2016, 19:33
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 340
Регистрация: 17-10-14
Пользователь №: 83 207



Вся плата описана в pinout.h и например, светодиод:

#define PIN_LED_GREEN GPIOA, GPIO_Pin_8

Есть макрос gpioSet(GPIO_TypeDef* GPIOx, PIN_TYPE pin, uint8_t state);

Вызываю соотв. gpioSet(PIN_LED_GREEN, true) или gpioSet(PIN_LED_GREEN, false).

В итоге манипулирую только объектами платы (PIN_LED_GREEN), м не портами и пинами (GPIOA, GPIO_Pin_8).

Также при новой версии железа достаточно поправить только pinout.h
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 6 2016, 19:40
Сообщение #9


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(Atlantis- @ Jul 6 2016, 18:40) *
Даже если дефайном присвоить имя какому то выводу, непонятно на каком он порте - надо смотреть плату.

Коллега оборачивает такие вещи в функции
Но это тоже не дело. Подскажите, как вы решаете такие проблемы?

Два экрана.
На одном всегда открыта плата.
Схема платы специально сделана так чтобы понятен был и порт, и функция, и аттрибуты порта.

На именах сигналов не зацикливаюсь, переназываю их в течении проекта много раз.
Могу в течении дня им несколько раз названия менять.
Вся программа пишется так чтобы выдерживать постоянный непрерывный рефакторинг.

Не память должна подстраиваться под программу, а программа под память.
Go to the top of the page
 
+Quote Post
x893
сообщение Jul 6 2016, 20:37
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



На схеме использую названия вида SIGNAL_PIN - например BUTTON_LEFT_PA1
В программе
#define BUTTON_LEFT PA1
или
#define BUTTON_LEFT_PA1 PA1
(как обычно PA0 = 0, ..., PB0 = 0x10, ..., PC0 = 0x20 и т.д)
если через макрос делается инициализация (а таких 99.9%)
то простейшие макросы переделывают PA0 в нужные маски и порты
Если runtime - то тоже не проблема переделать в порт/маску или bit-banding.
Хотя это конечно даже обсуждения не стоит.

Дергать ногами большого ума не надо. Вот что то красивое изобразить - это да.
Например нормальную (irq/dma) поддержку CAN со всеми mailbox'ами и fifo, или i2c/i2s.
С spi/uart проще конечно.

Тут без школы танцев не обойтись.
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Jul 7 2016, 02:12
Сообщение #11


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(x893 @ Jul 6 2016, 16:37) *
На схеме использую названия вида SIGNAL_PIN - например BUTTON_LEFT_PA1
В программе
#define BUTTON_LEFT PA1
или
#define BUTTON_LEFT_PA1 PA1
(как обычно PA0 = 0, ..., PB0 = 0x10, ..., PC0 = 0x20 и т.д)

Примерно также.

#define B1_PIN (M_PORT0 | 13)
#define B2_PIN (M_PORT1 | 30)
#define B3_PIN (M_PORT0 | 12)
#define B4_PIN (M_PORT1 | 31)

#define NEW_BUZZ_PIN (M_PORT2 | 1)
(т.е. В1 это PORT0.13 etc)

Далее используются следующие функции для установки периферии и пуллапов и пулдаунов.

ConfigPin2(NEW_VOL_PIN, 0x2, 0x00);
ConfigPin2(NEW_BUZZ_PIN, BRIGHTNESS_PIN_PWM_MODE, PULL_DOWN);
Включить пин на выход
SetPinOut(NEW_BUZZ_PIN);
И установить выходной уровень пина:
SetPin(SENS_ENA);
ClrPin(SENS_ENA);


Go to the top of the page
 
+Quote Post
esaulenka
сообщение Jul 7 2016, 06:34
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



https://github.com/antongus/stm32tpl - макросы Аскольда Волкова, которые творчески допилил АНТОХА.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Jul 7 2016, 07:35
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Цитата(turnon @ Jul 6 2016, 22:33) *
Вся плата описана в pinout.h и например, светодиод:

Также при новой версии железа достаточно поправить только pinout.h

Не знал, что можно делать такие дефайны
Код
#define PIN_LED_GREEN GPIOA, GPIO_Pin_8

это позволяет одному имени PIN_LED_GREEN присвоить сразу и порт GPIOA и ножку порта GPIO_Pin_8!
очень не хотелось писать отдельные дефайны типа такого:
Код
#define PIN_LED_GREEN GPIO_Pin_8
#define PORT_LED GPIOA

и потом рулить не очень удобно
Код
HAL_GPIO_WritePin(PORT_LED,PIN_LED_GREEN,GPIO_PIN_SET);

а тут получается намного проще можно сделать
Код
#define PIN_LED_GREEN GPIOA, GPIO_Pin_8

HAL_GPIO_WritePin(PIN_LED_GREEN,GPIO_PIN_SET);

а зачем Вам еще и макрос и как Вы его определяете gpioSet(GPIO_TypeDef* GPIOx, PIN_TYPE pin, uint8_t state) ?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 7 2016, 08:27
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(AlexandrY @ Jul 7 2016, 01:40) *
Не память должна подстраиваться под программу, а программа под память.

Т.е. - если что-то забыли, то в проге этот кусок должен исчезнуть biggrin.gif
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 7 2016, 10:30
Сообщение #15


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Всегда и на всех архитектурах использую решение на основе "макросов Аскольда" - благодаря этому моя наработанная библиотека цепляется к любому проекту и постоянно пополняется.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Jul 7 2016, 14:29
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Почему то не получается сделать макрос
Код
#define SET(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) HAL_GPIO_WritePin(GPIOx,GPIO_Pin,GPIO_PIN_SET)

компилятор ругается на знак *
хедэр где прописан GPIO_TypeDef подключен
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 7 2016, 15:11
Сообщение #17


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Atlantis- @ Jul 7 2016, 17:29) *
компилятор ругается на знак *

Правильно ругается.
В объявлении макросов никаких звёздочек быть не может, также как и типов данных, а в самом теле макроса пожалуйста...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Jul 7 2016, 20:07
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Совсем запутался...а как правильно передать созданный дефайн в макрос?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 7 2016, 21:50
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Atlantis- @ Jul 8 2016, 02:07) *
Совсем запутался...а как правильно передать созданный дефайн в макрос?

Жесть какая.... Откройте учебник по си! Макрос - это не функция: #define SET(GPIOx, GPIO_Pin) ...
Go to the top of the page
 
+Quote Post
turnon
сообщение Jul 8 2016, 06:16
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 340
Регистрация: 17-10-14
Пользователь №: 83 207



Цитата(Atlantis- @ Jul 7 2016, 10:35) *
Не знал, что можно делать такие дефайны

Можно конечно, ведь это просто кусок текста вставляемый препроцессором в заданное место перед компиляцией.

Цитата(Atlantis- @ Jul 7 2016, 10:35) *
Код
#define PIN_LED_GREEN GPIOA, GPIO_Pin_8

это позволяет одному имени PIN_LED_GREEN присвоить сразу и порт GPIOA и ножку порта GPIO_Pin_8!

Именно.

Цитата(Atlantis- @ Jul 7 2016, 10:35) *
HAL_GPIO_WritePin(PIN_LED_GREEN,GPIO_PIN_SET);[/code]
а зачем Вам еще и макрос и как Вы его определяете gpioSet(GPIO_TypeDef* GPIOx, PIN_TYPE pin, uint8_t state) ?


У меня единый gpio_utils.c для STM8/STM32, а в нем уже реализации (макросы) под каждый МК. Чтобы не вспоминать каждый раз у кого там
GPIO_SetBits, а у кого GPIO_WriteHigh. Ну и появлется возможность передать в качестве значения пина булевое выражение, а не делать if
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Jul 8 2016, 09:33
Сообщение #21


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Цитата(jcxz @ Jul 8 2016, 00:50) *
Жесть какая.... Откройте учебник по си! Макрос - это не функция: #define SET(GPIOx, GPIO_Pin) ...

Извините, я макросами никогда не пользовался, просто у turnon было написано gpioSet(GPIO_TypeDef* GPIOx, PIN_TYPE pin, uint8_t state), поэтому я тоже начал типы вставлять.
В общем, сделал так
Код
// Тестовые точки
#define TEST_X1                                  GPIOC,GPIO_PIN_14
#define TEST_X2                                  GPIOG,GPIO_PIN_12
#define TEST_X3                                  GPIOG,GPIO_PIN_13

#define SET(port_pin) HAL_GPIO_WritePin(port_pin,GPIO_PIN_SET)
#define RESET(port_pin) HAL_GPIO_WritePin(port_pin,GPIO_PIN_RESET)
#define TOGGLE(port_pin) HAL_GPIO_TogglePin(port_pin)

//вызов
TOGGLE(TEST_X1);
SET(TEST_X2);
RESET(TEST_X3);
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 8 2016, 11:20
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Вот теперь уже лучше. У меня в проектах примерно также, только пин я определяю короче:
#define PIN_SSP1_SCLK F, 4
#define PIN_SSP1_TX 1, 4
#define PIN_SSP1_RX 1, 3
#define PIN_LCD_LED 6, 9
Если нужно, потом к ним можно приклеить необходимые префиксы/суффиксы (типа GPIO): GPIO##port внутри макросов
Подобно:
#define SET_(port, pin) GPIO##port, GPIO_PIN_##pin
#define SET(port_pin) SET_(port_pin)
И не пользуюсь никакими HAL-ами, а прямо внутри этих макросов обращаюсь к регистрам GPIO.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 8 2016, 12:05
Сообщение #23


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(jcxz @ Jul 8 2016, 14:20) *
только пин я определяю короче:

И зря. Вы лишаете себя таких благ как:
Код
pin_init(PIN_RTC_SELECT);
...
pin_drive(PIN_RTC_SELECT, 1);
// do something
pin_drive(PIN_RTC_SELECT, 0);
Как видите, совсем не надо запариваться ни о инициализации, но о активном уровне.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 8 2016, 16:44
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(demiurg_spb @ Jul 8 2016, 18:05) *
И зря. Вы лишаете себя таких благ как:

Не понял чего именно я лишаюсь.... Инициализация пинов у меня делается примерно так:
Код
//Распределение SSI-портов
#define nSSI_hsdc     1    //номер SSI для ADE.HSDC
#define nSSI_storage  3    //номер SSI для FRAM, DFLASH0, DFLASH1 (система хранения)
#define PIN_FRAM_CS       F, 2  //CS для чипа FRAM
#define PIN_ADE_IRQ0      P, 0 //прерывание 0 от ADE
//Если скопом инитятся несколько пинов:
static TPinSel const t_iocon[] = {
  PINSEL(PIN_FRAM_CS, GPIO, SL, 12mA),
  PINSEL(PIN_ADE_IRQ0, GPIO, PU);
  PINSEL(concat(PIN_SSI, nSSI_storage, _MOSI), concat(SSI, nSSI_storage, _XDAT0), PD, SL, 12mA),
  PINSEL(concat(PIN_SSI, nSSI_storage, _MISO), concat(SSI, nSSI_storage, _XDAT1), PD, SL, 12mA),
  ...
};
PinSelN(t_iocon);
//Если по одному пину:
PinSel1(PIN_FRAM_CS, GPIO, SL, 12mA);
PinSel1(PIN_ADE_IRQ0, GPIO, PU),
PinSel1(concat(PIN_SSI, nSSI_storage, _MOSI), concat(SSI, nSSI_storage, _XDAT0), PD, SL, 12mA);
PinSel1(concat(PIN_SSI, nSSI_storage, _MISO), concat(SSI, nSSI_storage, _XDAT1), PD, SL, 12mA);
...

В списке аргументов макросов PINSEL и PinSel1 - опции доступные для данного пина (подтяжка: PU или PD; фильтр: SL; макс.ток: 2ma, 4ma, 8ma, 12ma, 18ma... и т.п.).
Первый аргумент в списке - имя пина (заданное define), второй - функция (GPIO или одна из спец.функций доступных на этом пине), далее - опциональный список опций пина произвольной длины.
PinSel1 и PinSelN конфигурят как опции пина(-ов) типа pullup, pulldown, opendrain и т.п., так и программируют мультиплексор пинов на нужную функцию.
Здесь я привёл примеры для Tiva, но в других проектах на других МК у меня организовано подобным образом, только список опций пинов другой.

И есть кучка макросов типа Pset(PIN_...), Pclr(PIN_...), Pval(PIN_...), Pin(PIN_...), Pout(PIN_...) и т.п.
Такие имена макросов у меня тоже одинаковые для разных проектов на разных МК, только реализация внутри разная, зависящая от периферии.

И совсем не запариваюсь о инициализации и т.п. sm.gif
При добавлении нового пина просто добавляю ещё одну запись с описанием необходимых его опций. И очень легко переназначать пины, менять назначение портов (UART, SPI, ...).
Go to the top of the page
 
+Quote Post
arhiv6
сообщение Jul 8 2016, 16:54
Сообщение #25


Знающий
****

Группа: Свой
Сообщений: 633
Регистрация: 21-05-10
Из: Томск
Пользователь №: 57 423



Вот готовая реализация на макросах. Там описание + примеры для F0, F1, F4 и L1.


--------------------
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 8 2016, 20:00
Сообщение #26


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(jcxz @ Jul 8 2016, 19:44) *
И совсем не запариваюсь о инициализации и т.п. sm.gif
Не увидел у вас, где определяется активный уровень H или L и то, что вы привели, не выглядит для меня разумным.

Есть драйвер чего бы то ни было и именно он в своей функции driver_init() вызывает pin_init(PIN_NAME) для своих линий ввода-вывода без каких либо дополнительных аргументов и дёргает ногами на своё усмотрение. Смысл абстракции именно в этом!

А у вас куча совершенно лишних буков там, где их быть не должно.
ГОРАЗДО разумнее в одной строке задефайнить всё сразу: и номер пина, и порт, и активный уровень, и все режимы работы порта, и ремапы, а не размазывать сопли по коду.

Пример для STM32F37x
Код
#define PIN_BTN_USER        A,0,H,REMAP_NONE,INPUT_PULL_DOWN,SPEED_NONE
#define PIN_UART2_RTS        A,1,H,REMAP_NONE,OUTPUT_PUSH_PULL,SPEED_2MHZ  // # software_RTS
#define PIN_UART2_TX        A,2,L,REMAP_AF07,OUTPUT_PUSH_PULL,SPEED_2MHZ    // #
#define PIN_UART2_RX        A,3,L,REMAP_AF07,INPUT_PULL_UP,SPEED_NONE       // #

#define PIN_LAMP_BLUE        E,12,H,REMAP_NONE,OUTPUT_PUSH_PULL,SPEED_2MHZ
#define PIN_LAMP_RED        E,13,H,REMAP_NONE,OUTPUT_PUSH_PULL,SPEED_2MHZ


pin_init(PIN_LAMP_RED);

for(;;)
    delay_ms(500),
    pin_toggle(PIN_LAMP_RED);

Вы лишаетесь прозрачности и удобства описания таргета: одна нога - одна строка и НИКАКИХ завязок более.
Даже если вы, например, поставили инвертор в цепи где его в прошлой плате не было, то НИЧЕГО в коде менять не надо.
Заметьте, именно так выходит полностью абстрагироваться от таргета и в смысле схемотехники платы, и в смысле типа MCU: хотите AVR, хотите STM32, хотите чёрта в ступе. НИ один высокоуровневый драйвер патчить не придётся вовсе. Создал новое описание таргета lowlevel333.h и в путь, не меняя в проекте ни одной строчки.
Предвосхищая ваши попытки сказать, что у меня, мол, тоже только один файл описания... Тоже, да не совсем - вы решили лишь половину задачи и ту не самым красивым способом. У каждого своё чувство прекрасного и я не хочу вас обидеть, но мне нередко смешно и грустно читать ваши безапелляционные посты, в которых, надо признать, часто много правильных мыслей...

Цитата(arhiv6 @ Jul 8 2016, 19:54) *
Не интересно смотреть. Своё уже давно написано. Но на первый взгляд не понравилась нотация макросов. Вы не учитываете некоторые весьма оправданные рекомендации, как то: если поведение макроса неотличимо от поведения функции, этот макрос должен быть назван с использованием строчных, а не ЗАГЛАВНЫХ букв, от которых рябит в глазах. Плюс выбраны не самые удачные имена HIGH, LOW - H,L достаточно на 100%. PIN_CONFIGURATION - очуметь как много букв!!! pin_init, pin_setup, pin_cfg - это синонимы не скрывающие смысла происходящего. В этом ключе, да и других направлениях есть куда расти... Чтобы стать профи никогда не стоит пренебрегать чтением профессиональной литературы - там зачастую есть чему поучиться. А про то, как правильно выбирать названия переменным и функциям, вообще в букварях пишут)))

2ALL: перечитайте название этого топика ещё раз, прежде чем сюда написать.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 8 2016, 21:42
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(demiurg_spb @ Jul 9 2016, 02:00) *
ГОРАЗДО разумнее в одной строке задефайнить всё сразу: и номер пина, и порт, и активный уровень, и все режимы работы порта, и ремапы, а не размазывать сопли по коду.

У меня как раз все режимы пина одной строкой и задаются. Но его номер и номер порта на котором он находится (или просто номер ноги корпуса) задаётся отдельно. Мне так удобнее, так как у нас обычно разрабатывается не одно устройство, а линейка устройств с подобным функционалом и, соответственно, с такими-же почти ногами, но с разной схемой, так что в одном из устройств линейки этот вывод находится на одной ноге, а в другом - на другой. И файлы работы с пинами - общие, свой только для каждого конкретного устройства, файл описания распределения пинов по реальным ногам чипа.
Так что строки режимов для PIN_... - общие для всей линейки в одном файле, а вот файлы с присвоением PIN_.... номеров ног - разные.

А где у меня лишние буквы? Вроде всё по минимуму...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 8 2016, 22:00
Сообщение #28


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(jcxz @ Jul 9 2016, 00:42) *

ИМХО одна строка всегда яснее чем две. Но идея с разделением ясна и она действительно м.б. оправдана в случае действительно огромного кол-ва вариантов железа ИМЕННО c прыгающими ногами. Мне сложно такое вообразить (сегодня реле PORTA,2 завтра PORTB,3, а в пятницу первый отряд лагеря меняется бельём со вторым). У меня за более чем 15-ти летнюю поддержку разных линеек приборов КИП и ПЛК наблюдается максимум 6-ой вариант железа у одного из них. У вас что, это чаще происходит? Вы в какой сфере варитесь? И что же вы про задание активного уровня не говорите ничего - у вас он тоже в конфиг режимов задвинут и как же ж он работает?))) ИМХО у вас этого функционала просто нет.
Ладно... Душевно обсосали темку. Спокойной ночи!


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 10 2016, 07:01
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(demiurg_spb @ Jul 9 2016, 04:00) *
ИМХО одна строка всегда яснее чем две. Но идея с разделением ясна и она действительно м.б. оправдана в случае действительно огромного кол-ва вариантов железа ИМЕННО c прыгающими ногами. Мне сложно такое вообразить (сегодня реле PORTA,2 завтра PORTB,3, а в пятницу первый отряд лагеря меняется бельём со вторым). У меня за более чем 15-ти летнюю поддержку разных линеек приборов КИП и ПЛК наблюдается максимум 6-ой вариант железа у одного из них. У вас что, это чаще происходит? Вы в какой сфере варитесь? И что же вы про задание активного уровня не говорите ничего - у вас он тоже в конфиг режимов задвинут и как же ж он работает?))) ИМХО у вас этого функционала просто нет.

Блин - написал такое развёрнутое сообщение с описанием, и грёбаный сайт глюканул и всё потерялось sad.gif((((((((((((((((
Заново писать неохота. Но вкратце: новые вариации железа у нас появляются не только во время поддержки устройства, а уже при старте разработки: сразу запускается линейка устройств с примерно одинаковым ПО, но разных схемотехнически.
Например: счётчик э/энергии 1-фазный прямого включения, счётчик э/энергии 3-фазный прямого включения, счётчик э/энергии 3-фазный трансформаторный, контроллер сбора данных, ....
У каждого из этих устройств линейки отдельное ПО, но большая часть файлов этих отдельных проектов - одинакова (просто копируется из проекта в проект). И у каждого есть файл описания номеров пинов, а вот уже работа с этими пинами может находиться в общих файлах драйверов, которые одинаковые для всех этих проектов.
Эти устройства в линейке могут быть построены даже на разных МК (в прошлой линейке использовались МК: LPC1758, LPC1778, а у них некоторая периферия совершенно разная (например - мультиплексор пинов)). Плюс ещё: у каждого из устройств линейки может быть несколько исполнений (в том числе и новых исполнений, появляющихся уже во время жизни устройства, если заказчик вдруг захотел другой набор аппаратных опций). Опции например такие: RS-485 (или несколько), ZigBee, GSM, Ethernet, PLC, RF, реле отключения фаз, осциллографирование, резервное питание и др. Разные исполнения - разная комбинация этих аппаратных опций.
И количество файлов в проектах ПО очень большое. Так что и стараемся при добавлении нового функционала или при смене ног, минимально трогать готовые файлы например с драйверами устройств.
Работаю я в сфере разработки устройств для э/энергетики: счётчики э/энергии, контроллеры присоединений, ...
Сейчас новая линейка в разработке на базе МК Tiva (от TI), но тоже - разные устройства в линейке построены на разных МК Tiva, плюс имеют - разный набор периферии внутри: один или два чипа флешь, (одного или другого типа), разные чипы FRAM, наличие или отсутствие других чипов (в зависимости от необходимого функционала). Места на платах очень мало, да надо ещё подешевле. Так что есть более дешёвые устройства в линейке, есть дороже. На более дешёвых может и плата меньше слоёв иметь. К тому же - есть ограничения по размеру платы, ограничения накладываемые необходимостью гальванической развязки и т.п. Это приводит к тому, что распределение пинов получается разным (по портам и номерам), но драйвера периферии должны быть по возможности одинаковыми.
Вот поэтому у нас для каждого устройства в линейке свой файл распределения пинов по номерам портов и разрядов, а инит их - общие файлы.

Не понял вопрос про задание активного уровня. При инициализации пина ему задаётся некое начальное значение (если это GPIO-пин), а потом меняется драйвером по его алгоритму. Есть у меня макросы установки/сброса/... текущего состояния GPIO-пина. Описывал их выше.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 08:31
Сообщение #30


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(demiurg_spb @ Jul 8 2016, 23:00) *
Не увидел у вас, где определяется активный уровень H или L и то, что вы привели, не выглядит для меня разумным.

ГОРАЗДО разумнее в одной строке задефайнить всё сразу: и номер пина, и порт, и активный уровень, и все режимы работы порта, и ремапы, а не размазывать сопли по коду.

Пример для STM32F37x
Код
#define PIN_BTN_USER        A,0,H,REMAP_NONE,INPUT_PULL_DOWN,SPEED_NONE
#define PIN_UART2_RTS        A,1,H,REMAP_NONE,OUTPUT_PUSH_PULL,SPEED_2MHZ  // # software_RTS


И этого слишком мало!

Если описывать то всё, включая все альтернативные функции.
Вот так:
Код
//  gpio          port              num  irqc      lock  mux   DSE     SRE        ODE     PFE      PUPD      dir     init
  { PTA_BASE_PTR, PORTA_BASE_PTR,   0,   IRQ_DIS,   0,   ALT7, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP,   0 }, // *JTCLK/SWC       50 # PTA0 # Default=(JTAG_TCLK/SWD_CLK/EZP_CLK)  ALT0=(TSI0_CH1)  ALT1=(PTA0)  ALT2=(UART0_CTS_b/UART0_COL_b)  ALT3=(FTM0_CH5)  ALT4=()  ALT5=(LPUART0_CTS_b)  ALT6=()  ALT7=(JTAG_TCLK/SWD_CLK)  EZPort=(EZP_CLK)
  { PTA_BASE_PTR, PORTA_BASE_PTR,   1,   IRQ_DIS,   0,   GPIO, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_OUT,   1 }, // *JTDI (LED)      51 # PTA1 # Default=(JTAG_TDI/EZP_DI)  ALT0=(TSI0_CH2)  ALT1=(PTA1)  ALT2=(UART0_RX)  ALT3=(FTM0_CH6)  ALT4=(I2C3_SDA)  ALT5=(LPUART0_RX)  ALT6=()  ALT7=(JTAG_TDI)  EZPort=(EZP_DI)
  { PTA_BASE_PTR, PORTA_BASE_PTR,   2,   IRQ_DIS,   0,   ALT7, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP,   0 }, // *JTDO/SWO        52 # PTA2 # Default=(JTAG_TDO/TRACE_SWO/EZP_DO)  ALT0=(TSI0_CH3)  ALT1=(PTA2)  ALT2=(UART0_TX)  ALT3=(FTM0_CH7)  ALT4=(I2C3_SCL)  ALT5=(LPUART0_TX)  ALT6=()  ALT7=(JTAG_TDO/TRACE_SWO)  EZPort=(EZP_DO)
  { PTA_BASE_PTR, PORTA_BASE_PTR,   3,   IRQ_DIS,   0,   ALT7, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP,   0 }, // *JTMS/SWD        53 # PTA3 # Default=(JTAG_TMS/SWD_DIO)  ALT0=(TSI0_CH4)  ALT1=(PTA3)  ALT2=(UART0_RTS_b)  ALT3=(FTM0_CH0)  ALT4=()  ALT5=(LPUART0_RTS_b)  ALT6=()  ALT7=(JTAG_TMS/SWD_DIO)  EZPort=()
  { PTA_BASE_PTR, PORTA_BASE_PTR,   4,   IRQ_DIS,   0,   GPIO, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP,   0 }, // -                54 # PTA4/LLWU_P3 # Default=(NMI_b/EZP_CS_b)  ALT0=(TSI0_CH5)  ALT1=(PTA4/LLWU_P3)  ALT2=()  ALT3=(FTM0_CH1)  ALT4=()  ALT5=()  ALT6=()  ALT7=(NMI_b)  EZPort=(EZP_CS_b)
  { PTA_BASE_PTR, PORTA_BASE_PTR,   5,   IRQ_DIS,   0,   GPIO, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP,   0 }, // -                55 # PTA5 # Default=(DISABLED)  ALT0=()  ALT1=(PTA5)  ALT2=(USB0_CLKIN)  ALT3=(FTM0_CH2)  ALT4=(RMII0_RXER/MII0_RXER)  ALT5=(CMP2_OUT)  ALT6=(I2S0_TX_BCLK)  ALT7=(JTAG_TRST_b)  EZPort=()
  { PTA_BASE_PTR, PORTA_BASE_PTR,   6,   IRQ_DIS,   0,   GPIO, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP,   0 }, // -                58 # PTA6 # Default=(DISABLED)  ALT0=()  ALT1=(PTA6)  ALT2=()  ALT3=(FTM0_CH3)  ALT4=()  ALT5=(CLKOUT)  ALT6=()  ALT7=(TRACE_CLKOUT)  EZPort=()
  { PTA_BASE_PTR, PORTA_BASE_PTR,   7,   IRQ_DIS,   0,   ALT0, DSE_HI, FAST_SLEW, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP,   0 }, // INP8             59 # PTA7 # Default=(ADC0_SE10)  ALT0=(ADC0_SE10)  ALT1=(PTA7)  ALT2=()  ALT3=(FTM0_CH4)  ALT4=()  ALT5=(RMII0_MDIO/MII0_MDIO)  ALT6=()  ALT7=(TRACE_D3)  EZPort=()


Тут немного искажено , поскольку включился автоматический перенос строк, но принцип понять можно.
И эта таблица генерится прямо из PDF-а мануала на чип.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 10 2016, 09:05
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(AlexandrY @ Jul 10 2016, 14:31) *
И этого слишком мало!
Если описывать то всё, включая все альтернативные функции.

Слишком громоздко. Я при описании предполагаю, что у пина есть некоторые дефолтные опции, и в строке описания пишу только отличия от дефолта.
Например:
PINSEL(PIN_DFLASH2_CS, GPIO, 12mA);
От дефолтного отличается только задание повышенного вых. тока. Если например нужен OpenDrain, добавлю в список OD и т.п. Через запятую.
Обязательные у меня только два первых аргумента: номер/порт пина и функция мультиплексора.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 09:50
Сообщение #32


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(jcxz @ Jul 10 2016, 12:05) *
Слишком громоздко. Я при описании предполагаю, что у пина есть некоторые дефолтные опции, и в строке описания пишу только отличия от дефолта.
Например:
... Если например нужен OpenDrain, добавлю в список OD и т.п. Через запятую.


Да, но моя то таблица генерится почти автоматически, а вам все 140 с лишним строк надо писать ручками каждый раз тщательно проверяя, а дефолтные ли параметры там. biggrin.gif
Таблица хоть и большая, но гомогенная. Отсюда меньшее количество ошибок.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 10 2016, 12:23
Сообщение #33


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(AlexandrY @ Jul 10 2016, 11:31) *
И этого слишком мало!
Если описывать то всё, включая все альтернативные функции.
Тут немного искажено , поскольку включился автоматический перенос строк, но принцип понять можно.
Вы сюда локи и прерывания ещё вынесли - вполне себе... Главное, что читаемо и понятно!

Цитата
И эта таблица генерится прямо из PDF-а мануала на чип.
Вот, а это уже интересно!
Поделитесь механизмом!
Сперва подумал, какой ацкий труд проделан по написанию каментов, а потом увидел, что и это автоматизировано - респект!

Цитата(jcxz @ Jul 10 2016, 10:01) *
Не понял вопрос про задание активного уровня. При инициализации пина ему задаётся некое начальное значение (если это GPIO-пин), а потом меняется драйвером по его алгоритму. Есть у меня макросы установки/сброса/... текущего состояния GPIO-пина. Описывал их выше.
Смысл H и L в макросах не только в задании начального состояния, но и в том чтобы не думать о нём вовсе.
pin_set(PIN_NAME); pin_clr(PIN_NAME); задают состояние ноги напрямую без учёта H и L,
а pin_drive(PIN_NAME, VALUE) задаёт активное/пассивное состояние c учётом активного уровня.
Поэтому в коде программы или коде драйвера я использую только pin_drive(PIN_NAME, VALUE), чтобы не думать о активном уровне. В ваших макросах явно напрашивается третий аргумент: А,12,H или B,5,L


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st August 2025 - 10:42
Рейтинг@Mail.ru


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