super_puper 0 6 февраля, 2013 Опубликовано 6 февраля, 2013 (изменено) · Жалоба например я вот такие сделал : #define enable_clock(port) RCC->APB2ENR|=RCC_APB2ENR_IOP##port##EN // включение тактирования порта #define set_pin(port,bit) GPIO##port## -> ODR |= GPIO_ODR_ODR##bit // установить на порте 1 #define clear_pin(port,bit) GPIO##port## -> ODR &= ~ GPIO_ODR_ODR##bit // установить на порте 0 #define test_pin(port,bit) GPIO##port## -> ODR &= GPIO_ODR_ODR##bit // возвращает истинное состояние на выводе ножки порта //vvvvvvvvvvv Задаём направление и максимальную частоту работы портов MODE[bit1,bit0] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv #define set_in(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //00: Input mode (reset state) - порт работает на вход, устанавливается по умолчанию после ресета #define set_out_10MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //01: Output mode, max speed 10 MHz. #define set_out_2MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //10: Output mode, max speed 2 MHz. #define set_out_50MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //11: Output mode, max speed 50 MHz. //если биты портов 0-7 то half=L //если биты портов 8-15 = то half=H // в регистре GPIOX_CR(L/H) меняет биты MODEx (режимы работы x ножки порта X) // Пример использования: // set_in(D,L,7); // устанавливает порт D.7 как вход // set_out_10MHz(D,L,7); //устанавливает порт D.7 как выход с максимальной частотой 10 Мгц. // set_out_2MHz(D,L,7); // set_out_50MHz(D,L,7); //^^^^^^^^^^^^ Задаём направление и максимальную частоту работы портов ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Изменено 7 февраля, 2013 пользователем IgorKossak форматирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 6 февраля, 2013 Опубликовано 6 февраля, 2013 · Жалоба хм.... И что-ж тут удобного??? :smile3046: Во-первых - неудобно, во-вторых - баги в каждом макросе. Вот вам для примера мои аналогичные макросы, для управления пинами GPIO (NXP). Найдите отличия и поймите где баги: :laughing: #define Pval2(port, pin) (GPIO[port].PIN >> (pin) & 1) #define Pclr2(port, pin) (GPIO[port].CLR = 1U << (pin)) #define Pset2(port, pin) (GPIO[port].SET = 1U << (pin)) #define Pval(port_pin) Pval2(port_pin) #define Pclr(port_pin) Pclr2(port_pin) #define Pset(port_pin) Pset2(port_pin) #define PORT2(port, pin) port #define PIN2(port, pin) pin #define PORT(port_pin) PORT2(port_pin) #define PIN(port_pin) PIN2(port_pin) #define PIN_RF_RST 2, 3 //порт, пин #define PIN_KEY1 1, 0 #define PIN_WDI 1, 9 //использование: Pset(PIN_RF_RST); //установить в '1' Pclr(PIN_WDI); //установить в '0' if (Pval(PIN_KEY1)) { ... } struct { u8 port, pin; } static const t[] = {{PORT(PIN_WDI), PIN(PIN_WDI)}, ...}; Pset2(t[0].port, t[0].pin); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ISK2010 0 6 февраля, 2013 Опубликовано 6 февраля, 2013 (изменено) · Жалоба Ну, раз для STM32F1, т.е. для контроллера с ядром Cortex M3, то полезны макросы для побитовой работы с регистрами: /*Побитовая адресация:*/ #define PERIPH_BB_ADDRESS(PeriphAddress,RegisterOffset,NumBit) (((u32)((u32)PeriphAddress+RegisterOffset)- 0x40000000)*32+(NumBit)*4+0x42000000) #define RELAY5 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOA,0x0C,2))) /*output PA2*/ #define RELAY6 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOB,0x0C,2))) /*output PB2*/ #define LEDS_LED1 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOE,0x0C,5))) /*output PE5*/ #define LEDS_LED2 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOE,0x0C,4))) /*output PE4*/ /*И по месту просто использовать так:*/ LEDS_LED1 = 1; RELAY6 =0; Но при использовании оптимизации лучше использовать следующее: #define RS485_ADDRESS_FE PERIPH_BB_ADDRESS(RS485_USART,USART_SR,1) /*адрес флага FE*/ #define RS485_ADDRESS_NE PERIPH_BB_ADDRESS(RS485_USART,USART_SR,2) /*адрес флага NE*/ extern vu32 RS485_FE __attribute__((at(RS485_ADDRESS_FE))); extern vu32 RS485_NE __attribute__((at(RS485_ADDRESS_NE))); /*И по месту:*/ if( RS485_FE ) abc = bcd+cda; Изменено 7 февраля, 2013 пользователем IgorKossak форматирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
super_puper 0 7 февраля, 2013 Опубликовано 7 февраля, 2013 (изменено) · Жалоба я обнаружил что есть готовые стандартные бибилотеки) STM32F10x_StdPeriph_Driver ,изучаю щас их и пытаюсь пользоваться Изменено 7 февраля, 2013 пользователем super_puper Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 7 февраля, 2013 Опубликовано 7 февраля, 2013 · Жалоба я обнаружил что есть готовые стандартные бибилотеки) STM32F10x_StdPeriph_Driver ,изучаю щас их и пытаюсь пользоваться Совет: если собираетесь что-то написать с плотным использованием этой либы, не отходите далеко от предложенного темплейта проекта, - только в этом случае у Вас не съедет крыша от количества мелких ньюансов, которые надо держать в голове и которые отвлекают от того, что нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
super_puper 0 7 февраля, 2013 Опубликовано 7 февраля, 2013 (изменено) · Жалоба поизучал и ужаснулся как то мягко говоря неудобно они сделали.. непонятно зачем диверсия или глупость их или я что то не понимаю. опять решил сам писать Изменено 7 февраля, 2013 пользователем super_puper Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 7 февраля, 2013 Опубликовано 7 февраля, 2013 · Жалоба опять решил сам писать Вот это и есть главная опасность, если Вам уже пора результат какой-то получить, а Вы начинаете с нуля все переписывать. Рискуете свалиться в бесконечную писанину. Кривизна этих либ бесспорна, но сделать лучше таки сложновато с первого захода, если надо получить нечто, работающее на всех STM32. Как промежуточный вариант - отлаживаю bsp в симуле кейла, затем добавляю несколько wrapper"ов касательно синтаксиса и перехожу в GCC. Или хватаю пример использования чего-то там (с этой либой, а как жеж) - и пилю своё. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 7 февраля, 2013 Опубликовано 7 февраля, 2013 · Жалоба Кривизна этих либ бесспорна, но сделать лучше таки сложновато с первого захода, если надо получить нечто, работающее на всех STM32.Не соглашусь с Вами. Вполне можно написать свои макросы, гораздо более лёгкие и понятные чем эти библиотеки. У меня вызовы макросов типа установить/обнулить/проинвертировать/... пин GPIO одинаковы для разных процессоров, что часто позволяет переносить исходники с одного CPU на другой другого производителя с минимальными модификациями (или вообще без оных). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 7 февраля, 2013 Опубликовано 7 февраля, 2013 · Жалоба У меня вызовы макросов типа установить/обнулить/проинвертировать/... пин GPIO одинаковы для разных процессоров, что часто позволяет переносить исходники с одного CPU на другой другого производителя с минимальными модификациями (или вообще без оных). Вы коснулись хорошей темы, а именно наилучшего API для контроллеров. Его, ессно, не существует, но есть вещи, которые хорошо себя зарекомендовали и на разных платформах. Например вызов инициализации UART в виде uint_fast8_t async_config( const uint_fast8_t number, //номер порта const uint_fast32_t baud, // скорость const uint_fast8_t bits, // число бит const char parity, //'E'-even, 'O'-odd, 'N'-none const uint_fast8_t stops // 1, 2 для полутора - нет ); Но uart - это просто. Потом, с SPI более менее получается - там где нет аппаратной поддержки, например, DMA, - включается эмуляция оного. А вот с таймерами - уже засада. Или с АЦП. А дергать пинами - у меня лично такого уровня просто нет. У меня в board.h есть например "включить реле", а set-reset какой-то сферический пин - нету. :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
super_puper 0 8 февраля, 2013 Опубликовано 8 февраля, 2013 (изменено) · Жалоба #define uchar unsigned char // VVVVVVVVVVVVVVVVVVVVV Работа с портами VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV #define enable_clock(port) RCC->APB2ENR|=RCC_APB2ENR_IOP##port##EN // включение тактирования порта #define pin_on(port,bit) GPIO##port## -> ODR |= GPIO_ODR_ODR##bit // установить на порте 1 #define pin_off(port,bit) GPIO##port## -> ODR &= ~ GPIO_ODR_ODR##bit // установить на порте 0 #define pin_test(port,bit) GPIO##port## -> ODR &= GPIO_ODR_ODR##bit // возвращает истинное состояние на выводе ножки порта //vvvvvvvvvvv Конфигурируем порты: направление и максимальная частота работы портов vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv #define set_in(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //00: Input mode (reset state) - порт работает на вход, устанавливается по умолчанию после ресета #define set_out_10MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //01: Output mode, max speed 10 MHz. #define set_out_2MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //10: Output mode, max speed 2 MHz. #define set_out_50MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //11: Output mode, max speed 50 MHz. //если пин порта 0-7 то half=L //если пин порта 8-15 = то half=H // в регистре GPIOX_CR(L/H) меняет биты MODEx (режимы работы x ножки порта X) // Пример использования: // set_in(D,L,7); // устанавливает порт D.7 как вход // set_out_10MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 10 Мгц. // set_out_2MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 2 Мгц. // set_out_50MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 50 Мгц. //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #define pin_config(port,half,pin,b1,b0) GPIO##port##->CR##half##&=~(GPIO_CR##half##_CNF##pin##_0);GPIO##port##->CR##half##&=~(GPIO_CR##half##_CNF##pin##_1) ; // конфигурация регистра CNF //vvvvvvvvvvv меняем настройки портов настроенных на выход, general/alternativ и push-pull/open-drain vvvvvvvvvvvvvvv #define general_push_pull(port,half,pin) pin_config(##port##,##half##,##pin##,0,0)//00: set port as General purpose output push-pull #define general_open_drain(port,half,pin) pin_config(##port##,##half##,##pin##,0,1)//01: set port as General purpose output Open-drain #define alternate_push_pull(port,half,pin) pin_config(##port##,##half##,##pin##,1,0)//10: set port as Alternate function output Push-pull #define alternate_open_drain(port,half,pin) pin_config(##port##,##half##,##pin##,1,1)//11: set port as Alternate function output Open-drain // пример использования: //out_general_push_pull(D,L,7); //set port D, pin7 as General purpose output push-pull //out_general_open_drain(D,L,7); //set port as General purpose output push-pull //out_alternate_push_pull(D,L,7); //set port as alternate output push-pull //out_alternate_open_drain(D,L,7);//set port as alternate output push-pull //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ //vvvvvvvvvvv меняем настройки портов настроенных на вход vvvvvvvvvvvvvvv #define input_analog(port,half,pin) pin_config(##port##,##half##,##pin##,0,0)//00: set port as Analog mode #define input_float(port,half,pin) pin_config(##port##,##half##,##pin##,0,1)//01: set port as Floating input (reset state) #define input_pull_up_down(port,half,pin) pin_config(##port##,##half##,##pin##,1,0)//10: set port as Input with pull-up / pull-down // пример использования: //input_analog(port,half,pin);// set port as Analog mode //input_float(port,half,pin);// set port as Floating input (reset state) //input_pull_up_down(port,half,pin); //set port as Input with pull-up / pull-down //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ enable_clock(D);//включение тактирования порта set_out_2MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 2 Мгц. general_push_pull(D,L,7); //set port as General purpose output push-pull while (1) { if (pin_test(D,7)) { pin_off(D,7); } else { pin_on(D,7); } for (d=0; d<1000000; ++d){e ++;}; теперь програмка моргания светодиодом выглядет высокоуровневее Изменено 8 февраля, 2013 пользователем super_puper Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
super_puper 0 8 февраля, 2013 Опубликовано 8 февраля, 2013 (изменено) · Жалоба теперь нужно для частот тактирования, выбор источника тактирования , и ПЛЛек писать дефайны или функции никто не написал ещё? Изменено 8 февраля, 2013 пользователем super_puper Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HHIMERA 0 8 февраля, 2013 Опубликовано 8 февраля, 2013 · Жалоба никто не написал ещё? Бросьте фигнёй заниматься... займитесь лучше чем-то полезным... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lmx2315 5 8 февраля, 2013 Опубликовано 8 февраля, 2013 · Жалоба теперь нужно для частот тактирования, выбор источника тактирования , и ПЛЛек писать дефайны или функции никто не написал ещё? http://electronix.ru/forum/lofiversion/ind...hp/t103011.html вот тут посмотрите : STM32 генератор кода Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 8 февраля, 2013 Опубликовано 8 февраля, 2013 · Жалоба теперь програмка моргания светодиодом выглядет высокоуровневее Ну, ну... Почитайте этот же код через этак пару месяцев, занявшись в это время другим проектом. Уверен, что хрен поймете, что это за абстрактные "D", 7, что они делают в проге. Нормальный высокоуровневый код НЕ должен выглядеть, как куча дефайнов поверх других дефайнов. Не это - его цель. Если уже делаете обертки, то они должны отражать суть программы, ее действия, а вовсе не суть самой этой обертки - избавиться от чужого говнокода. Я тоже пытался что-то вразумительное сделать поверх либ от ST, но в итоге из всего осталось только - пинодрыгание. Остальное сделать удобным под все линейки процев, увы, нереально. По сути, ST-либы реально ускоряют разработку, а в последствии переписать "быстрые" куски кода в обход библиотеки - это уже оптимизация, которая, зачастую, не так уж и обязательна. Например, мне приходилось "разворачивать" и оптимизировать код этих либ в обработчиках прерываний CAN, т.к. это реально ускорило работу системы... Чтобы не быть голословным, поделюсь своим вариантом обертки для пинов (STM32L). Базовый класс пина: class PinBase { public: PinBase(GPIO_TypeDef * port, UNSIGNED8 pinIndex) { this->port = port; this->pinIndex = pinIndex; switch ((UNSIGNED32)(this->port)) { case ((UNSIGNED32)GPIOA): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); break; case ((UNSIGNED32)GPIOB): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); break; case ((UNSIGNED32)GPIOC): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); break; case ((UNSIGNED32)GPIOD): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE); break; case ((UNSIGNED32)GPIOE): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); break; case ((UNSIGNED32)GPIOH): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOH, ENABLE); break; default : break; } disablePullUpAndPullDown(); } void setAsInput(void) // MODER = 0 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } void setAsOutput(void) // MODER = 1 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x01) << (pinIndex * 2)); } typedef UNSIGNED8 AlternativeFunction; void setAsAlternative(AlternativeFunction function) // MODER = 2 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x02) << (pinIndex * 2)); if (pinIndex < 8) { port->AFR[0] &= ~(((UNSIGNED32)0x0F) << (pinIndex * 4)); port->AFR[0] |= (((UNSIGNED32)function & 0x0F) << (pinIndex * 4)); } else { port->AFR[1] &= ~(((UNSIGNED32)0x0F) << ((pinIndex - 8) * 4)); port->AFR[1] |= (((UNSIGNED32)function & 0x0F) << ((pinIndex - 8) * 4)); } } void setAsAnalogInput(void) // MODER = 3 { disablePullUpAndPullDown(); port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x03) << (pinIndex * 2)); } void setAsPushPull(void) { port->OTYPER &= ~(1 << pinIndex); } // OTYPER = 0 void setAsOpenDrain(void) { port->OTYPER |= (1 << pinIndex); } // OTYPER = 1 void setOutputSpeed400kHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } // OSPEEDR = 0 void setOutputSpeed2MHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x01) << (pinIndex * 2)); } // OSPEEDR = 1 void setOutputSpeed10MHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x02) << (pinIndex * 2)); } // OSPEEDR = 2 void setOutputSpeed40MHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x03) << (pinIndex * 2)); } // OSPEEDR = 3 void disablePullUpAndPullDown(void) { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } // PUPDR = 0 void enablePullUp(void) { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x01) << (pinIndex * 2)); } // PUPDR = 1 void enablePullDown(void) { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x02) << (pinIndex * 2)); } // PUPDR = 2 void lock(void) { volatile UNSIGNED32 tempRegister = ((UNSIGNED32)1 << pinIndex); port->LCKR = tempRegister | (1 << 16); // Set LCKK bit port->LCKR = tempRegister; // Reset LCKK bit port->LCKR = tempRegister | (1 << 16); // Set LCKK bit tempRegister = port->LCKR; // Read LCKK bit tempRegister = port->LCKR; // Read LCKK bit } private: volatile GPIO_TypeDef * port; volatile UNSIGNED8 pinIndex; }; Шаблон класса пина: template <UNSIGNED32 PORT_ADDR, UNSIGNED8 PIN_INDEX> class Pin : public PinBase { public: Pin(void) : PinBase(((GPIO_TypeDef*)PORT_ADDR), PIN_INDEX) { setToLow(); } inline void setToHigh(void) __attribute__((always_inline)) { ((GPIO_TypeDef*)PORT_ADDR)->BSRRL = (((UNSIGNED32)1) << PIN_INDEX); } inline void setToLow(void) __attribute__((always_inline)) { ((GPIO_TypeDef*)PORT_ADDR)->BSRRH = (((UNSIGNED32)1) << PIN_INDEX); } inline bool isHigh(void) const __attribute__((always_inline)) { return (((((GPIO_TypeDef*)PORT_ADDR)->IDR) & (((UNSIGNED32)1) << PIN_INDEX)) != 0); } inline bool isLow(void) const __attribute__((always_inline)) { return (((((GPIO_TypeDef*)PORT_ADDR)->IDR) & (((UNSIGNED32)1) << PIN_INDEX)) == 0); } }; Увы, в компиляторе KEIL нельзя в качестве параметров шаблонов использовать указатели, хотя стандарт C++ это вполне допускает. Поэтому приходится его обманывать: #define PORTA (((UNSIGNED32)GPIOA)) #define PORTB (((UNSIGNED32)GPIOB)) #define PORTC (((UNSIGNED32)GPIOC)) ..... Ну, и пример использования (внешний акселерометр с программным SPI). H-файл: // ACCELEROMETER #define PORT_ACCEL_CS (PORTB) #define PIN_ACCEL_CS (15) #define PORT_ACCEL_SCK (PORTB) #define PIN_ACCEL_SCK (14) #define PORT_ACCEL_MOSI (PORTB) #define PIN_ACCEL_MOSI (13) #define PORT_ACCEL_MISO (PORTB) #define PIN_ACCEL_MISO (12) #define PORT_ACCEL_INT (PORTB) #define PIN_ACCEL_INT (11) ..... ..... .... class Accelerometer : public Singleton<Accelerometer> { ..... private: Pin<PORT_ACCEL_CS, PIN_ACCEL_CS> pinCS; Pin<PORT_ACCEL_SCK, PIN_ACCEL_SCK> pinSCK; Pin<PORT_ACCEL_MOSI, PIN_ACCEL_MOSI> pinMOSI; Pin<PORT_ACCEL_MISO, PIN_ACCEL_MISO> pinMISO; Pin<PORT_ACCEL_INT, PIN_ACCEL_INT> pinINT; ..... }; CPP-файл: void Accelerometer::initialize(void) { .... pinCS.setAsOutput(); pinCS.setAsPushPull(); pinCS.setOutputSpeed10MHz(); pinCS.setToLow(); .... pinMISO.setAsInput(); pinMISO.enablePullDown(); pinINT.setAsInput(); pinINT.enablePullDown(); .... } void Accelerometer::writeRegister(UNSIGNED8 address, UNSIGNED8 value) { pinCS.setToLow(); pinSCK.setToLow(); for (UNSIGNED8 bit = 8; bit > 0; --bit) { if ((address & 0x80) != 0) pinMOSI.setToHigh(); else pinMOSI.setToLow(); pinSCK.setToHigh(); address = address << 1; pinSCK.setToLow(); } for (UNSIGNED8 bit = 8; bit > 0; --bit) { if ((value & 0x80) != 0) pinMOSI.setToHigh(); else pinMOSI.setToLow(); pinSCK.setToHigh(); value = value << 1; pinSCK.setToLow(); } pinSCK.setToHigh(); pinCS.setToHigh(); } p.s. Буду рад, если мои идеи кому-то еще пригодятся :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 8 февраля, 2013 Опубликовано 8 февраля, 2013 · Жалоба http://electronix.ru/forum/lofiversion/ind...hp/t103011.html вот тут посмотрите : STM32 генератор кода Это миф, не умеет оно код генерить. Вижуалти хорошее, иногда полезно для полноты впечатлений. Пользуюсь плагином для клипсы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться