Использование стандартных периферийных библиотек в IAR.

Сначала хотел просто выложить шаблоны проектов для iar, но потом решил что кроме этого стоит привести пример написания программы типа «Hello светодиод» с ее использованием. И чем использование библиотек лучше засовывания битов в регистры в ручную.
Шаблоны используются мои, переделанные из идущих в комплекте. Переделывать пришлось т.к. фирменные у меня почему-то не открывались без кучи ошибок.
main
Сначала нужно установить шаблон. Для этого содержимое архива нужно распаковать по следующему пути:
1. Для х32 систем — C:\\Program Files\\IAR Systems\\Embedded Workbench 6.0 Evaluation\\stm8\\config\\template\\project
2. Для х64 систем — C:\\Program Files (x86)\\IAR Systems\\Embedded Workbench 6.0 Evaluation\\stm8\\config\\template\\project
Это если при установки использовался стандартный путь. Файлы readme можно удалить:) Там моя же подсказка мне, куда распаковывать все это. Шаблоны будут нормально работать только в версии iar 1.30!
Теперь можно запустить iar и создать новый проект. Должны будут появиться новые варианты проектов, как на заглавном рисунке.

1. Создание проекта
Создаем новый проект для stm8l как и обычный, после чего его стоит сразу откомпилировать (F7). В результате получим одно предупреждение, на него не обращаем внимание. Первую компиляцию я делаю, что бы используемые файлы
были добавлены к main в окне Workspace. Можно конечно сразу настроить проект под нужный тип контроллера, отредактировав файлы в папке inc окна Workspace.

#include "stm8l15x.h"
// !!! Edit stm8l15x_conf.h to enable peripheral header
// !!! Test STM8L15X_MD in stm8l15x.h to the target STM8L device used
// Current selected:
// STM8L15x devices are STM8L151C4, STM8L151C6, STM8L152C4,
// STM8L152C6, STM8L151K4, STM8L151K6, STM8L152K4, STM8L152K6, STM8L151G4,
// STM8L151G6, STM8L152G4 and STM8L152G6
int main( void )
{

}

По умолчанию проект создается для STM8L152C6, той что стоит в дискавери. Тип м/с изменяется в свойствах проекта. Также может понадобится изменить в stm8l15x.h семейство. Выбор семейства делается раскоментированием нужной строчки:

//#define STM8L15X_LD      /*!< STM8L15X_LD: STM8L15x Low density devices */
#define STM8L15X_MD      /*!< STM8L15X_MD: STM8L15x Medium density devices */
//#define STM8L15X_MDP     /*!< STM8L15X_MDP: STM8L15x Medium density plus devices */
//#define STM8L15X_HD      /*!< STM8L15X_HD: STM8L15x/16x High density devices */

Какие именно контроллеры входят в то или иное семейство написано в том же файле.
Так как по умолчанию вся периферия у серии L отключена, то и в библиотеках они тоже отключены. Нужные модули включаются в файле stm8l15x_conf.h.
Для отладке в железе так же нужно выбрать в свойствах проекта, в разделе Debugger тип используемого отладчика.
2. Написание «Hello светодиод»
Мигать будем сразу по взрослому, через таймер и прерывания:) Для создания этого шедевра понадобятся библиотеки портов ввода/вывода, таймера и прерывания. Включаем нужные библиотеки в stm8l15x_conf.h (остальные остаются отключенные):

#include "stm8l15x_clk.h"
#include "stm8l15x_gpio.h"
#include "stm8l15x_itc.h"
#include "stm8l15x_tim2.h"
Первая используется для включения тактирования периферии, вторая порты, третья прерывания и последняя таймер 2.
В основной программе настроим работу кристалла на максимальную частоту в 16Мгц:
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);

Порт PC7 на вывод:
GPIO_Init(GPIOC,GPIO_Pin_7,GPIO_Mode_Out_PP_High_Fast);

Включим таймер 2 и настроим на частоту 2Гц, попутно разрешив прерывания от него и включим:

  // Timer 2, F=2Hz
  // ARR=Fsck/Prescale/Fuser
  // ARR=16 000 000 / 128 / 2 = 62500
  CLK_PeripheralClockConfig(CLK_Peripheral_TIM2,ENABLE);
  TIM2_TimeBaseInit(TIM2_Prescaler_128,TIM2_CounterMode_Up,62500);
  // Interrupt
  TIM2_ITConfig(TIM2_IT_Update,ENABLE);
  // Start TIM2
  TIM2_Cmd(ENABLE);

Теперь сделаем обработчик прерывания, в котором будет сбрасываться флаг вызванного события и заодно изменять состояние светодиода:
// Timer 2 interrupt
INTERRUPT_HANDLER(TIM2_handler,TIM2_UPD_OVF_TRG_BRK_IRQn)
{
  if (TIM2_GetFlagStatus(TIM2_FLAG_Update))
  {
    GPIO_ToggleBits(GPIOC,GPIO_Pin_7);
    TIM2_ClearFlag(TIM2_FLAG_Update);
  }
}

Остается разрешить прерывания и программа готова:

#include "stm8l15x.h"
void main( void )
{
  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
  GPIO_Init(GPIOC,GPIO_Pin_7,GPIO_Mode_Out_PP_High_Fast);
  // Timer 2, F=2Hz
  // ARR=Fsck/Prescale/Fuser
  // ARR=16 000 000 / 128 / 2 = 62500
  CLK_PeripheralClockConfig(CLK_Peripheral_TIM2,ENABLE);
  TIM2_TimeBaseInit(TIM2_Prescaler_128,TIM2_CounterMode_Up,62500);
  // Interrupt
  TIM2_ITConfig(TIM2_IT_Update,ENABLE);
  // Start TIM2
  TIM2_Cmd(ENABLE);  
  __enable_interrupt();
  while(1);
}
// Timer 2 interrupt
INTERRUPT_HANDLER(TIM2_handler,TIM2_UPD_OVF_TRG_BRK_IRQn)
{
  if (TIM2_GetFlagStatus(TIM2_FLAG_Update))
  {
    GPIO_ToggleBits(GPIOC,GPIO_Pin_7);
    TIM2_ClearFlag(TIM2_FLAG_Update);
  }
}


3. Разница при написании программы через библиотеки и напрямую.
При создании этого чуда не пришлось ни разу заглядывать в мануалы и изучать где какие биты и в каких регистрах надо изменять (а многие из них разбросаны по регистрам весьма причудливо:). Все возможные значения есть в соответствующих заголовочных файлах. Так же в архиве с библиотеками (в файле stm8l15x-16x_stdperiph_lib_um.chm) идет подробнейший хелп с примерами по использованию всего что понапихано в кристалл. Так же при переносе на другой кристалл изменения будут минимальнейшие. Еще из приятных плюшек — автоматическая настройка временных параметров периферии. Например при настройки I2C в ините достаточно просто указать желаемую частоту шины и коэффициенты будут рассчитаны автоматически при выполнении программы в зависимости от текущего состояния.
Основных недостатков три. Увеличение размера и уменьшение скорости работы программы понятно будут. Но очень не значительные. Гораздо неприятней не полная совместимость библиотек между разными типами контроллеров. Причем зачем так сделано мне совсем не понятно, к примеру настройка порта С на выход для stm8L и stm8S:
GPIO_Init(GPIOC,GPIO_Pin_7,GPIO_Mode_Out_PP_High_Fast); — STM8L
GPIO_Init(GPIOC,GPIO_PIN_7,GPIO_MODE_OUT_PP_HIGH_FAST); — STM8S
Все идентично, кроме регистров дефайнов.
  • +6
  • 09 августа 2011, 14:15
  • PRC
  • 1
Файлы в топике: STM8L Template.zip

Комментарии (83)

RSS свернуть / развернуть
Т.е. периферийная библиотека прикручена к шаблону?
0
Да. Без нее и сам иар вполне годный проект создает, достаточно только файл описания микросхемы приделать.
0
В своих примерчиках я не зря делал всю возню через регистры. С библиотекой оно конечно круто и модно, но когда понадобится понять, почему не работает (или просто разобраться как происходит настройка), то можно получить неслабый разрыв мозга, если не знаешь, как устроена система.

Стоит хотя-бы посмотреть на народ на форуме, который дико, яростно требует библиотеки под все что угодно (начиная со светодиода и заканчивая какой-нибудь экзотикой), а когда его обламывают со словами «напиши сам, там-же просто» — начинает срать кирпичами, ибо нифига не понимает, что ему писать и куда.

В общем, ИМХО, для обучения надо показывать все «как есть», т.е. с минимальной абстракцией от железки.

С другой стороны, если надо написать программу «еще вчера», то библиотека выручает. Ибо довольно сложно ошибиться, и скорость написания возрастает в разы. Память? Позвольте, у самого топорного МК, который у меня есть — STM8S103F3 — 8 Килобайт этого вашего флеша. А учитывая его унылую периферию и маленькое количество выводов, написать что-то эпичное под него вряд-ли выйдет даже у самого упоротого быдлокодера.

Библиотечные функции и работу через регистры можно смешивать (но не встряхивать!). Правда тогда придется держать в голове все функции вместе с тем, что они делают. Иначе можно лишний раз поставить какой-то флаг или забыть выключить кому-нибудь clock.

Что касается меня, то я перенес на STM8 свою технику методику привычку (во!), которая появилась давным-давно, когда был паскаль и тиньки.
Суть в том, чтобы писать, делая ставку на сокращение времени написания, но в то-же время стараться не транжирить память (в тиньках её было мало). Библиотечные функции в паскале видимо делались по принципу «одна функция на все случаи жизни» — поэтому занимали сотни памяти. Если программа не влезала в тиньку, то я начинал заниматься жестокой оптимизацией, следуя заветам ДиХальта — «не отдавать без боя ни один байт» :)

Здесь памяти много, поэтому можно расслабиться. Единственное, где придется оптимизировать — места критичные ко времени выполнения, или куски кода, живущие в оперативке (по причине её скудности).

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

Я кончил.

P.S. Собственно, зачем заходил: есть мнение, что при использовании библиотеки для GPIO, код получается жирным и каким-то неадекватным. Не замечал такого?
+1
Нет, идет только дополнительный вызов подпрограммы. Кроме инициализации конечно. У S серии вроде идет еще какая-то проверка, не знаю. Я с ними еще не игрался. Кстати в стм32 при максимальной оптимизации эти вызовы сокращаются до такого же ручного засыла байта в регистр.
По поводу знания регистров и их назначения. Не вижу абсолютно никакого смысла в запоминании этого дикого кол-ва регистров и битов в них. Одна маска будильника чего стоит — каждый бит маски в отдельном регистре. Ее настройка типа alarm.RTC_AlarmMask=RTC_AlarmMask_DateWeekDay; мне нравится гораздо больше. Биты стоит смотреть только, если при отладке что-то идет не так. Именно на время отладки.
С стм8 думаю стоит отходить уже от написания программ в стиле авр, у которого всего 66 регистров (это у популярной меги16) из которых не меньше половины или вообще на части не делятся (типа счетчиков и указателей) или деление прозрачно (те же porta, pinc и подобные). Иначе написание программы превратится в постоянное листание даташита в поисках очередного нужного бита и регистра.
0
При создании этого чуда не пришлось ни разу заглядывать в мануалы и изучать где какие биты и в каких регистрах надо изменять

Вы считаете, что это хорошо?
0
  • avatar
  • _YS_
  • 10 августа 2011, 19:22
Да, разумеется.
0
Очень хорошо.
Обратите внимание на примеры которые есть в интернете. Если в них используют напрямую запись в регистры, то обычно эти примеры дальше мигания светодиодом не идут. И наглядность этих примеров обычно весьма низкая. То же переключение тактирования в виде:

CLK_ECKR_bit.HSEEN = 1;            // Вкючаем HSE
CLK_SWCR_bit.SWEN=1;               // Разрешаем переключение источника тактовой частоты
while(CLK_ECKR_bit.HSERDY != 1) {} //Ждем готовности источника тактирования
CLK_CKDIVR = 0;                    // Предделитель равен нулю
CLK_SWR = 0xB4;                    // Выбираем HSE источником тактовой частоты
while (CLK_SWCR_bit.SWIF != 1){}   // Ждем готовности переключения 

Выглядит на редкость понятно:) Особенно магическая команда CLK_SWR = 0xB4; Сравните с:

  CLK_HSEConfig(CLK_HSE_ON);
  CLK_SYSCLKSourceSwitchCmd(ENABLE);
  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
  CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSE);

Все понятно и без всяких комментариев.
Кстати этого 0хВ4 нет ни в одном даташите, а есть «0x04: HSE selected as system clock source». Кто-то ошибся или еще что, но все стабильно копируют этот кусок кода ни разу не думая, что именно они копируют.
+1
Только вот при использовании библиотек нифига непонятно, как оно все работает внутри. Там что под x86, что под ARM, что под PIC — все едино. Это либо для убогих, либо для тех, кто ну очень торопится (завтра сдавать проект, типа). Работать, конечно, будет, но вот только многое может быть упущено.

С библиотекой оно конечно круто и модно, но когда понадобится понять, почему не работает (или просто разобраться как происходит настройка), то можно получить неслабый разрыв мозга, если не знаешь, как устроена система.
0
А зачем это знать? В общих чертах это и так известно, а подробности при необходимости доставят сорцы или даташит.
Тебе же не нужны исходники VCL и винды, а также полная карта памяти этой самой винды, чтобы накропать прожку для связи с твоим мегадевайсом.
0
Я уже приводил пример с CLK_SWR = 0xB4; что нет такого значения. Однако он стабильно появляется из примера в пример. Что явно свидетельствует о глубоком понимании копируемого кода.
Настоящие труЪ программисты могут писать хоть на ассемблере, только увидим ли мы результаты их титанического труда? И смысл в этом, если все тоже самое я сделаю в 100 раз быстрее и легко переносимо с проца на проц?
0
А зачем это знать?

Чтобы писать оптимальный код и избегать волшебных неожиданностей.

Что явно свидетельствует о глубоком понимании копируемого кода.

Ключевое слово — копируемого. Я, например, никогда не копирую примеры на этапе освоения. Я читаю документацию и заново переписываю их руками. И так пока не дойдет.
0
Чтобы писать оптимальный код и избегать волшебных неожиданностей
В большинстве случаев для достижения обоих задач как раз таки нужно использовать готовые библиотеки. Люди из ST луда лучше знают, как правильно сменить частоту камня.
Я, например, никогда не копирую примеры на этапе освоения. Я читаю документацию и заново переписываю их руками. И так пока не дойдет.
Это по большей части тоже не нужно. Если программа работает (и работает правильно) — значит она правильная. А задача программиста — написать правильную программу при минимальных затратах времени. Поэтому в целом знать в общем, как работает процессор желательно, но знать регистры и систему команд каждого МК — излишне.
Собственно, я без проблем накатал функцию на ассемблере x51 руководствуясь тока небольшим курсом по основам его архитектуры (точнее, не столь уж небольшим — там было дофига ненужной воды, а крупицы для окончательного понимания какой-то тонкости приходилось искать по всему курсу) и списком команд. Но куда лучше было бы, если бы тупой и кривой микропаскаль компилировал код без ошибок, не вынуждая меня переписывать пол-ртос на убогом инлайновом ассемблере. Кончилось это переходом на Keil и написанием почти всего проекта на С (кроме функции DecToBcd — вариант на С кейл как-то странно скомпилил, даже не воспользовавшись аппаратным делителем/умножителем, хотя он работал и по времени укладывался, так что переписал я его just for fun).
0
Это по большей части тоже не нужно. ...

just for fun

Вот он, ответ. :-)
0
Вот только не надо выставлять то, что just for fun, как единственно правильный путь.
В определенных пределах с девайсом, разумеется, ознакомиться надо. Но и копать глубже необходимого тоже совершенно незачем. Понадобится — тогда придется закопаться, да.

Кстати, подобные закидоны имеют свойство проходить с возрастом. Потом вспоминаешь о них и усмехаешься)
0
Так я же говорил — если код надо сдавать завтра, а уже два часа пополуночи, то, ессно, идти на прицип глупо. А если есть время, отчего бы нет?
0
Тащемта, это почти всегда глупо. Давнее наблюдение из любительского геймдева. Те, кто начал делать свою игру с написания своего движка — в лучшем случае только движок и сделают. На игру практически никогда у них уже не хватает ни времени, ни энтузиазма. А вот игры на готовом движке периодически выкладываются, и среди них попадаются годные экземпляры.

Хотя, с другой стороны, движок — это все-таки от 10к строк кода, и игра столько же. Радиолюбители редко юзают МК, куда столько влезет) Но энтузиазм без быстрого результата таки имеет свойство затухать, оставляя недоделанные проекты.
0
А если я делаю девайс для себя и ресурсов проца при использовании библиотек мне хватает за глаза? Зачем упираться загоняя «волшебные» числа в регистры, выискивая имя каждого в даташите? И какой результат я получу на выходе? Программу на пару килобайт меньше, которую нельзя перенести на другое семейство без глобального перелопачивания всего кода, зато с сомнительным удовольствием в виде поисков, а то ли значения я записал в этот регистр? А сколько радости будет, когда через год нужно будет внести небольшие изменения.
Я уже писал посмотрите на примеры выложенные тут. С прямым обращением к регистрам идет только общая теория, что проц может работать так или так. Причем иногда с ошибками. И почему то никто про эту ошибку не написал. Все примеры программ, делающих хоть что-то более-менее вменяемое написаны с использованием библиотек.
Желание разобраться с назначением каждого бита в каждом регистре конечно похвальное, но использовать его при написании реальной программы мне кажется перебором. Хотя всегда будут желающие писать под ту же винду на ассемблере. Но их всегда будет меньшинство.
0
Угу. И запускать, например, преобразование АЦП как-то так:

ADC_StartSingleConversionRightNowWithInterruptEnabled();

Вместо простого и лаконичного

ADCSRA|=(1<<ADSC) | (1<<ADIE);

xDD
0
Да, разумеется. В первом случае сразу видно, что происходит. Во втором — какая-то математика. Без курения даташита и не узнаешь, что это математическое выражение на самом деле запускает преобразование.
А код в листинге наверняка будет идентичным, потому как любой мало-мальски вменяемый программист сообразит, что такую функцию следует делать инлайновой.
0
Без курения даташита и не узнаешь, что это математическое выражение на самом деле запускает преобразование.

Без курения даташита к МК лучше вообще не подходить. Или покупать ардуйню какую-нибудь, как гуманитарии. :-)

Любому же, кто читал даташит, понятно, что это

ADc Control and Status Register A = ADc Start Conversion + ADc Interrupt Enable

А использовать библиотеки можно тогда, когда уже наизусть знаешь, как они устроены. Ну или если надо очень быстро. Как вариант — если экспериментатор гуманитарий. :-DDD
0
Чудненько, может быстренько найдете в даташите куда надо записывать маску будильника для rtc?
0
может быстренько найдете в даташите

Быстренько нашел. Причем дольше всего искал сам даташит. :-D

Даже беглого взгляда на недодаташит достаточно, чтобы понять, что это, скорее всего, RTC_ALRMARx (страница 41). Reference manual подтверждает это — стр. 410.

RTFM, гы-гы. xD
0
Ах да, подробное описание интересующих регистров — стр. 430.
0
Точнее RTC_ALRMAR1-RTC_ALRMAR4. По одному биту в каждом.
0
Дыг я ж написал — RTC_ALRMARx
0
А теперь по названию регистра RTC_ALRMAR2 бит MSK2 скажите что он делает.
0
Точнее RTC_ALRMAR1-RTC_ALRMAR4. По одному биту в каждом.
Какие упоротые у них разработчики)
Reference manual подтверждает это — стр. 410.
Ах да, подробное описание интересующих регистров — стр. 430.
И сколько там в сумме страниц, сколько ты времени искал, и главное зачем это?
Алсо, если не для этого регистра, то для какого-нить другого (или какого-нить действия) запросто может быть какое-нить малозаметное, но важное примечание в совершенно другом разделе, которое в библиотеке учтено, а заметить его без полного чтения даташита — фиг.
0
А теперь по названию регистра RTC_ALRMAR2 бит MSK2 скажите что он делает.

Зачем гадать по названию? Есть же Reference manual! :-)

стр.430:

24.6.23 Alarm A register 2 (RTC_ALRMAR2)

Bit 7 MSK2: Alarm A minutes mask
0: Alarm A set if the minutes match.
1: Minutes don’t care in alarm A comparison.


И сколько там в сумме страниц, сколько ты времени искал

566 страниц, искал минуты две. Есть такая штука — оглвление называется.

малозаметное, но важное примечание в совершенно другом разделе,

Обычно дается ссылка.

Например:

Note: This register can not be written when RTC_ISR1/RECALPF is 1 (see Section: Recalibration
on-the-fly).
This register is write protected. The write access procedure is described in Section: RTC
register write protection on page 411.
0
Без даташита, по аналогии с ADc Control and Status Register A = ADc Start Conversion + ADc Interrupt Enable
0
Я отрицал библиотеки, а не даташит. ;-) Даташит же — наше все!
0
А не надоест каждый раз выискивать каждый такой бит в даташите? Запомнить их всех никакой памяти не хватит:) Это сейчас нужно было значение одного бита найти, да еще по свежим воспоминаниям. А когда придется разбираться в чей-то чужой программе и не на один экран размером. Или переносить программу с stm8l на stm8s.
0
Когда надоест — можно переходить на библиотеки. :-)
0
Я думаю будет достаточно первого, относительно, крупного проекта.
0
Не отрицаю. В крупных проектах это все оправдано.
0
Даташит штука полезная, но меня никоим местом не интересует, как именно на нем запускается преобразование, когда я изучаю по коду алгоритм работы какого-нить там спектроанализатора.
Честно говоря, меня это не интересует даже когда я программу пишу, до тех пор, пока я без этого могу обойтись.
И вместо раздела даташита с описанием регистров меня прекрасно устроит хелп на библиотеку, где описано, как запстить преобразование и как настроить его параметры на нужные
А с особенностями фунциклирования железа я неплохо ознакомлюсь, разбирая дизасм прошивки от какого-нить очередного жадного на сорцы автора. Но даже для этого полное скуривание ДШ не требуется.
0
Но даже для этого полное скуривание ДШ не требуется.

Так полное скуривание ДШ почти никогда не требуется. Курить стоит только тот модуль, с которым собираешься работать.
0
Не путайте стм8 и авр. У них кол-во регистров весьма сильно различается.
Тем более это не так делается:)

// Собственно настройка
  CLK_PeripheralClockConfig(CLK_Peripheral_ADC1,ENABLE);
  ADC_VrefintCmd(ENABLE);
  ADC_Init(ADC1,ADC_ConversionMode_Single,ADC_Resolution_12Bit,ADC_Prescaler_2);
  ADC_Cmd(ADC1, ENABLE);
// Само измерение
  ADC_ChannelCmd(ADC1,ADC_Channel_14,ENABLE);
  ADC_SoftwareStartConv(ADC1);
  while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
  Vout=ADC_GetConversionValue(ADC1);

И для более точного измерения рекомендуют применять некоторые дополнительные методы. У меня получается точность, около 0.02-0.03В с использованием только программных средств.
Можете привести этот же пример только с использованием регистров и сравним где получилось наглядней.
0
#pragma holywar=off

У каждого свой метод, товарищи. :-)
0
Выскажусь против монструозных библиотечных функций, пример настройки таймера 17 и прерывания по переполнению(правда для STM32, но в STM8 думаю будет похоже), с библиотеками:

#include "stm32f10x.h" 


/* Private function prototypes -----------------------------------------------*/
void Delay(void);
void RCC_Configuration(void);
void NVIC_Configuration(void);
void GPIO_Configuration(void);
void TIM_Configuration(void);
void TIM2_IRQHandler(void);

/*----------------------------------------------------------------------------
Enable periferial clocks
*----------------------------------------------------------------------------*/
void RCC_Configuration(void)
{
  /* Enable GPIO_LED clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_LED, ENABLE);
  
  /* Enable TIM2 clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}

/*----------------------------------------------------------------------------
GPIO LED pins setting
*----------------------------------------------------------------------------*/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Configure GPIO_LED pin 8, GPIO_LED pin 9 as output push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIO_LED, &GPIO_InitStructure);
  GPIO_ResetBits(GPIO_LED, GPIO_Pin_8);
  GPIO_ResetBits(GPIO_LED, GPIO_Pin_9);
}

/*----------------------------------------------------------------------------
TIM2 NVIC enable Interrupt
*----------------------------------------------------------------------------*/
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
  
  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* Enable the TIM2 gloabal Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  
  NVIC_Init(&NVIC_InitStructure);
}
/*----------------------------------------------------------------------------
TIM2 Configuration
*----------------------------------------------------------------------------*/
void TIM_Configuration(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 24000;
  TIM_TimeBaseStructure.TIM_Prescaler = 1000;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  
  TIM_ARRPreloadConfig(TIM2, ENABLE);
  
  /* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);
  TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
}

void TIM2_IRQHandler(void)
{  
  /* Clear TIM2 update interrupt */
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}

int main(void)
{
  RCC_Configuration();
  GPIO_Configuration();
  TIM_Configuration();
  NVIC_Configuration();
  
  while(1)
  {    
  }
}


И тоже самое без SWLib:

#include "stm32f10x.h"
#include "stm32f10x_it.h"

volatile unsigned long d;
extern volatile uint16_t test_count;

void Init(void)
{
  //Enabling clock for GPIOC
  RCC->APB2ENR|=RCC_APB2ENR_IOPCEN;
    
  //Leds
  GPIOC->CRH = 0x00000011;  //PORTC.8,9 Output Push-pull
    
  GPIOC->BSRR=GPIO_BSRR_BR8;    //set 0 
  GPIOC->BSRR=GPIO_BSRR_BR9;    //set 0 
  
  //Timer 17
  RCC->APB2ENR |= RCC_APB2ENR_TIM17EN;
  TIM17->PSC = 1000 - 1;                 //Timer prescaler 24000Hz
  TIM17->ARR = 24 - 1;                   //Reload value = 24 "tics"  - 1ms
  TIM17->DIER |= TIM_DIER_UIE;
  TIM17->CR1 = TIM_CR1_CEN | TIM_CR1_ARPE; //Enable timer and autoreload
  
  NVIC_SetPriority(TIM1_TRG_COM_TIM17_IRQn, 15); //Set priority TIM17 IRQ
  NVIC_EnableIRQ(TIM1_TRG_COM_TIM17_IRQn); //Enable TIM17 IRQ
  
}


void main(void)
{ 
  Init();
  
  while (1)
  {     
  }
}


Как по мне без библиотек кода намного меньше и он понятней.
+1
Для стм8 не катит:)

// GPIOB.4 и GPIOC.4
  GPIO_Init(GPIOB,GPIO_Pin_4,GPIO_Mode_Out_PP_High_Fast);
  GPIO_Init(GPIOC,GPIO_Pin_4,GPIO_Mode_Out_PP_High_Fast);
// Timer 2
// ARR=Fsck/Prescale/Fuser
// ARR=20 000 000 / 32 / 50 = 12500
  CLK_PeripheralClockConfig(CLK_Peripheral_TIM2,ENABLE);
  TIM2_TimeBaseInit(TIM2_Prescaler_32,TIM2_CounterMode_Up,12500);
  // IER
  TIM2_ITConfig(TIM2_IT_Update,ENABLE);
  // Start TIM1
  TIM2_Cmd(ENABLE);

Желающие могут перевести ее в версию с ручным распихиванием битов, но меньше и наглядней она точно не будет:) Особенно таймер.
0
Короче, но не понятней.
К тому же, завелись магические числа. Ну и не вижу установки скорости гпио на 50мгц.
Хотя инициализация через структурки выглядит и правда странновато. Интересно, почему они сделали именно так?
0
Ну видимо как кому, мне понятней. Никакой магии :) Запись типа:

GPIOB->CRL = 0x00000011;  //PORTB.0,1 Push-pull output 10MHz
GPIOB->CRH = 0x00000010;  //PORTB.9 Push-pull output 10MHz


назначит выходы со скоростью 10 МГц, а вот так 50Мгц:


GPIOB->CRL = 0x00000033;  //PORTB.0,1 Push-pull output 50MHz
GPIOB->CRH = 0x00000030;  //PORTB.9 Push-pull output 50MHz


Очень хорошо описано тут и тут.
Так очень удобно назначать сразу несколько пинов.
0
Порты, как наиболее часто используемые и простые устройства, запоминаются лучше всего. Приведите лучше пример, аналогичный этому:
TIM2_TimeBaseInit(TIM2_Prescaler_32,TIM2_CounterMode_Up,12500);
И сразу замените значение делителя на 128, не заглядывая в даташиты конечно.
А еще лучше аналог этой инициализации:
I2C_Init(I2C1, 400000, 0x80, I2C_Mode_I2C, I2C_DutyCycle_2, I2C_Ack_Enable,I2C_AcknowledgedAddress_7bit);
Где — 400000 частота шины, вычисляется в момент исполнения.
0
Весьма «адекватная» либа ничего не скажешь.
Как вычисляет это отдельные разговор. Но то что корректно вычислять будет только для HSI и HSE с 16 МГц, вы конечно не в курсе?
0
Для 20МГц (что не есть штатно) при задании скорости в 400кГц реальная была 384кГц.
0
  • avatar
  • PRC
  • 07 сентября 2011, 12:56
А ты комментарии оторви и сравни, что понятнее. Впрочем, опыт некоторых позволяет читать программу по бинарному коду, но большинство оным не обладает.
Например, в большинстве моего кода комментарии если и попадаются, то содержат куски кода. И это мне не мешает без проблем в нем ориентироваться не только в момент работы над ним, но и через 2-3 года после того, как я туда в последний раз заглядывал. А такие вот магические числа комментировать приходится в обязательном порядке, иначе я забуду что это уже на следущий день. И даже названия регистров не особо помогут, так как расшифровать аббревиатуру типа ADSС можно только смутно припоминая даташит или свой опыт.
0
Прикол в том, что когда читаешь даташит и разглядываешь какой куда битик суется, то попутно и досконально изучаешь все приколы и фичи железа. Просто потому, что оно пролистывается перед глазами. А не только те, что интуитивно понятный интерфейс библиотеки тебе покажет.

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

Так что если хочешь изучить МК вдоль и поперек — библиотеки нахуй и даташит в зубы. Если хошь слабать по быстрому, ну тады ищи готовые решения.
0
Буду повторяться:)
Я уже писал про CLK_SWR = 0xB4;. Встречал в нескольких местах, в том числе и тут. И что то ни кто из изучающих даташиты про него не написал. Все тупо скопировали. Так же и в программе будет — копирование из проекта в проект. Хотя в некоторых случаях половина может оказаться просто лишней. Или вообще вредной. А запомнить точную функцию всех битов никакого ума не хватит. Это не мега16 с 66 регистрами.
И что-то мне как то сомнительно, что мое запихивание битов будет более эффективно библиотек.
0
Ну как бы речь идет о обучении и изучении, а не про быдлокопипастинг.
0
Ты уверен что через месяц вспомнишь, что бит MSK4 в регистре RTC_ALRMAR2 отвечает за маску минут?
0
Я да. У меня просто убойная память на такие вещи :) Поэтому я для себя даже комменты не пишу обычно. И так помню все, даже если прошло пару лет.
0
Ну вот, а ведь в ALRMAR2 нет бита MSK4, а есть только MSK2:)
А в программе напишешь и будешь потом по регистрам выискивать, почему работает через зад.
0
Не напишу. Я запомню. Просто я на stm8 даже даташит еще не открывал. Все руки не дойдут :)

Кстати в CMSIS такая херь бы не прошла. Там у каждого бита имя сформировано так, что не туда его просто не запишешь. Там в имени полный путь указан.
0
Но названия там ебанутые, ага :( Нет чтобы бы назвать биты по человечески.
0
сегодня начал изучать, причем как раз с этого примера и сразу же нашел
Bits 7:0 CKM[7:0]: Clock master status bits
These bits are set and cleared by hardware. They indicate the currently selected master clock
source. An invalid value occurring in this register will automatically generate an MCU reset.
0xE1: HSI selected as master clock source (reset value)
0xD2: LSI selected as master clock source (only if LSI_EN option bit is set)
0xB4: HSE selected as master clock source

RM0016 Reference manual стр 76.
0
Это в С, в Л такого нет.
0
Ну, можно еще быстро скурить даташит на предмет возможностей периферии, и писать на библиотеках. Про нужную периферию в нем все равно нужно прочитать, но совершенно не обязательно при этом изучать возню с регистрами.
0
Быстро скурить не выйдет. Пока все заработает на регистры посмотреть придется:) Но запоминать их и вручную писать туда волшебные числа будет явным перебором:)
0
Я полностью согласен с DIHALT. Я против библиотек, точнее их можно использовать, но не начальном этапе. Изучать даташит нужно в любом случае. А говорить, что я разберусь, когда нужно будет — это не правильно. Это мода современных школьников и студентов говорить, что зачем его учить, если в книге это написано и когда нужно, то мол найду. Это неправда! Если не знаешь алфавита, то не прочтешь книгу; если не выучил таблицу умножения, то не решишь задачу; если не знаешь таблицы интегралов и дифференциалов, то не проведешь моделирование процесса и т.д. Всегда есть базис без которого ни одна задача не решиться. Да и библиотеки не всегда могут быть реализованы. Вот почитайте, что пишут про библиотеку ST для STM8
0
  • avatar
  • luxin
  • 15 августа 2011, 17:41
… всегда могут быть реализованы хорошо. Вот почитайте, что пишут про библиотеку ST для STM8 тут («STM8(S/L), первые впечатления»).
0
Типичная плата за удобство. Если внезапно не хватит скорости или памяти (последней, впрочем, там много) — тогда уже нужно искать пути оптимизации. И то, врядли потребуется переносить с библиотеки инит, а подергать пин и так несложно.
0
Это про первые версии. Сейчас большинство ошибок пофиксили.
А изучать даташит — это как? Внимательно читать назначение каждого бита в каждом из регистров? И запоминать? Нахрена это кому нужно? Получить в результате программу на пару килобайт меньше, но написанную за время, за которое можно написать 5 таких программ? И получить кучу геморроя при переносе на другое ядро или при внесении каких-то мелких изменений.
0
Даташит, конечно, в любом случае изучать, но с PL он изучается однажды, дальше заголовочник и CodeInsight доставят всю необходимую инфу. А вот с регистрами в даташит придется лазить за каждой строчкой, кроме однотипных. И, при достаточном количестве и запутанности регистров — каждый раз при написании кода. И это при постоянной работе с данным МК, при эпизодической каждый раз придется лазить даже за доками на MCS51, чтобы вспомнить, как они назвали тот или иной бит/регистр.
0
Если бы Вы внимательно прочитали ветку, то там не только ошибки, но и код генерировался не оптимальный. А я считаю, что если и использовать библиотеку, то она должна быть хорошо продумана и отлажена, т.к. разработчик приложения уже не должен ее править. Гнилыми гвоздями дом не построить! Как изучать? Архитектуру, методы адресации, форматы команд и данных и т.д. А вот биты это как раз справочные данные, их и подсмотреть можно. Без базы хорошее приложение никогда не напишите. Как говорил мой учитель, что без базы Вы не специалист, а ремесленник. Медведей тоже учат ездить на велосипеде, но вот только они велосипедистами от этого не становятся, т.к. умеют крутить только педали.
0
Я библиотеки не правил:) Не оптимальный код получается из-за универсальности, причем в основном только при инициализации.
А систему команд и прочее ассемблерно-процессорное тут похоже вообще никто не изучал:) Все на С клепают, только я в регистры через библиотеки пишу, а они напрямик. В этом основная дискуссия и заключается:)
0
но и код генерировался не оптимальный.
А он и не нужен, оптимальный код, в большинстве случаев. Запас производительности и памяти у СТМ8 нехилый. Если же ее не хватит — тогда уже можно подумать о оптимизации. Да и то, скорость нужна в основном при дергании GPIO, а это — запомнить пару регистров (причем обычно довольно логичных), а не все.
0
И еще, исправь заголовок на «периферийных».
0
  • avatar
  • Vga
  • 16 августа 2011, 00:07
Гы, а я и фаерфокс не заметил:)
0
Глупый вопрос — эти ИАРовские библиетеки идут вместе с ИАР 1.3? Я сейчас (и еще долго) могу заходить только с мобильного и поэтому скачать и посмотреть сам не могу.
Или речь про подпиленые библиотеки, которые лежат в папке примеров и с ИАР 1.20?
0
  • avatar
  • Maxim
  • 16 августа 2011, 17:46
Эти библиотеки идут с иаром в качестве примеров к stm8l-discovery. Но какая версия в них не знаю. У меня последняя, на данный момент, версия с st.com 1.5.1, из которых сделан готовый шаблон.
0
Еще один не менее — библиотеки с сайта СТ уже и под ИАР портированы, а не только космик и «тот второй»? Или Вы сами пилили?
0
Да, они портированы самой st.
0
Легким движением руки шаблон перепиливается под IAR 1.20. Красота!
0
И кстати, при компиляции — ни одного warning. Что я сделал не так? :)
0
Не подключил библиотеку stm8l15x_itc и не сделал полную перекомпиляцию.
0
  • avatar
  • PRC
  • 25 сентября 2011, 14:35
Не подключил, так и есть. Ибо не нужна пока.
0
Скачал библиотеку для STM8S, скинул содержимое из inc в соответствующую папку в IAR, также сделал с содержимым src. Получил такие ошибки при компиляции:
0
0
Что я сделал не так?
0
Судя по примеру библиотек унадо сначала скомпилить, попробовал это сделать по анаглогии с примерами в папке с IAR:
0
Без ошибок не обошлось: bsvi.ru/1261012615b7f
Где вообще должна быть объявлена ADC2?
(второй раз уже задеваю какую-то комбинацию кнопок и отправляется сообщение)
0
Разобрался. Вё просто, лишние .c файлы надо удалить.
0
Все правильно. Для Л'ки это не нужно, а для С лишнее нужно удалить.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.