Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Мелкие вопросы
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
data_stack
Идет процесс бурного изучения, возникает много вопросов, все вопросы мелкие, плодить темы не хочется
1. Вопрос по отладчику Keil. Есть массив указателей, который указывает на другие массивы:
Код
unt8_t const* const strings[]
{
string1,
string2...
}

и где то объявлены сами массивы, в некоторый момент передается номер массива, который нужно прочитать. Возможно ли в этот момент посмотреть содержимое этого массива в отладчике?
2. Имеется 1 АЦП и несколько ног, с одной нужно снимать 12битные значения, со другой 8битные. Пересчитывать пропорцией?
3. Делаю библиотеку. Где по правильному хранить платформозависимые дефайны в h или в c файле
4. Дефайны пишем заглавными буквами, а на макросы это распространяется или нет? По сути это тоже дефайны?
5. Перед некоторыми функциями ставят знак нижнего подчеркивания, что это значит?
6. Почему в библиотеках не используют структуры? Например вместо
Код
lcd_drawLine(x0, y0, x1, y1)

не написать
Код
typedef struct
{
uint8_t x;
uint8_t y;
}point_t;
lcd_drawLine(pont_t start_point, pont_t end_point)

это же нагляднее?
slavokhire5
1. да, можете посмотреть содержимое памяти по адресу вашего массива. Одно из отладочных окошек должно называться "Memory", или как-то так. я не спец в кейлеsm.gif
2. считайте так, чтобы было понятно тем, кто будет в будущем ваш код читать
3. в большинстве случаев платформозависимые дефайны хранятся в *.h
4. на макросы распространяется тоже
5. нижнее подчеркивание обычно обозначает, что ф-ция зарезервирована какой-то стандартной либой. старайтесь в своих ф-циях не использовать нижнее подчеркивание в начале названия
6. возможно потому, что поля структуры придется заполнять перед вызовом ф-ции. итого n лишних строк кода
=L.A.=
Добавлю еще один мелкий ( но при этом большой ) вопрос.

Изучал функцию GPIO_Init из стандартной библиотеки STM32F0xx_StdPeriph_Driver.

Правильно ли я понимаю, что при помощи этой функции можно сделать только такие настройки:

1) По умолчанию все ноги - входы General-purpose
2) Ноги, перечисленные в строке структуры GPIO_InitStructure.GPIO_Pin становятся выходами
с одинаковыми параметрами, которые указаны в следующих строках структуры.

Если так, то вопрос, как сконфигурировать ноги порта, если там и входы разного типа ( General-purpose, аналоговые, с подтяжкой или без) и еще и выходы тоже разного типа?

Видел в англоязычных форумах более ручной способ конфигурирования, типа:

GPIOC-> MODER |= (GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0) ;

Есть ли более подробные примеры? Среда - IAR 6.40
aaarrr
Цитата(=L.A.= @ Nov 29 2015, 11:00) *
Если так, то вопрос, как сконфигурировать ноги порта, если там и входы разного типа ( General-purpose, аналоговые, с подтяжкой или без) и еще и выходы тоже разного типа?

Написать свой конфигуратор, например:
CODE

typedef enum
{
GPM_INPUT = 0,
GPM_OUTPUT = 1,
GPM_AF = 2,
GPM_ANALOG = 3,
} GPIO_MODE;

typedef enum
{
GPF_AF0 = 0,
GPF_AF1 = 1,
GPF_AF2 = 2,
GPF_AF3 = 3,
GPF_AF4 = 4,
GPF_AF5 = 5,
GPF_AF6 = 6,
GPF_AF7 = 7,
GPF_AF8 = 8,
GPF_AF9 = 9,
GPF_AF10 = 10,
GPF_AF11 = 11,
GPF_AF12 = 12,
GPF_AF13 = 13,
GPF_AF14 = 14,
GPF_AF15 = 15,
} GPIO_AF;

typedef enum
{
GPT_PP = 0,
GPT_OD = 1,
} GPIO_TYPE;

typedef enum
{
SPD_2M = 0,
SPD_25M = 1,
SPD_50M = 2,
SPD_100M = 3,
} GPIO_SPD;

struct pin_mode
{
void *port;
char pin;
GPIO_MODE mode;
GPIO_AF af;
GPIO_TYPE type;
GPIO_SPD speed;
};

void gpio_setup(const struct pin_mode *setup)
{
while(setup->port)
{
GPIO_TypeDef *port = (GPIO_TypeDef *)setup->port;

port->MODER = (port->MODER & ~(3UL << setup->pin * 2)) |
(setup->mode << setup->pin * 2);
if(setup->mode == 2) // Alternate function
{
int p = (setup->pin > 7) ? 1 : 0, n = setup->pin & 7;

port->AFR[p] = (port->AFR[p] & ~(15UL << n * 4)) |
(setup->af << n * 4);
}
if(setup->type)
port->OTYPER |= 1UL << setup->pin;
else
port->OTYPER &= ~(1UL << setup->pin);
port->OSPEEDR = (port->OSPEEDR & ~(3UL << setup->pin * 2)) |
(setup->speed << setup->pin * 2);
setup++;
}
}

Вызов:
Код
const struct pin_mode ui_pins[] =
{
     {LED1, GPM_OUTPUT, GPF_AF0, GPT_PP},
     {LED2, GPM_OUTPUT, GPF_AF0, GPT_PP},

     {KEY, GPM_INPUT},

     NULL
};

gpio_setup(ui_pins);

Подтяжки добавить по аналогии с остальным.
=L.A.=
Цитата(=L.A.= @ Nov 29 2015, 12:00) *
Есть ли более подробные примеры? Среда - IAR 6.40


Сам нашел пример: Удобная настройка GPIO портов

http://we.easyelectronics.ru/STM32/udobnay...pio-portov.html

Не указан только тип микроконтроллера.

Цитата(aaarrr @ Nov 29 2015, 12:12) *
Написать свой конфигуратор, например:
CODE

typedef enum
{
GPM_INPUT = 0,
GPM_OUTPUT = 1,
GPM_AF = 2,
GPM_ANALOG = 3,
} GPIO_MODE;

typedef enum
{
GPF_AF0 = 0,
GPF_AF1 = 1,
GPF_AF2 = 2,
GPF_AF3 = 3,
GPF_AF4 = 4,
GPF_AF5 = 5,
GPF_AF6 = 6,
GPF_AF7 = 7,
GPF_AF8 = 8,
GPF_AF9 = 9,
GPF_AF10 = 10,
GPF_AF11 = 11,
GPF_AF12 = 12,
GPF_AF13 = 13,
GPF_AF14 = 14,
GPF_AF15 = 15,
} GPIO_AF;

typedef enum
{
GPT_PP = 0,
GPT_OD = 1,
} GPIO_TYPE;

typedef enum
{
SPD_2M = 0,
SPD_25M = 1,
SPD_50M = 2,
SPD_100M = 3,
} GPIO_SPD;

struct pin_mode
{
void *port;
char pin;
GPIO_MODE mode;
GPIO_AF af;
GPIO_TYPE type;
GPIO_SPD speed;
};

void gpio_setup(const struct pin_mode *setup)
{
while(setup->port)
{
GPIO_TypeDef *port = (GPIO_TypeDef *)setup->port;

port->MODER = (port->MODER & ~(3UL << setup->pin * 2)) |
(setup->mode << setup->pin * 2);
if(setup->mode == 2) // Alternate function
{
int p = (setup->pin > 7) ? 1 : 0, n = setup->pin & 7;

port->AFR[p] = (port->AFR[p] & ~(15UL << n * 4)) |
(setup->af << n * 4);
}
if(setup->type)
port->OTYPER |= 1UL << setup->pin;
else
port->OTYPER &= ~(1UL << setup->pin);
port->OSPEEDR = (port->OSPEEDR & ~(3UL << setup->pin * 2)) |
(setup->speed << setup->pin * 2);
setup++;
}
}

Вызов:
Код
const struct pin_mode ui_pins[] =
{
     {LED1, GPM_OUTPUT, GPF_AF0, GPT_PP},
     {LED2, GPM_OUTPUT, GPF_AF0, GPT_PP},

     {KEY, GPM_INPUT},

     NULL
};

gpio_setup(ui_pins);

Подтяжки добавить по аналогии с остальным.



Я так понимаю, это всё для отдельного вход/выхода? Выходит громоздко. К тому же в хидерах стандартной библиотеки многое уже объявлено и определено, зачем придумывать целиком свой код?
aaarrr
Цитата(=L.A.= @ Nov 29 2015, 11:18) *
Я так понимаю, это всё для отдельного вход/выхода? Выходит громоздко. К тому же в хидерах стандартной библиотеки многое уже объявлено и определено, зачем придумывать целиком свой код?

Да, для каждого отдельного пина, затем они собираются в группы.
Громоздко? Не вижу смысла в современных реалиях экономить флеш, это не ATtiny.
Стандартную библиотеку не использую и никому не рекомендую.
Herz
Цитата(data_stack @ Nov 27 2015, 13:48) *
Идет процесс бурного изучения, возникает много вопросов, все вопросы мелкие, плодить темы не хочется

Однако потрудитесь назвать тему более информативно, иначе она будет удалена.
Но если вопросов слишком много, то не лучше ли обратиться к литературе?
slavokhire5
Я за стандартные либы. Да, местами криво. Да, жрут. Но представьте, что вам достался чужой глючный проект с десятками тысяч строк кода, и все либы - велосипед...
aaarrr
Цитата(slavokhire5 @ Nov 29 2015, 18:35) *
Но представьте, что вам достался чужой глючный проект с десятками тысяч строк кода, и все либы - велосипед...

Если уж прямо десятки тысяч строк, то и доля "либ" в них будет невелика. И Вы не допускаете мысли, что "велосипед" может быть построен аккуратно и грамотно, в отличие от?
slavokhire5
Если написать свои библиотеки на всю переферию какого-то жирного стм32, то кода там будет ого-го. Велосипед может быть весьма хорош. А может и не быть. Допускаю переписывание части библиотек, только если не будет хватать производительности.
aaarrr
Вся ли периферия "жирного" STM32 используется в каждом изделии? Да и вообще она большей частью примитивна, за исключением USB, EMAC и, возможно, чего-нибудь еще. Зато посмотрите, сколько на этом форуме тем типа "стандартная USB CDC либа не отправляет пакеты с размером, кратным 64 байтам"! Куда уж тут говорить о производительности.
jcxz
Цитата(slavokhire5 @ Nov 29 2015, 21:35) *
Я за стандартные либы. Да, местами криво. Да, жрут. Но представьте, что вам достался чужой глючный проект с десятками тысяч строк кода, и все либы - велосипед...

Какие либы на десятки тысяч строк? Для периферии??? Чушь несёте.
Что там можно писать десятками тысяч строк? Вы мануал на периферию хоть раз открывали или только "либами" пользуетесь?
Работа практически с любой широкораспространённой периферией типа UART-ов, SPI, I2C, таймеров ... - десятки строк аппаратно-зависимого кода.
USB, Ethernet и некоторая другая - чуть побольше (к примеру в моём текущем проекте на LPC43xx в драйвере USB-device уровень работы с железом чуть больше 500строк).

PS: Ну если только "кодом" называть все дефайны определяющие регистры периферии и битовые поля в них, только тогда можно раздуть на десятки тысяч строк. Только это не код.
data_stack
Цитата(Herz @ Nov 29 2015, 10:48) *
Однако потрудитесь назвать тему более информативно, иначе она будет удалена.
Но если вопросов слишком много, то не лучше ли обратиться к литературе?


offtop mode = true
На вашем форуме не хватает такой темы, где можно сгрузить мелкие вопросы по STM32, работе с отладчиком, вопросам по оформлению кода. Этого нет в книгах. Я задал несколько не связанных вопросов, получил на них ответы, не понимаю что здесь необычного. Поверьте нигде больше я бы не нашел на них ответ. А вот нытье по поводу выбора инструментария и прочий флуд не нужен, дайте мне полномочия только на эту тему, я буду следить и чистить только ее, все будут довольны. Если я не прав, можно удалять тему, буду на каждый вопрос создавать отдельную тему.
offtop mode = false


=L.A.=
Еще небольшой вопросец. Есть такая штука "SysTick_Handler". Я проштудировал доки и не нашел ответа, какой таймер использует эта функция ? Это один из периферийных ( TIM1 ... TIM17 ) или дополнительный таймер из ядра?
Сергей Борщ
Цитата(=L.A.= @ Dec 14 2015, 09:46) *
SysTick timer и использует. Из ядра. И его описание, соответственно, в описании ядра. Кстати, и вектор SysTick_Handler находится среди векторов ядра (всяких xxxAbort_Handler и т.п.).
=L.A.=
Цитата(Сергей Борщ @ Dec 14 2015, 09:58) *
SysTick timer и использует. Из ядра. И его описание, соответственно, в описании ядра. Кстати, и вектор SysTick_Handler находится среди векторов ядра (всяких xxxAbort_Handler и т.п.).
.

Спасибо. Главное для меня, что это отдельный от всех остальных таймер и если включено SysTick, то другие таймеры можно использовать. В доках на ядро F0 о таймере SysTick написано крайне мало. Даже Гугль ничего не находит sm.gif

А вектор ( приоритет SysTick ) попробую переставить пониже в файле startup_stm32f051.s Вдруг подействует?
Сергей Борщ
Цитата(=L.A.= @ Dec 14 2015, 10:51) *
В доках на ядро F0 о таймере SysTick написано крайне мало. Даже Гугль ничего не находит sm.gif

PM0215, "STM32F0xxx Cortex-M0 programming manual", раздел 4.4, 4 страницы с картинками.
Гугль. Результатов: примерно 18 600. Попробуйте сменить интернет.

Цитата(=L.A.= @ Dec 14 2015, 10:51) *
А вектор ( приоритет SysTick ) попробую переставить пониже в файле startup_stm32f051.s Вдруг подействует?
В файле вы можете перставлять что угодно, а в кристалле вектора прибиты к своим адресам гвоздями. Про приоритеты написано в том же описании в разделе 2.2, этот раздел аж из 6 страниц.
=L.A.=
Цитата(Сергей Борщ @ Dec 14 2015, 11:38) *
PM0215, "STM32F0xxx Cortex-M0 programming manual", раздел 4.4, 4 страницы с картинками.


Эту доку читал, но интересовался не описанием регистров, а связью SysTick c другими таймерами, о чем в
в Programming manual не написали. Можно сравнить адреса регистров, но надо обратить специальное внимание, что я уже сделал.

Теперь добавил в программу инициализацию TIM6 и установку прерывания по этому таймеру. ИАР выдает ошибку
Error while running Linker :

Error[Li005]: no definition for "NVIC_Init" [referenced from C:\ARM\2_PROJ\1Prb32F0\EWARMv5\Release\Obj\01PrbDsc.o]

Что ему не нравится?

Код
*
//#########################    
// /* TIM6 is used to  */
//
  NVIC_InitTypeDef            NVIC_InitStructure;
  TIM_TimeBaseInitTypeDef     TIM_TimeBaseStructure;
//
/* TIMER clock enable */
//
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6 , ENABLE);

/* Enable the TIMER global Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//
  NVIC_Init(&NVIC_InitStructure);
//
  TIM_TimeBaseStructure.TIM_Period = 5000;
  TIM_TimeBaseStructure.TIM_Prescaler = 32;
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//
  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
//
/* TIM IT enable */
  TIM_ITConfig(TIM6, TIM_IT_Update , ENABLE);
//
/* TIM enable counter */
//
   TIM_Cmd(TIM6, ENABLE);    
//-------
=L.A.=
Цитата(=L.A.= @ Dec 14 2015, 15:53) *
Error while running Linker :

Error[Li005]: no definition for "NVIC_Init" [referenced from C:\ARM\2_PROJ\1Prb32F0\EWARMv5\Release\Obj\01PrbDsc.o]


Нашел. Оказалось, что функция void NVIC_Init(....) спрятана в файле
stm32f0xx_misc.c

Цитата(Сергей Борщ @ Dec 14 2015, 11:38) *
В файле вы можете перставлять что угодно, а в кристалле вектора прибиты к своим адресам гвоздями. Про приоритеты написано в том же описании в разделе 2.2, этот раздел аж из 6 страниц.
.

Насчет "прибитых гвоздями" векторов. Прочитал доку. Вижу таблицу с непонятными словами "settable". Что бы это значило? sm.gif Гугля спросить или интернет поменять?


aaarrr
Цитата(=L.A.= @ Dec 14 2015, 18:01) *
Что бы это значило?

Что приоритет можно установить, что же еще? Позиция вектора от этого не изменится.
Ruslan1
Вопрос по определению USB подключения на STM32F0:

Обязательно ли нужно в STM32F0 (STM32F070) для работы с USB задействовать какой-то вывод МК кроме DP,DM для определения факта подключения (наличия VBUS) и начала инициализации USB соединения? Отдельный вывод под контроль VBUS очень не хочется, ножек не хватает.

Для DFU программатора ему это не нужно: только DP и DM, внешний pull-up резистор на DP не нужен- есть свой управляемый внутри МК.
A как для обычной работы, делать периодическое сканирование? USB планирую использовать просто как консоль, то есть пауза от подключения до детектирования может быть хоть 10 секунд, это не проблема. Но жалко много ресурсов МК тратить на сканирование интерфейса, который обычно выключен.
Много ли вычислительных ресурсов периодическое сканирование на предмет наличия USB подключения занимает?
=L.A.=
STM32F0xxx

Приоритет SysTick устанавливается программно. Тактовая частота - как в примерах: HSE (HSI) на 8 МГц, умножитель на 6, то есть имеем 48 МГц тактирование ядра.

Код
//**************************************************************************//
//  Установка периода SysTick  5 мс  
//==========================================================================//
    SysTick_Config(SystemCoreClock/200);
//
    NVIC_SetPriority(SysTick_IRQn, 2);  // IRQ Priority = 2

//
//
.....................
//
//**************************************************************************//
//  IRQ  SysTickTimer  с периодом 5 мс
//==========================================================================//
void SysTick_Handler(void)
{
//
....trtrtrtrtrtrtrtrtrtrtr....
//
}
Сергей Борщ
Цитата(=L.A.= @ Jan 11 2016, 20:16) *
Приоритет SysTick устанавливается программно.
Да. Это влияет на адрес вектора? Или вы о чем-то другом хотели сказать?
esaulenka
Цитата(Ruslan1 @ Dec 15 2015, 16:35) *
Вопрос по определению USB подключения на STM32F0:
Обязательно ли нужно в STM32F0 (STM32F070) для работы с USB задействовать какой-то вывод МК кроме DP,DM для определения факта подключения (наличия VBUS) и начала инициализации USB соединения? Отдельный вывод под контроль VBUS очень не хочется, ножек не хватает.


Про F0 ничего не скажу, не работал.
А вот в USB OTG более "толстых" камней есть чудная грабля - VBUS им обязателен. При низком уровне на этой ноге соединение само собой гасится, при появлении высокого - восстанавливается.
Я столкнулся с этим на F105, на ногу VBUS удобно лёг передатчик UART'а. Пока по UART'у ничего не передавалось, всё работало. Зато сразу после написания драйвера на этот UART начались произвольные пропадания данных в USB. Ремап ножек там очень убогий, пришлось много резать, к сожалению.

Собственно, предложений два:
- проверить (демо-плата есть?), что низкий уровень на отключенной ремапом ножке не приводит к фатальным последствиям
- инициализировать один раз, и потом просто сидеть и ждать прерывания от хоста. Правда, это не очень красиво, если устройство супер-малопотребляющее.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.