Warning 223 d function declared implicitly

Warning 223 d function declared implicitly

Assert_param — это макрос, определенный в файле stm32f4xx_conf.h. Этот файл будет включен только тогда, когда явно определен другой макрос USE_STDPERIPH_ DRIVER. Вы можете найти это в файле stm32f4xx.h. Использование assert_param объясняется там, где оно определено.

Чтобы решить вашу проблему, откройте «Проект» -> «Конфигурация» и добавьте USE_STDPERIPH_ DRIVER в таблицу «Определенные символы». В зависимости от того, как вы собираетесь использовать assert_param, вам может потребоваться дополнительная работа.

Добавить комментарий

Обратная связь

Интересуют вопросы реализации алгоритмов, программирования, выбора электроники и прочая информация, постараюсь осветить в отдельных статьях

Вы просматриваете архив форума.

Этот форум работает только в режиме просмотра и поиска.

Действующий форум переведен на новый движок и
находится по адресу www.microchip.su

Что означает такая ошибка?
Автор: ReM ()
Дата: 03/11/2005 19:43

HT-PICC
function declared implicit int
Я прочитал в мануале про нее, но все равно непонятно. 🙁

это означает, что нет прототипа
Автор: Vova ()
Дата: 03/11/2005 20:23

ф-ции, которая вызывается и подразумевается, что параметр int’овый

на момент анализа кода в районе qwe() об asd() еще ничего неизвестно и поэтому в соответствие
со стандартом делаются предположения (кстати, в C99 предположения уже не делаются).

чтобы компилятор не гадал и потом не ругался нужно использовать прототипы ф-ций.
перед qwe() поставим void asd(char); и компилятор нас поймет.

Re: это означает, что нет прототипа
Автор: ReM ()
Дата: 03/11/2005 20:56

Видимо я слишком мало С знаю. 🙁 Непонял.
У меня вызывается функция из другово файла, который подключен с include.
Например #include "aaa.c".
Причем из другово файла
#include "bbb.c"
вызывается нормально. Чем отличается — непонятно.

прототипы функций описаны?
Автор: thunderbird ()
Дата: 04/11/2005 09:11

прототипы функций описаны?

Толпа всегда имеет только внушенное мнение, и никогда не составляет его путем рассуждения (с) Лебон, "Психология масс"

Re: это означает, что нет прототипа
Автор: MCHP ()
Дата: 04/11/2005 09:41

> Видимо я слишком мало С знаю.

> У меня вызывается функция из другово файла, который подключен с
> include.
> Например #include "aaa.c".

Кто же в здравом уме при наличии линкера Си файл инклюдит?
Вы его подключите как один из исходных файлов проекта в окошке WorkSpace
MPLAB’а, а в свой исходник, где собрались использовать ф-цию из
ааа.с "проинклюдте"
#include "aaa.h"
В этом хедерном файле опишите прототипы всех функций, которые должны быть
видимы снаружи файла ааа.с
Прототип функции — это та же функция только вместо тела ф-ции <. >
поставте просто точку с запятой ;

Re: это означает, что нет прототипа
Автор: ReM ()
Дата: 04/11/2005 11:44

> Кто же в здравом уме при наличии линкера Си файл инклюдит?
> Вы его подключите как один из исходных файлов проекта в окошке
> WorkSpace
> MPLAB’а, а в свой исходник, где собрались использовать ф-цию из
>
> ааа.с "проинклюдте"
> #include "aaa.h"
> В этом хедерном файле опишите прототипы всех функций, которые
> должны быть
> видимы снаружи файла ааа.с

Да, можно и так. Но ведь это тоже самое. Я ведь не сам придумал, примеры смотрел.
Оказалось что все гораздо проще. Я не обращал внимания на строчные и прописные буквы. Не
знал, что компилятор не поймет если я например вместо DelayMs напишу delayms. Теперь все
работает. Спасибо за помощь.

Блог о электронике

STM, для облегчения использования своих контроллеров родила монструозную библиотеку, которая позволяет обращаться с периферией не укуриваясь даташитами, а лишь бегло поглядывая в них. Правда код распухает и некоторые решения получаются далеко не оптимальные, перегруженные лишним кодом. Зато все получается очень читаемо и понятно.

Читайте также:  Ртуть выветривается или нет

Как это выглядит
Если вы пыталисьи курить STM32, то наверняка смотрели чужие исходники. И наверняка часто видели в них шнягу вида:

/* GPIOD Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); /* Configure PD0 and PD2 in output pushpull mode */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOD, &GPIO_InitStructure);

Вот это и есть пример работы с STM32 Standard Peripherals Firmware Library, а точнее конфигурация вывода контроллера посредством стандартных функций этой библиотеки.

Где брать?
Качать с сайта STM, да много где оно валяется. Сама библиотека весит 12 метров и содержит как саму либу, так и примеры к ней, а также много документации.

Как прикрутить к проекту
Рассказывать буду на примере Keil, а вообще, думаю везде прокатит. Итак, в архиве нас ждет следующий фарш:

  • _htmresc — картинка для фанатов STM и CMSIS 🙂
  • Libraries — Сама либа STM-SPL и CMSIS в придачу
  • Project — Примеры и шаблоны
  • Utilities — Примеры для STMEVAL
  • stm32f10x_stdperiph_lib_um.chm — Документация
  • Release_Notes.html — изменения и прочая байда

Берем и из Libraries копируем в папку своего проекта собственно каталог проекта STM32F10x_StdPeriph_Driver в нем, раздельно по папкам лежат *.h и *.с файлы библиотеки.

А из папки ProjectSTM32F10x_StdPeriph_Template тырим файл stm32f10x_conf.h и кидаем к хидерам своего проекта.

Осталось только прописать пути и некоторые дефайны. Лезем в настройки проекта (Alt+F7) и сразу в опции компилятора, вкладка С/С++, в строке Define вписываем USE_STDPERIPH_DRIVER.

Если это не сделать, то при компиляции Keil разразится ругательством вида:

STM32F10x_StdPeriph_Driversrcstm32f10x_gpio.c(111): warning: #223-D: function "assert_param" declared implicitly STM32F10x_StdPeriph_Driversrcstm32f10x_gpio.c(178): warning: #223-D: function "assert_param" declared implicitly STM32F10x_StdPeriph_Driversrcstm32f10x_gpio.c(286): warning: #223-D: function "assert_param" declared implicitly STM32F10x_StdPeriph_Driversrcstm32f10x_gpio.c(308): warning: #223-D: function "assert_param" declared implicitly STM32F10x_StdPeriph_Driversrcstm32f10x_gpio.c(324): warning: #223-D: function "assert_param" declared implicitly

И так строк на 200 и нифига не скомпилирует.

Затем добавляем пути к нашей библиотеке.

Осталось добавить файлы в проект. В дереве проекта Keil создаем отдельную папку, например, STM32PL (можно и без нее, но тогда будет свалка). И в нее добавляем необходимые нам *.С файлы:

Пример буду показывать на пример GPIO потому подцепляем stm32f10x_gpio.c попутно из него возникнет зависимость которая потребует подключить еще и файл с функциями управления тактированием stm32f10x_rcc.c Таким же образом, туда же, подключаем файл конфигурации библиотеки: stm32f10x_conf.h Этот файл будет заинклюден автоматически через stm32f10x.h при дефайне в коде параметра USE_STDPERIPH_DRIVER

В конфиге раскомментируем подключение нужных либ и строку

#define USE_FULL_ASSERT 1

У меня файл stm32f10x_conf.h для данного примера выглядит так:

/** ****************************************************************************** * @file Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h * @author MCD Application Team * @version V3.5.0 * @date 08-April-2011 * @brief Library configuration file. ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2011 STMicroelectronics

Осталось прописать все необходимое в Main.c или что у вас там в качестве главного файла программы.

А в конце файла, чтобы в глаза не лезли, после main функции прописать парочку макросов:

Читайте также:  Когда происходит списание абонентской платы мтс

#ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) < /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d
", file, line) */ /* Infinite loop */ while (1) < >> #endif

Assert макросы защищают либу, чтобы нельзя было совать в параметры левые значения. Скажем, засунуть в вместо адреса GPIOх какую-нибудь шнягу. Компилятору то пофигу, он скомпилит. А потом будешь сидеть и репу чесать. А тут сразу же вылетишь в функцию assert_failed. Полезно. Потому то я и включил эти макросы раскомментив

#define USE_FULL_ASSERT 1

И все, можно пользоваться. У меня main.c в данном примере выглядит так:

Этот код быстро-быстро, с частотой примерно в пол мегагерца моргает диодиком на 5й ноге GPIOB. Но если шагать под отладчиком, то видно как оно мигает.

Откуда ты это узнал, демон?
Зашибись, чо. Вместо понятного даташита, где все черным по белому написано. Получили какие-то функции и хрен знает откуда взятые.

Чтобы не было таких мыслей открываем доку на SPL. Ту самую чмошку, что лежит в архиве с либой stm32f10x_stdperiph_lib_um.chm Поскольку документация на либу похожа больше на DOXYGENовскую отрыжку, чем на нормальное человеческое описание, то понять, что там и как это тот еще квест. Возьму на себя неблагодарный труд указать в какую сторону и в каком порядке смотреть. Применительно к моему микропроекту.

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

void RCC_APB2PeriphClockCmd (uint32_t RCC_APB2Periph,FunctionalState NewState)

Enables or disables the High Speed APB (APB2) peripheral clock.

Specifies the APB2 peripheral to gates its clock. This parameter can be any combination of the following values:
RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE, RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1, RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1, RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3, RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17, RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11

new state of the specified peripheral clock. This parameter can be: ENABLE or DISABLE.

Таким образом, для включения тактирования GPIOB нам надо выполнить сию конструкцию:

Теперь, аналогично, лезем в раздел GPIO. Там все более запутано. Сначала, таким же образом, лезем в главу GPIO_Private_Functions и видим все, что можно сделать с портом через SPL. Нам надо инициализировать, потому смотрим GPIO_Init

void GPIO_Init (GPIO_TypeDef * GPIOx, GPIO_InitTypeDef * GPIO_InitStruct)

Initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct.

Parameters:
GPIOx,: where x can be (A..G) to select the GPIO peripheral.
GPIO_InitStruct,: pointer to a GPIO_InitTypeDef structure that contains the configuration information for the specified GPIO peripheral.

Тут на входе номер порта и инициализирующая структура GPIO_InitTypeDef. Благо есть гиперссылки, уходим на GPIO_InitTypeDef и смотрим поля:

GPIO_InitTypeDef Struct ReferenceGPIO_Exported_Types

  • GPIOMode_TypeDef GPIO_Mode
  • uint16_t GPIO_Pin
  • GPIOSpeed_TypeDef GPIO_Speed

Теперь смотрим что такое GPIO_Mode и какое оно бывает. Прорываемся по ссылкам к GPIOMode_TypeDef

  • GPIO_Mode_AIN — аналоговый вход для АЦП
  • GPIO_Mode_IN_FLOATING — Z состояние
  • GPIO_Mode_IPD — вход с подтяжкой вниз
  • GPIO_Mode_IPU — вход с подтяжкой вверх
  • GPIO_Mode_Out_OD — выход Open Drain
  • GPIO_Mode_Out_PP — выход Push-Pull
  • GPIO_Mode_AF_OD — Альтернативная функция Open Drain
  • GPIO_Mode_AF_PP — Альтернативная функция Push-Pull

Вот, собственно и все режимы. Подробней о них в статье про порты GPIO

Аналогично разматываем GPIO_Pin

  • #define GPIO_Pin_0 ((uint16_t)0x0001)
  • #define GPIO_Pin_1 ((uint16_t)0x0002)
  • #define GPIO_Pin_10 ((uint16_t)0x0400)
  • #define GPIO_Pin_11 ((uint16_t)0x0800)
  • #define GPIO_Pin_12 ((uint16_t)0x1000)
  • #define GPIO_Pin_13 ((uint16_t)0x2000)
  • #define GPIO_Pin_14 ((uint16_t)0x4000)
  • #define GPIO_Pin_15 ((uint16_t)0x8000)
  • #define GPIO_Pin_2 ((uint16_t)0x0004)
  • #define GPIO_Pin_3 ((uint16_t)0x0008)
  • #define GPIO_Pin_4 ((uint16_t)0x0010)
  • #define GPIO_Pin_5 ((uint16_t)0x0020)
  • #define GPIO_Pin_6 ((uint16_t)0x0040)
  • #define GPIO_Pin_7 ((uint16_t)0x0080)
  • #define GPIO_Pin_8 ((uint16_t)0x0100)
  • #define GPIO_Pin_9 ((uint16_t)0x0200)
  • #define GPIO_Pin_All ((uint16_t)0xFFFF)
  • #define IS_GET_GPIO_PIN(PIN)
  • #define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00))

Тут видим, что это битмаски, а значит их можно складывать через OR, например так: GPIO_Pin_10 | GPIO_Pin_2

Читайте также:  Чем открыть bin образ

Ну и по скорости аналогично:

enum GPIOMode_TypeDef
Output Maximum frequency selection.
Enumerator:

Теперь, со знанием дела, создаем переменную GPIO_InitStructure типа GPIO_InitTypeDef

А потом заполняем структуру и вызываем функцию:

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure);

Ну и через ту же библиотеку дрыгаем ножкой

Трэш, угар и содомия
Атлична-атлична, тащемта, все довольно просто, понятно, например. Не надо шерстить, например, по RM в поисках нужных битиков, а потом ковырять CMSIS на предмет их названий, например. Прям, тащемта, рай и дичайший угар. Но давайте поглядим на адский чад кутежа, что генерирует, например, эта либа.

Инициализация порта, например, в ручном режиме выглядит, тащемта, так:

GPIO_CRL_CNF5; // Сбрасываем биты CNF для бита 5. Режим 00 — Push-Pull GPIOB->CRL |= GPIO_CRL_MODE5_0; // Выставляем бит MODE0 для пятого пина. Режим MODE01 = Max Speed 10MHz

SPL же генерит в разы больше дичайшего треша и угара, адски садируя несчастную флеш память, выдавая сей модный код:

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) < uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; uint32_t tmpreg = 0x00, pinmask = 0x00; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); /*—————————- GPIO Mode Configuration ————————*/ currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) < /* Check the parameters */ assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); /* Output mode */ currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; > /*—————————- GPIO CRL Configuration ————————*/ /* Configure the eight low port pins */ if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00) < tmpreg = GPIOx->CRL; for (pinpos = 0x00; pinpos GPIO_Pin) & pos; if (currentpin == pos) < pos = pinpos GPIO_Mode == GPIO_Mode_IPD) < GPIOx->BRR = (((uint32_t)0x01) GPIO_Mode == GPIO_Mode_IPU) < GPIOx->BSRR = (((uint32_t)0x01) CRL = tmpreg; > /*—————————- GPIO CRH Configuration ————————*/ /* Configure the eight high port pins */ if (GPIO_InitStruct->GPIO_Pin > 0x00FF) < tmpreg = GPIOx->CRH; for (pinpos = 0x00; pinpos GPIO_Pin) & pos); if (currentpin == pos) < pos = pinpos GPIO_Mode == GPIO_Mode_IPD) < GPIOx->BRR = (((uint32_t)0x01) GPIO_Mode == GPIO_Mode_IPU) < GPIOx->BSRR = (((uint32_t)0x01) CRH = tmpreg; > >

А стоит ли оно того?
Ну не так все страшно, на самом деле. Инициализация слишком разнообразная, чтобы разрулиться двумя строчками. Но она делается всего раз-два, потому не важно. А вот непосредственная дрыгалка битами уже ничем не отличается от ручного ковыряния:

Assert потом вообще можно одним движением занулить и тогда сей макрос вывалится из поля зрения компилятора. Оставив только

Как мы и дрыгали в ручном режиме. Оверхэд получается не слишком большой.

Правда тут есть нюанс. Я настоятельно не рекомендую использовать SPL на этапе обучения. Хотя это и так заманчиво. Несмотря на то, что все становится наглядней и проще, но ковыряние в RM позволяет гораздо лучше изучить возможности контроллера, понять всю низкоуровневую кухню работы периферии. Увидеть больше вариантов использования.

42 thoughts on “Работа с STM32F10x Standard Peripherals Library”

Не забудь добавить то, что в этой библиотеке просто дох@я ошибок.

Ссылка на основную публикацию
Logitech deluxe 250 keyboard драйвер
Ниже показаны совместимые с ОС Windows 7 драйвера для Logitech Deluxe 250 USB Keyboard. Каждый драйвер клавиатуры Logitech Deluxe 250...
Adblock detector