|
Как вы работаете с регистрами GPIOx_AFR? |
|
|
|
Oct 20 2015, 08:11
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Как вы настраиваете альтернативные функции у GPIO с помощью регистров GPIOx_AFR (например при настройке USART1 на PA9, PA10 на STM32F407VG) ? В стандартном файле описания периферии (stm32f4xx.h) - нет информации и масок для работы с этим регистром. Просто высчитываете сами битовую маску и записываете в этот регистр готовое число?
|
|
|
|
|
Oct 20 2015, 08:51
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Как узнать число, которое нужно записать в AFRH9 и AFRH10, что бы включить альтернативную функцию USART1 на PA9, PA10 на STM32F407? (это число состоит из 4-ёх бит согласно стр. 287 RM0090)
Сообщение отредактировал allsettingsdone - Oct 20 2015, 08:52
|
|
|
|
|
Oct 20 2015, 08:56
|

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

|
Типа того. Раньше для альтернативных функций конкретно перечисления создавал (typedef enum { AF_SYSTEM, AF_TIM1, AF_TIM2 = 1, AF_TIM3...), потом перестал. CODE /*! GPIO Mode Type */ typedef enum { MD_IN, //!< Input * MD_GO, //!< General purpose output MD_AF, //!< Alternate function MD_AN //!< Analog } GPIO_MODE_t;
/*! GPIO Output Type */ typedef enum { OT_PP, //!< Output push-pull* OT_OD //!< Output open-drain } GPIO_OTYPE_t;
/*! GPIO Output Speed Type */ typedef enum { SP_LO, //!< 2 MHz Low speed * SP_ME, //!< 10 MHz Medium speed // 2 MHz SP_HI = 3 //!< 50 MHz High speed } GPIO_OSPEED_t;
/*! GPIO Pull-Up_Pull-Down Type */ typedef enum { PL_NP, //!< No pull-up, pull-down * PL_PU, //!< Pull-up PL_PD //!< Pull-down // Reserved } GPIO_PUPD_t;
/*! GPIO Alternate Functions The specific alternate function assignments for each pin are detailed in the device datasheet */ typedef enum { AF_00, //!< AF0 * AF_01, //!< AF1 AF_02, //!< AF2 AF_03, //!< AF3 AF_04, //!< AF4 AF_05, //!< AF5 AF_06, //!< AF6 AF_07, //!< AF7 AF_08, //!< AF8 AF_09, //!< AF9 AF_10, //!< AF10 AF_11, //!< AF11 AF_12, //!< AF12 AF_13, //!< AF13 AF_14, //!< AF14 AF_15 //!< AF15 } GPIO_AFLH_t;
#define GPIO_CONF(PORT, \ MD00, OT00, SP00, PL00, AF00, \ MD01, OT01, SP01, PL01, AF01, \ MD02, OT02, SP02, PL02, AF02, \ MD03, OT03, SP03, PL03, AF03, \ MD04, OT04, SP04, PL04, AF04, \ MD05, OT05, SP05, PL05, AF05, \ MD06, OT06, SP06, PL06, AF06, \ MD07, OT07, SP07, PL07, AF07, \ MD08, OT08, SP08, PL08, AF08, \ MD09, OT09, SP09, PL09, AF09, \ MD10, OT10, SP10, PL10, AF10, \ MD11, OT11, SP11, PL11, AF11, \ MD12, OT12, SP12, PL12, AF12, \ MD13, OT13, SP13, PL13, AF13, \ MD14, OT14, SP14, PL14, AF14, \ MD15, OT15, SP15, PL15, AF15); \ GPIO##PORT->MODER = ( \ MD00 << 0 | MD01 << 2 | MD02 << 4 | MD03 << 6 | \ MD04 << 8 | MD05 << 10 | MD06 << 12 | MD07 << 14 | \ MD08 << 16 | MD09 << 18 | MD10 << 20 | MD11 << 22 | \ MD12 << 24 | MD13 << 26 | MD14 << 28 | (uint32_t)MD15 << 30); \ GPIO##PORT->OTYPER = ( \ OT00 << 0 | OT01 << 1 | OT02 << 2 | OT03 << 3 | \ OT04 << 4 | OT05 << 5 | OT06 << 6 | OT07 << 7 | \ OT08 << 8 | OT09 << 9 | OT10 << 10 | OT11 << 11 | \ OT12 << 12 | OT13 << 13 | OT14 << 14 | (uint32_t)OT15 << 15); \ GPIO##PORT->OSPEEDR = ( \ SP00 << 0 | SP01 << 2 | SP02 << 4 | SP03 << 6 | \ SP04 << 8 | SP05 << 10 | SP06 << 12 | SP07 << 14 | \ SP08 << 16 | SP09 << 18 | SP10 << 20 | SP11 << 22 | \ SP12 << 24 | SP13 << 26 | SP14 << 28 | (uint32_t)SP15 << 30); \ GPIO##PORT->PUPDR = ( \ PL00 << 0 | PL01 << 2 | PL02 << 4 | PL03 << 6 | \ PL04 << 8 | PL05 << 10 | PL06 << 12 | PL07 << 14 | \ PL08 << 16 | PL09 << 18 | PL10 << 20 | PL11 << 22 | \ PL12 << 24 | PL13 << 26 | PL14 << 28 | (uint32_t)PL15 << 30); \ GPIO##PORT->AFR[0] = ( \ AF00 << 0 | AF01 << 4 | AF02 << 8 | AF03 << 12 | \ AF04 << 16 | AF05 << 20 | AF06 << 24 | (uint32_t)AF07 << 28); \ GPIO##PORT->AFR[1] = ( \ AF08 << 0 | AF09 << 4 | AF10 << 8 | AF11 << 12 | \ AF12 << 16 | AF13 << 20 | AF14 << 24 | (uint32_t)AF15 << 28);
|
|
|
|
|
Oct 20 2015, 09:24
|

Местный
  
Группа: Свой
Сообщений: 270
Регистрация: 8-08-15
Из: Москва
Пользователь №: 87 901

|
Цитата(allsettingsdone @ Oct 20 2015, 11:51)  Как узнать число, которое нужно записать в AFRH9 и AFRH10, что бы включить альтернативную функцию USART1 на PA9, PA10 на STM32F407? (это число состоит из 4-ёх бит согласно стр. 287 RM0090) В вашем случае так: GPIOA->AFR[1]|=0x770; Если представить вышеуказанное число в двоичном виде, то у нас получится следующее: 0111 0111 0000. Как вы и писали на каждую ножку настройка функций идет по 4 битам. Здесь последние 4 бита идут нули, а следующие 8 имеют значение 0х77, что соответствует 7 альтернативной функции (USART1) для вашего контроллера на ножках 9 и 10. Сами назначения функций (зависимость функции от числа) можно посмотреть в таблице альтернативных функций в даташите на контроллер http://www.st.com/web/en/resource/technica.../DM00037051.pdfСтр. 61
Сообщение отредактировал ЯadiatoR - Oct 20 2015, 09:29
|
|
|
|
|
Oct 20 2015, 10:17
|

Частый гость
 
Группа: Участник
Сообщений: 101
Регистрация: 2-05-15
Из: Россия, Омск
Пользователь №: 86 474

|
ИМХО, в Datasheet на STM32F407, страница 61, описаны альтернативные функции по каждому пину в виде таблицы. Соответственно, AF0 == 0000 (0), AF15 == 1111 (F), etc. А уже в Reference manual'е описаны сами регистры. Так что, пример выбора альтертанивной функции #10 для пина #7 будет выглядеть так: Код GPIOn->AFRL &= ~(0xF0000000); // Сброс битов альтертанивных функций для пина GPIOn->AFRL |= (0xA0000000); // Выставляем биты регистра Либо Код GPIOn->AFRL &= ~(0x0F << 28); // То же, но с предварительными сдвигами. GPIOn->AFRL |= (0x0A << 28); // То же, но со сдвигом.
Сообщение отредактировал AlanDrakes - Oct 20 2015, 10:18
|
|
|
|
|
Oct 20 2015, 11:24
|
Знающий
   
Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250

|
В opencm3 нужные макросы есть. И даже функции вроде Код gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, AFIO_MAPR_SPI1_REMAP); (это я SPI на более удобные ноги переносил) или так: Код gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP2); (а это - переносил таймер на 5-tolerant ноги). Ну и, естественно, везде в main() до конфигурирования ног делаю Код AFIO_MAPR = AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF; (по какой-то глупой причине это приходится явно делать)
|
|
|
|
|
Oct 21 2015, 11:44
|

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

|
Цитата(allsettingsdone @ Oct 20 2015, 11:11)  Как вы настраиваете альтернативные функции у GPIO с помощью регистров GPIOx_AFR (например при настройке USART1 на PA9, PA10 на STM32F407VG) ? Странно, что никто не сказал, что единственный правильный путь - это STM32Tpl. Код Pin<'A',9>::Alternate (ALT_FUNC_USART1); Pin<'A',10>::Alternate (ALT_FUNC_USART1);
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Oct 22 2015, 06:22
|

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

|
Цитата(Golikov A. @ Oct 21 2015, 16:12)  а как этот правильный путь поможет задать альтернативные функции LPC? или право делать процы с альтернативными функциями пинов на арм ядре только у СТМ  ? Если мне придётся снова работать с LPC'хами, буду делать библиотеку по образу и подобию. Когда-то у меня был набор макросов (в принципе, то же самое - задавался порт, пин, режим пина), но эти хитрые шаблоны удобнее. Варианты ЯadiatoR и AlanDrakes, которые прочитали даташит, явно неудобные. Пусть компилятор нужные смещения считает, он железный.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Oct 26 2015, 08:52
|
Профессионал
    
Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882

|
Инициалиация в одном месте хорошо. Но иногда не прокатывает: при работе с встраиваемыми модулями (GSM и прочие) сразу инициализировать ноги нельзя, вначале надо подать на модуль питание. И, соотвественно, иницалиировать в третье состяоние при снятии питания. Таким образом, инциализация ног происходит не разово, а постоянно в работе. Для LPC и STM создан "drv_gpio" Все регистры для установки ног вычиляются внутри функции IO_SetupPin(..) С одной стороны, лишние накладные расходы, с другой - код намного читабельнее и понятнее. Единстенное, что никак не стандартизируешь - вариант альтернативной конфиграции ноги. Тут уж придется лезть в даташит. CODE #ifndef __DRV_IOPORTS_H #define __DRV_IOPORTS_H
enum __pindirection { PIN_IN, PIN_OUT, PIN_ALTOUT };
enum __pullupmode { ppullINACTIVE = 0, ppullDOWN, ppullUP, ppullREPEATER };
enum __pinslew { pslewENABLED = 0, pslewDISABLED = 1 };
enum __pinmode { pinNORMAL = 0, pinOPENDRAIN = 1, pinANALOG = 2, };
enum __pinfilter { pglfENABLED = 0, pglfDISABLED = 1 };
enum __pinntest_res { PIN_OK, PIN_SHORTLOW, PIN_SHORTHIGH };
#define pmANALOG 0 #define pmDIGITAL 1
#define PORTA A #define PORTB B #define PORTC C #define PORTD D #define PORTE E #define PORTF F
#define PORTABASE ((void*)&GPIOA_CRL) #define PORTBBASE ((void*)&GPIOB_CRL) #define PORTCBASE ((void*)&GPIOC_CRL) #define PORTDBASE ((void*)&GPIOD_CRL) #define PORTEBASE ((void*)&GPIOE_CRL)
#define _PORTBASE(port) ((void*)&(GPIO ## port ## _CRL))
#define _PORTSET(port) GPIO ## port ## _BSRR #define _PORTCLR(port) GPIO ## port ## _BRR #define _PORTPIN(port) GPIO ## port ## _IDR
#define PORTSET(port) _PORTSET(port) #define PORTCLR(port) _PORTCLR(port) #define PORTPIN(port) _PORTPIN(port) #define PINSET(port, pin) _PORTSET(port) = BIT(pin) #define PINCLR(port, pin) _PORTCLR(port) = BIT(pin) #define PINREAD(port, pin) (!!(_PORTPIN(port) & BIT(pin)))
#define PINSETUP(port, pin, dir, pu, pm, s, f) \ IO_SetupPin(_PORTBASE(port), pin, dir, pu, pm, s, f)
#define PINMODE(port, pin, mode)
#define PINDIR(dir, port, pin) IO_PinDir(dir, port, (1UL << pin))
#ifdef __cplusplus extern "C" { #endif void IO_Init(void);
void IO_SetupPin(void * portbase, int pin, enum __pindirection dir, enum __pullupmode pumode, enum __pinmode pinmode, enum __pinslew slewrate, enum __pinfilter filter);
enum __pinntest_res IO_PinTest(int port, int pin);
void IO_PinDir(enum __pindirection dir, int port, unsigned long pinmask);
#ifdef __cplusplus } #endif
#endif //__DRV_IOPORTS_H
|
|
|
|
|
Oct 27 2015, 08:03
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(esaulenka @ Oct 22 2015, 09:22)  Если мне придётся снова работать с LPC'хами, буду делать библиотеку по образу и подобию. Когда-то у меня был набор макросов (в принципе, то же самое - задавался порт, пин, режим пина), но эти хитрые шаблоны удобнее. Года 3 назад делал библиотеку шаблонов для LPC 2119/2368/2468. Кому-то такие объявления могут показаться избыточными, но мне самому пользоваться очень нравилось. Код CPU::WATCHDOGTIMER<> wdt( CPU::PLL::PeriodToTicks(10), CPU::WATCHDOGTIMER<>::DEBUG );
CPU::TIMER<0> ustimer( CPU::PLL::FreqToTicks(1000000) ); CPU::CALLBACKTIMER<1, MEASURETIMERCB, IRQP_MEASURETIMER> measuretimer( CPU::PLL::FreqToTicks(FADC) );
CPU::GPIO0::PINGROUP<0,2> _uartusb_rx_tx(1); USBQUEYECLASS usbq(115200);
CPU::GPIO0::PINGROUP<8,2> _uartrs485_rx_tx(1); CPU::GPIO0::PIN<10> uartrs485_txen(0, CPU::GPIO0::OUTPUT); RS485QUEYECLASS rs485q(19200, 8, RS485QUEYECLASS::EVEN, 1);
CPU::GPIO1::PIN<23> disp_d7_busy(0, CPU::GPIO1::OUTPUT); CPU::GPIO0::PIN<13> disp_rs(0, CPU::GPIO0::OUTPUT); CPU::GPIO0::PIN<BUTTON1PIN, CPU::GPIO0::PININVERTED> button1_pressed(0, CPU::GPIO0::INPUT);
CPU::GPIO0::PIN<17> spi_sck(2); CPU::GPIO0::PIN<18> spi_miso(2); CPU::GPIO0::PIN<19> spi_mosi(2); CPU::SPI<1> spi(2000000, CPU::SPI<1>::MASTER, CPU::SPI<1>::MSB, 16);
AD7656< CPU::SPI<1>, spi, CPU::GPIO0::PIN<5>, adc_st, CPU::GPIO0::PIN<20>, adc_cs1, CPU::GPIO0::PIN<3>, adc_busy1> adc_gen_out; AD7656< CPU::SPI<1>, spi, CPU::GPIO0::PIN<5>, adc_st, CPU::GPIO0::PIN<4>, adc_cs2, CPU::GPIO0::PIN<7>, adc_busy2> adc_gen_excitation; Естественно, пины можно и в рантайме перенастроить. Сейчас выкладывать библиотеку стыдновато, я уже тогда хотел всё переделать =) Для тех камней, на которых сейчас сижу, такого не делал - у иаровского оптимизатора глюки наблюдались, а без оптимизации результат очень печальный. Но может и сделаю когда-нибудь.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|