|
Научите красиво дергать ножками STM32 |
|
|
|
Jul 6 2016, 15:40
|
Местный
  
Группа: Участник
Сообщений: 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); } Но это тоже не дело. Подскажите, как вы решаете такие проблемы?
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 14)
|
Jul 6 2016, 15:57
|
Гуру
     
Группа: Свой
Сообщений: 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;
|
|
|
|
|
Jul 6 2016, 16:01
|

Гуру
     
Группа: Модераторы
Сообщений: 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).
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jul 6 2016, 18:12
|

Профессионал
    
Группа: Свой
Сообщений: 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 самое то.
|
|
|
|
|
Jul 6 2016, 18:44
|
Группа: Участник
Сообщений: 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.
|
|
|
|
|
Jul 6 2016, 19:12
|
Гуру
     
Группа: Свой
Сообщений: 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 использую более сложные макросы, определяющие назначение портов, их направление и т.д. Но этот вариант сложный, и он требует высшего уровня оптимизации, оправдан, если много проектов на одной плате.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jul 6 2016, 19:40
|

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

|
Цитата(Atlantis- @ Jul 6 2016, 18:40)  Даже если дефайном присвоить имя какому то выводу, непонятно на каком он порте - надо смотреть плату.
Коллега оборачивает такие вещи в функции Но это тоже не дело. Подскажите, как вы решаете такие проблемы? Два экрана. На одном всегда открыта плата. Схема платы специально сделана так чтобы понятен был и порт, и функция, и аттрибуты порта. На именах сигналов не зацикливаюсь, переназываю их в течении проекта много раз. Могу в течении дня им несколько раз названия менять. Вся программа пишется так чтобы выдерживать постоянный непрерывный рефакторинг. Не память должна подстраиваться под программу, а программа под память.
|
|
|
|
|
Jul 7 2016, 02:12
|
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);
|
|
|
|
|
Jul 7 2016, 07:35
|
Местный
  
Группа: Участник
Сообщений: 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) ?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|