Vladimir N. Shilov před 9 roky
revize
60d8596b3d
29 změnil soubory, kde provedl 2570 přidání a 0 odebrání
  1. 48 0
      !идеи.txt
  2. binární
      Atollic_Checklist_GCC_CodeSize.pdf
  3. 218 0
      C.txt
  4. 295 0
      C_port_pins_struct.txt
  5. 118 0
      C_unions_bits.txt
  6. 2 0
      ReadMe.txt
  7. 29 0
      Srv_Fan_Ctrl.txt
  8. 13 0
      adc.txt
  9. 102 0
      floatToString.h
  10. 7 0
      iar_interrupts.txt
  11. 100 0
      key_process.c
  12. 153 0
      knopki.txt
  13. 35 0
      ln.txt
  14. 21 0
      median_filter.c
  15. 327 0
      printf.c
  16. 252 0
      printf.h
  17. 1 0
      stm32/ReadMe.txt
  18. 70 0
      stm32/delay_us_systick.c
  19. 54 0
      stm32/gpio.c
  20. 66 0
      stm32/pwm.c
  21. 35 0
      stm32/spi.c
  22. 204 0
      stm8/Makefile.stm8l
  23. 172 0
      stm8/Makefile.stm8s
  24. 1 0
      stm8/ReadMe.txt
  25. 29 0
      stm8/lse.c
  26. 125 0
      stm8/mcu_gpio.h
  27. 2 0
      Поливалки.txt
  28. 43 0
      классы.txt
  29. 48 0
      фнч.txt

+ 48 - 0
!идеи.txt

@@ -0,0 +1,48 @@
+***
+часы-таймер бате на дачу.
+
+***
+что-то вроде
+http://www.ebay.com/itm/221206174532
+
+вольт-ампер-ватт-коловатчасов-метр переменного тока :-)
+http://radiokot.ru/circuit/digital/measure/76/
+http://radiokot.ru/circuit/digital/measure/23/
+http://radiokot.ru/circuit/digital/measure/14/
+
+***
+индиктаор уровня напряжения
+вроде этого
+http://radiokot.ru/circuit/digital/measure/47/
+
+***
+6-ти канальное зарядное для ni-mh/ni-cd с простешим управлением и индикацией
+по 6 штук -- двухцветные светодиоды (разряд/заряд/готов), каналы на разряд, 
+каналы на заряд. готовый алгоритм можно взять от заряжного электроотвёртки.
+можно поставить дип-переключатель для задания общего тока 100/200/400/600 мА
+если ставить 6 дипов -- то ещё придётся ставить какой-то коммутатор...
+проще ничего не придумывается...
+
+***
+зарядное для авто-аккумов, база на tl494, символьный индикатор. выставил 
+ёмкость аккума и оно заряжается. можно контроль температуры и соответсвенная 
+корректировка напряжения.
+
+***
+управляемый БП на lm2596 или любом другом интегральном стализаторе.
+можно взять stm32, индикатор от моторолы, сделать бп двухканальным.
+
+***
+многоподдиапазонный измеритель напряжения/тока, с точностью не хуже 10 мВ/мА
+на минимальном диапазоне возможно 1 мВ/мА
+
+***
+шим регулятор дял паяльника с обратной связью -- измерением тока на самом 
+нагревателе.
+
+***
+моддерский экранчег для компа -- измеряем температуру, крутим вентиляторы, по 
+юсб общаемся с компом...
+
+***
+забабахать цветомузыку на rgb-лентах. используя stm32f4 например...

binární
Atollic_Checklist_GCC_CodeSize.pdf


+ 218 - 0
C.txt

@@ -0,0 +1,218 @@
+[FAQ] Изменение и чтение отдельных битов
+
+имеем порт J, в codevision работать с ним как PORTJ.n нельзя,
+поэтому для установки бита N в единицу не трогая другие биты делаем так:
+PORTJ = PORTJ | (1<<N); или короче PORTJ |= (1<<N);
+
+установка бита N в ноль тогда будет:
+PORTJ = PORTJ & ~(1 << N);
+
+-------------------
+
+#ifndef _BV    // If !WinAVR
+#define _BV(n)    (1 << (n))
+#endif
+
+#define set_bit(p, n)    p |= _BV(n)
+#define clear_bit(p, n)    p &= ~_BV(n)
+#define invert_bit(p, n)    p ^= _BV(n) 
+
+-------------------
+
+ПРОВЕРЕНО в компиляторах IAR, CVAVR, ImageCraft ICC
+
+1) вариант для любого компилятора:
+
+// объявление:
+
+#define SET_B(x) |= (1<<x) 
+#define CLR_B(x) &=~(1<<x) 
+#define INV_B(x) ^=(1<<x)
+
+// x - номер бита в регистре
+
+// использование:
+
+PORTB SET_B(5);  // "установить"  бит5
+PORTB CLR_B(2);  // "очистить"  бит2
+PORTB INV_B(6);  // инвертировать бит6
+
+"установить" значит сделать "1" 
+"очистить" значит сделать "0" 
+"инвертировать" - сделать "0" если был "1" и наоборот.
+
+===============================================================================
+
+Вот классический алгоритм реверса битов в байте:
+
+unsigned char b = 0x72; // b = 01110010b
+// Меняем местами соседние биты в парах
+b = (b & 0x55) << 1 | (b & 0xAA) >> 1;
+// Меняем местами пары битов в тетрадах
+b = (b & 0x33) << 2 | (b & 0xCC) >> 2;
+// Меняем местами тетрады битов в байтах числа
+b = (b & 0x0F) << 4 | (b & 0xF0) >> 4;
+
+===============================================================================
+// Тип, описывающий глобальные флаги программы
+typedef struct _SFLAGS {
+    
+    uint8_t KeyModePressed:  1; // Состояние клавиши MODE
+    uint8_t KeyColorPressed: 1; // Состояние клавиши COLOR
+    uint8_t GotoSleep:       1; // Команда "Заснуть" для основного потока (main)
+    uint8_t RxComplete:      1; // Принята посылка в USART0
+    uint8_t:                 4; // дополнение до 8 бит (резерв) 
+    
+} SFLAGS;
+
+
+volatile struct               //flags
+ {
+   unsigned char Direction  : 1;
+   unsigned char SensorFree : 1;
+   unsigned char Tick       : 1;
+   unsigned char DirChd     : 1;
+ } Flag;
+
+
+использование:
+Flag.Tick = TRUE;
+
+===============================================================================
+
+Си для микроконтроллеров и чайников.
+Часть 2. Операции с переменными и регистрами микроконтроллера.
+
+§ 	> Обзор стандартных операций с регистрами.
+
+Настало время перейти к более серьёзным операциям над регистрами и программными переменными. Управление работой микроконтроллера в большинстве случаев сводится к следующему простому набору действий с его регистрами:
+
+1. Запись в регистр необходимого значения.
+2. Чтение значения регистра.
+3. Установка в единицу нужных разрядов регистра.
+4. Сброс разрядов регистра в ноль.
+5. Проверка разряда на логическую единицу или логический ноль.
+6. Изменение логического состояния разряда регистра на противоположное.
+
+Во всех указанных действиях принимает участие оператор присваивания языка Си, записываемый в виде знака равенства. Принцип действия оператора примитивно прост - он записывает в регистр или переменную расположенную слева от него, значение того, что записано справа. Справа может находится константа, другой регистр, переменная либо состоящее из них выражение, например:
+
+A = 16; // Присвоить переменной A значение 16;
+A = B; // Считать значение переменной B и присвоить это значение переменной A;
+A = B+10; // Считать значение переменной B, прибавить к считанному значению 10, результат присвоить переменной A (значение переменной B при этом не изменяется).
+
+
+§ 	> Запись и чтение регистров.
+ Из рассмотренных примеров видно, что оператор присваивания сам по себе решает две первые задачи — запись и чтение значений регистров. Например для отправки микроконтроллером AVR байта по шине UART достаточно записать его в передающий регистр с именем UDR:
+UDR = 8; // Отправить по UART число 8;
+
+ Чтобы получить принятый по UART байт достаточно считать его из регистра UDR:
+A = UDR; // Считать принятый байт из UART и переписать в переменную A.
+
+
+§ 	> Установка битов регистров.
+
+Язык Си не имеет в своём составе команд непосредственного сброса или установки разрядов переменной, однако присутствуют побитовые логические операции "И" и "ИЛИ", которые успешно используются для этих целей.
+Оператор побитовой логической операции "ИЛИ" записывается в виде вертикальной черты - "|" и может выполнятся между двумя переменными, а так же между переменной и константой. Напомню, что операция "ИЛИ" над двумя битами даёт в результате единичный бит, если хотя бы один из исходных битов находится с состоянии единицы. Таким образом для любого бита логическое "ИЛИ" с "1" даст в результате "1", независимо от состояния этого бита, а "ИЛИ" с логическим "0" оставит в результате состояние исходного бита без изменения. Это свойство позволяет использовать операцию "ИЛИ" для установки N-ого разряда в регистре. Для этого необходимо вычислить константу с единичным N-ным битом по формуле 2^N, которая называется битовой маской и выполнить логическое "ИЛИ" между ней и регистром, например для установки бита №7 в регистре SREG:
+(SREG | 128) — это выражение считывает регистр SREG и устанавливает в считанном значении седьмой бит, далее достаточно изменённое значение снова поместить в регистр SREG:
+SREG = SREG | 128; // Установить бит №7 регистра SREG.
+
+Такую работу с регистром принято называть "чтение - модификация - запись", в отличие от простого присваивания она сохраняет состояние остальных битов без именения.
+Приведённый программный код, устанавливая седьмой бит в регистре SREG, выполняет вполне осмысленную работу - разрешает микроконтроллеру обработку программных прерываний. Единственный недостаток такой записи — в константе 128 не легко угадать установленный седьмой бит, поэтому чаще маску для N-ного бита записывают в следующем виде:
+
+(1<<N) - это выражение на языке Си означает, число один, сдвинутое на N разрядов влево, это и есть маска с установленным N-ным битом. Тогда предыдущий код в более читабельном виде:
+REG = SREG | (1<<7); 
+
+или ещё проще с использование краткой формы записи языка Си:
+REG |= (1<<7); 
+
+которая означает - взять содержимое справа от знака равенства, выполнить между ним и регистром слева операцию, стоящую перед знаком равенства и записать результат в регистр или переменную слева.
+
+
+§ 	> Сброс битов в регистрах.
+
+Ещё одна логическая операция языка Си – побитовое "И", записывается в виде символа "&". Как известно, операция логического "И", применительно к двум битам даёт единицу тогда и только тогда, когда оба исходных бита имеют единичное значение, это позволяет применять её для сброса разрядов в регистрах. При этом используется битовая маска, в которой все разряды единичные, кроме нулевого на позиции сбрасываемого. Её легко получить из маски с установленным N-ным битом, применив к ней операцию побитного инвертирования:
+~(1<<N) в этом выражении символ "~" означает смену логического состояния всех битов маски на противоположные. Так, например, если (1<<3) в двоичном представлении – 00001000b,  то ~(1<<3) уже 11110111b. Сброс седьмого бита в регистре SREG будет выглядеть так:
+SREG = SREG & (~ (1<<7));  или кратко: SREG &= ~ (1<<7);
+
+В упомянутом ранее заголовочном файле для конкретного микроконтроллера приведены стандартные имена разрядов регистров специального назначения, например:
+#define OCIE0 1
+
+здесь #define – указание компилятору заменять в тексте программы сочетание символов "OCIE0" на число 1, то есть стандартное имя бита OCIE0, который входит в состав регистра TIMSK микроконтроллера Atmega64 на его порядковый номер в этом регистре. Благодаря этому установку бита OCIE0 в регистре TIMSK можно нагляднее записывать так:
+TIMSK|=(1<<OCIE0);
+
+Устанавливать или сбрасывать несколько разрядов регистра одновременно можно, объединяя битовые маски в выражениях оператором логического "ИЛИ":
+PORTA |= (1<<1)|(1<<4); // Установить выводы 1 и 4 порта A в единицу;
+PORTA&=~((1<<2)|(1<<3)); // Выводы 2 и 3 порта A сбросить в ноль.
+
+ 
+§	> Проверка разрядов регистра на ноль и единицу.
+
+Регистры специального назначения микроконтроллеров содержат в своём 
+составе множество битов-признаков, так называемых "флагов”, уведомляющих 
+программу о текущем состоянии микроконтроллера и его отдельных модулей. 
+Проверка логического уровня флага сводится к подбору выражения, которое 
+становится истинным или ложным в зависимости от того установлен или 
+сброшен данный разряд в регистре. Таким выражением может служить 
+логическое "И” между регистром и маской с установленным разрядом N на 
+позиции проверяемого бита :
+(REGISTR & (1<<N)) в этом выражении операция "И” во всех разрядах кроме 
+N-ного даст нулевые значения, а проверяемый разряд оставит без изменения. 
+Таким образом возможное значения выражения будут или 0 или 2^N, например 
+для второго бита регистра SREG:
+
+Приведённое выражение можно использовать в условном операторе if 
+(выражение) или операторе цикла while (выражение), которые относятся к 
+группе логических, то есть воспринимают в качестве аргументов значения 
+типа истина и ложь. Поскольку язык Си, приводя числовые значения к 
+логическим, любые числа не равные нулю воспринимает как логическую истину, 
+значение (REGISTR & (1<<N)) равное 2^N в случае установленного бита, будет 
+воспринято как "истина".
+
+Если появляется необходимость при установленном бите N получить для нашего 
+выражения логическое значение «ложь», достаточно дополнить его оператором 
+логической инверсии в виде восклицательного знака - !(REGISTR & (1<<N)). 
+Не следует путать его с похожим оператором побитовой инверсии (~) меняющим 
+состояние битов разряда на противоположное. Логическая инверсия работает 
+не с числовыми значениями, а с логическими, то есть преобразует истинное в 
+ложное и наоборот. Такая конструкция приводится в DataSheet на Atmega как 
+пример для ожидания установки бита UDRE в регистре UCSRA, после которого 
+можно отправлять данные в UART:
+while ( !( UCSRA & (1<<UDRE)) ) { } // Ждать установки UDRE.
+
+здесь при сброшенном бите UDRE выражение ( UCSRA & (1<<UDRE)) даст 
+значение ”ложь”, инвертированное
+!( UCSRA & (1<<UDRE)) — ”истину”, и пока это так, программа будет 
+выполнять действия внутри фигурных скобок, то есть не делать ничего 
+(стоять на месте). Как только бит UDRE установится в единицу, программа 
+перейдёт к выполнению действий следующих за конструкцией while(), например 
+займётся отправкой данных в UART.
+
+
+§ 	> Изменение состояния бита регистра на противоположное.
+
+Эту, с позволения сказать, проблему с успехом решает логическая операция 
+побитного "ИСКЛЮЧАЮЩЕГО ИЛИ” и соответствующий ей оператор Си, 
+записываемый в виде символа " ^ ”. Правило "исключающего или" с двумя 
+битами даёт "истину” тогда и только тогда, когда один из битов установлен, 
+а другой сброшен. Не трудно убедиться, что этот оператор, применённый 
+между битовой маской и регистром, скопирует в результат биты стоящие 
+напротив нулевых битов маски без изменения и инвертирует расположенные 
+напротив единичных. Например, если: reg=b0001 0110 и mask=b0000 1111, то 
+reg^mask=b0001 1001. Таким способом можно менять состояние светодиода, 
+подключенного к пятому биту порта A:
+
+#define LED 5 // Заменять в программе сочетание символов LED на число 5 
+(вывод светодиода).
+…
+PORTA ^=(1<< LED); // Погасить светодиод, если он светится и наоборот.
+
+
+§ 	> Арифметика и логика языка Си.  
+
+Мы рассмотрели типичный набор операций, используемый при работе с 
+регистрами микроконтроллера. Помимо них в арсенале языка имеется ряд 
+простейших арифметических и логических операций, описания которых можно 
+найти в любом справочнике по Си, например: 
+
+Для более подробного знакомства с операциями над переменными и языком Си в 
+целом, рекомендую книгу "Язык программирования Си" Б. Керниган, Д. Ритчи.

+ 295 - 0
C_port_pins_struct.txt

@@ -0,0 +1,295 @@
+из каментов к 
+http://easyelectronics.ru/avr-uchebnyj-kurs-programmirovanie-na-si-chast-2.html
+
+
+
+То есть (по крайне мере, по моему) вместо
+while(PORTB & (1 << MYPIN_DRIVE_LOCK))
+
+гораздо приятнее писать
+while(ControlBus.DriveLock)
+
+Я так себе вообще написал удобные макросы, с помощью которых порты определяю так:
+BEGIN_PORT_DEFINITION
+	DEFINE_PORT_PIN(RowFeedback)
+	DEFINE_PORT_PIN(RowForwarder)
+	DEFINE_PORT_PIN(RowDataline)
+	DEFINE_PORT_PIN(ColFeedback)
+	DEFINE_PORT_PIN(ColForwarder)
+	DEFINE_PORT_PIN(AnodeSwitch)
+END_PORT_DEFINITION(Matrix, A)
+
+инициализирую так:
+	HalConfigurePin(Matrix,		RowFeedback,	IN,		PULLUP	);
+	HalConfigurePin(Matrix,		RowForwarder,	OUT,			);
+	HalConfigurePin(Matrix,		RowDataline,	OUT,			);
+	HalConfigurePin(Matrix,		ColFeedback,	IN,		PULLUP	);
+	HalConfigurePin(Matrix,		ColForwarder,	OUT,			);
+	HalConfigurePin(Matrix,		AnodeSwitch,	IN,		Z	);
+
+А юзаю примерно так:
+	Matrix.Out->RowDataline = 1;
+	ImpulseP(Matrix.Out->RowForwarder);
+	Matrix.Out->RowDataline = 0;
+
+	if(Matrix.In->RowFeedback)
+	{
+		//
+		// Отсутствует отклик с RCM-шины. Нет ни одного RCM
+		// или сбой в первом RCM
+		// 
+
+		PostErrorSound(POSTERROR_NO_RCM_FEEDBACK);
+	}
+
+ИМХО это выразительнее, чем побитовые опрерации, при равной производительности 
+и компактности кода.
+
+
+----
+
+ОК, сейчас объясню.
+
+Фишка в том, что в Си мы имеем возможность юзать bit-field’ы (кто не знает что 
+это такое, ищите сами, я здесь объяснять не буду).
+
+У нас порт это (обычно) 8 пинов и мы работаем с каждым пином дёргая 
+соответствующие биты в соответствующих портах.
+
+Ну а доступ к отдельным битам можно получать по разному: можно с помощью 
+bitwise-операций, а можно с помощью bit-field’ов. Адекватному компилятору не 
+должно быть никакой разницы, написали ли мы
+    foo |= 2
+
+или же у нас
+    foo.SecondBitField = 1
+
+он в обоих случаях генерирует один и тот же машинный код.
+
+Так вот, есть у нас, скажем, PORTC, у которого первые три пина — выходы, на 
+которых висят светодиоды, потом один пулап-вход и 2 высокоимп. входа.
+
+Мы могли бы объявить 6 констант и работать с регистрами порта с помощью 
+обычных побитовых операторов, примерно так:
+    #define MY_PIN_RED_LED     0
+    #define MY_PIN_YELLOW_LED  1
+    #define MY_PIN_GREEN_LED   2
+    #define MY_PIN_BUTTON      3
+    #define MY_PIN_AUX1        4
+    #define MY_PIN_AUX2        5
+
+    ...
+
+    DDRC = 0;
+    // Делаем первые три пина выходами
+    DDRC |= ((1 << MY_PIN_RED_LED) | (1 << MY_PIN_YELLOW_RED) | (1 << MY_PIN_GREEN_LED));
+
+    // Включаем подтяжку на нужном пине
+    PORTC = 1 << MY_PIN_BUTTON;
+    ...
+
+    // Зажигаем красный и зелёный сиды:
+    PORTC |= ((1 << MY_PIN_RED_LED) | (1 << MY_PIN_GREEN_LED));
+
+    // Проверяем вход последнего пина:
+    if(PINC & (1 << MY_PIN_AUX2)) ...
+
+но могли бы объявить такую структуру:
+    typedef struct
+    {
+        char RedLed:1;
+        char YellowRed:1;
+        char GreenLed:1;
+        char Button:1;
+        char Aux1:1;
+        char Aux2:1;
+    } MY_PORT_PINS;
+
+и делать то же самое, но кастуя тип регистров к этой структуре:
+    // Делаем первые три пины выходами
+    ((MY_PORT_PINS)DDRC).RedLed = 1;
+    ((MY_PORT_PINS)DDRC).YellowRed = 1;
+    ((MY_PORT_PINS)DDRC).GreenRed = 1;
+
+    // Включаем подтяжку на нужном пине
+    ((MY_PORT_PINS)PORTC).Button = 1
+    ...
+
+    // Зажигаем красный и зелёный сиды:
+    ((MY_PORT_PINS)PORTC).RedLed = 1;
+    ((MY_PORT_PINS)PORTC).GreenLed = 1;
+
+    Проверяем вход последнего пина:
+    if(((MY_PORT_PINS)PINC).Aux2) ...
+
+Как видите, здесь структура MY_PORT_PINS выступает чем-то вроде контейнера для 
+бит-фиелдов и отражает реальную структуру порта.
+
+Это выглядит чуть лучше, но всё ещё плохо: куча кастования. Кроме того, этот 
+код вообще не скомпилируетя. По крайней мере AvrGCC отказался кастовать PORTC 
+к структуре. Да и у нас тут везде всё те же PORTC, PINC, DDRC. Если мы захотим 
+сменить порт на B, это что же нам, везде менять? Даже если мы заюзам макросы, 
+придётся использовать три макроса (ну и менять соответственно 3 строчки).
+
+Негоже! :)
+
+Поэтому окончательное решение состоит в том, чтобы создать глобальную 
+переменную для всего порта, имя которой будет отражать предназначение порта. 
+Типом этой глобальной переменной будет структура с трёмя полями-указателями на 
+PORTX, PINX и DDRX.
+
+Важно (!!!) поставить квалификатор const в объявления указателей. 
+Использование константных указателей компилятор оптимизирует, поэтому никакой 
+разницы в коде между предыдущим примером не будет, зато внешне всё будет 
+выглядеть красивее:
+
+(Ахтунг! Я советую вам чем раньше, тем лучше подробно разобраться с 
+CV-квалификаторами. Крайне важно понимать, чем указатели на константу (const 
+int * a) отличаются от константных указателей (int * const a), очень важно, 
+чтобы ваш мозг не взорвался когда вы увидите сочетание const- и volatile- 
+квалификаторов (это абсолютно нормальное сочетание, на самом деле))
+
+    typedef struct
+    {
+        char RedLed:1;
+        char YellowRed:1;
+        char GreenLed:1;
+        char Button:1;
+        char Aux1:1;
+        char Aux2:1;
+    } MY_PORT_PINS;
+
+    typedef struct
+    {
+        MY_PORT_PINS* const In;
+        volatile MY_PORT_PINS* const Out;
+        MY_PORT_PINS* const DDR;
+    } MY_PORT_CONTROL_BUS ControlBus = {
+                                            (MY_PORT_PINS*)&PINC,
+                                            (MY_PORT_PINS*)&PORTC,
+                                            (MY_PORT_PINS*)&DDRC,
+                                       };
+
+    // Всё, теперь доступ к битам регистра PIN порта С осуществляетсчя так:
+    //         ControlBus->In.xxxxxx
+    // доступ к битам регистра PORT порта C, так:
+    //         ControlBus->Out.xxxxxx
+    // доступ к битам регистра DDR порта C, так:
+    //         COntrolBus->DDR.xxxxxx
+    // где xxxxx -- логический пин, он же поле из структуры MY_PORT_PINS,
+    //              например GreenLed.
+
+Чтобы для каждого совего порта не писать такую громадину из сткрутур, я создал 
+следующие три макроса:
+    #define BEGIN_PORT_DEFINITION  typedef struct {
+    #define DEFINE_PORT_PIN(name) char name:1;
+    #define END_PORT_DEFINITION(portname, hardport) } SYSPORTPINS_##portname; \
+                                            typedef struct \
+              { \
+               SYSPORTPINS_##portname* const In; \
+               volatile SYSPORTPINS_##portname* const Out; \
+               SYSPORTPINS_##portname* const DDR; \
+              } SYSPORT_##portname; \
+              SYSPORT_##portname portname = {(SYSPORTPINS_##portname*)&PIN##hardport,     
+
+(SYSPORTPINS_##portname*)&PORT##hardport, (SYSPORTPINS_##portname*)&DDR##hardport};
+
+С применением этих макросов вместо такого объявления:
+    typedef struct
+    {
+        char RedLed:1;
+        char YellowRed:1;
+        char GreenLed:1;
+        char Button:1;
+        char Aux1:1;
+        char Aux2:1;
+    } MY_PORT_PINS;
+
+    typedef struct
+    {
+        MY_PORT_PINS* const In;
+        volatile MY_PORT_PINS* const Out;
+        MY_PORT_PINS* const DDR;
+    } MY_PORT_CONTROL_BUS ControlBus = {
+                                            (MY_PORT_PINS*)&PINC,
+                                            (MY_PORT_PINS*)&PORTC,
+                                            (MY_PORT_PINS*)&DDRC,
+                                       };
+
+мы можем писать так:
+    BEGIN_PORT_DEFINITION
+        DEFINE_PORT_PIN(RedLed)
+        DEFINE_PORT_PIN(YellowRed)
+        DEFINE_PORT_PIN(GreenLed)
+        DEFINE_PORT_PIN(Button)
+        DEFINE_PORT_PIN(Aux1)
+        DEFINE_PORT_PIN(Aux2)
+    END_PORT_DEFINITION(ControlBus,C)
+
+Осталось только сделать удобное конфигурирование портов. 
+
+Как известно, если в DDR бит установлен, то пин — выход, в противном случае вход.
+ Если порт выход, то бит в регистре PORT это его состояние, если же вход — то 
+бит в регистре PORT определяет, включена подтяжка или нет.
+
+Поэтому я сделал макрос HalConfigurePin, чтобы конфигурировать пины быстро, 
+красиво, и в таблице-подобном виде.
+
+Сам макрос (+ прилагающиеся к нему константы) выглядит так:
+    #define __HALCONF_   0
+    #define __HALCONF_OUT   1
+    #define __HALCONF_IN  0
+    #define __HALCONF_PULLUP 1
+    #define __HALCONF_Z   0
+
+    #define HalConfigurePin(__port, __pin, __in_out, __pullup_val) __port.DDR->__pin = __HALCONF_##__in_out;
+
+__port.Out->__pin = __HALCONF_##__pullup_val
+
+Соответственно, код для конфигурирования наших 6 пинов будет выглядеть так:
+    HalConfigurePin(ControlBus, RedLed        , OUT ,        );
+    HalConfigurePin(ControlBus, YellowRed     , OUT ,        );
+    HalConfigurePin(ControlBus, GreenLed      , OUT ,        );
+    HalConfigurePin(ControlBus, Button        , IN  , PULLUP );
+    HalConfigurePin(ControlBus, Aux1          , IN  , Z      );
+    HalConfigurePin(ControlBus, Aux2          , IN  , Z      );
+
+Ну и первоначальный код соответственно будет выглядеть так:
+    BEGIN_PORT_DEFINITION
+        DEFINE_PORT_PIN(RedLed)
+        DEFINE_PORT_PIN(YellowRed)
+        DEFINE_PORT_PIN(GreenLed)
+        DEFINE_PORT_PIN(Button)
+        DEFINE_PORT_PIN(Aux1)
+        DEFINE_PORT_PIN(Aux2)
+    END_PORT_DEFINITION(ControlBus,C)
+
+    ...
+
+    HalConfigurePin(ControlBus, RedLed        , OUT ,        );
+    HalConfigurePin(ControlBus, YellowRed     , OUT ,        );
+    HalConfigurePin(ControlBus, GreenLed      , OUT ,        );
+    HalConfigurePin(ControlBus, Button        , IN  , PULLUP );
+    HalConfigurePin(ControlBus, Aux1          , IN  , Z      );
+    HalConfigurePin(ControlBus, Aux2          , IN  , Z      );
+
+    // Зажигаем красный и зелёный сиды:
+    ControlBus->Out.RedLed = 1;
+    ControlBus->Out.GreenLed = 1;
+
+    //Проверяем вход последнего пина:
+    if(ControlBus->In.Aux2) ...
+
+
+----
+
+К конкретному порту идёт привязка в макросе END_PORT_DEFINITION. Там вторым 
+параметром указывается буковка. Я ступил и забыл написать в этом 
+посте-примере, но в самом первом посте (где Matrix) это есть.
+
+А в этом посте, если у тебя есть возможность, поправь
+ END_PORT_DEFINITION
+ на
+ END_PORT_DEFINITION(ControlBus, X)
+ где X — поставь букву любого порта, к которому душа лежит :)
+

+ 118 - 0
C_unions_bits.txt

@@ -0,0 +1,118 @@
+http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=67601
+
+   typedef union { 
+       volatile unsigned char flinps; 
+       struct { 
+          unsigned char b0 : 1; 
+          unsigned char b1 : 1; 
+          unsigned char menubtileft : 1; 
+          unsigned char menubtimiddle : 1; 
+          unsigned char menubtiright : 1; 
+          unsigned char b5 : 1; 
+          unsigned char b6 : 1; 
+          unsigned char b7 : 1; 
+       }; 
+    } flinps_union_t; 
+     
+    typedef union { 
+       volatile unsigned char buttons; 
+       struct { 
+          unsigned char b0 : 1; 
+          unsigned char b1 : 1; 
+          unsigned char menubtbleft : 1; 
+          unsigned char menubtbmiddle : 1; 
+          unsigned char menubtbright : 1; 
+          unsigned char b5 : 1; 
+          unsigned char b6 : 1; 
+          unsigned char b7 : 1; 
+       }; 
+    } buttons_union_t; 
+
+ typdef struct { 
+    flinps_union_t flinps; 
+    buttons_union_t buttons; 
+    unsigned char buttprsd;        
+    unsigned char fdsmsm;        
+    unsigned char tmpinps; 
+ } mydata_struct_t; 
+
+ mydata_struct_t mydata; 
+
+ int main(void) { 
+     mydata.flinps.menubtileft = 1; 
+     mydata.buttons.menubtbright = 0; 
+     mydata.buttprsd = 11; 
+     mydata.fdsmsm = 22; 
+     mydata.tmpinps = 33; 
+ }
+-------------------------------------------------------------------------------
+
+Как брать отдельные байты от слова?
+
+http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=20709&start=0
+
+A UNION is the most elegant solution and designed to perform just this task. 
+
+Code:
+
+ union u_type            //Setup a Union 
+ { 
+   unsigned int IntVar; 
+   unsigned char Bytes[2]; 
+ } 
+  temp;                    //Assign a var name to the Union 
+
+
+ void main(void) 
+ { 
+  temp.IntVar=65535;          //Assign a value to the Int var of the Union 
+  HighByte=temp.Bytes[1];  //Get the High Byte (255) 
+  LowByte=temp.Bytes[0];   //Get the Low Byte (255) 
+ }
+
+----------
+
+into a series of char (8-bit) pointers. Example: 
+Code:
+
+ unsigned char low_byte; 
+ unsigned char high_byte; 
+ unsigned int the_value; 
+ ... 
+ the_value = 1234; 
+ low_byte = * ((unsigned char *)&the_value); 
+ high_byte = * ((unsigned char *)((&the_value)+1)); 
+
+
+ or a char-sized pointer could be used the same way. [I'd probably use the pointer method for repetitive uses within an app and/or many-byte variables.] 
+
+Code:
+
+ unsigned char low_byte; 
+ unsigned char high_byte; 
+ unsigned int the_value; 
+ unsigned char *the_ptr; 
+ ... 
+ the_value = 1234; 
+ the_ptr = * ((unsigned char *)&the_value); 
+ low_byte = *the_ptr; 
+ the_ptr++; 
+ high_byte = *the_ptr;
+
+----------
+
+the bset way: 
+
+ it only compile in ONe line asm code ! 
+
+Code:
+
+ #define LowB(x) (*((unsigned char*)  &(##x)+1)) 
+ #define HighB(x) (*((unsigned char*) &(##x)+0)) 
+
+
+
+ for ex for low byte use LowB(x)
+
+только тут наверное младший байт без смещение (лежит первым), а старший 
+байт -- +1. И тогда это совпадёт с предыдущим примером.

+ 2 - 0
ReadMe.txt

@@ -0,0 +1,2 @@
+Решил в одном месте собирать разные советы, тонкости хитрости, мысли и 
+заметки, которые можно применять больше одного раза.

+ 29 - 0
Srv_Fan_Ctrl.txt

@@ -0,0 +1,29 @@
+Задумка для нового проекта
+контроллер 4-х вентиляторов для моего сервака.
+
+1. контроль температуры радиатора процессора
+1.а. ещё один датчик где-то или получение инфы от сервака.
+2. управление оборотами 4-х кулеров
+3. контроль оборотов 4-х кулеров
+4. связь с серваком по ком-порту для получения команд и выдачи текущей инфы.
+5. можно мерять напруги питания. может будет точнее чем встроенное.
+
+кандидаты в процы:
+STM8S105C6T6
+ - LQFP-48
+ - ROM 32kB, RAM 2kB, EEPROM 1kB
+ - timers: 1x8-bit, 3x16-bit
+ - 2 WDG, beeper
+ - adc 10x10bit
+ - SPI; I2C; UART;
+ - 38 ios
+связь с серваком -- через мост uart-usb
+
+сильно много ног, и дохрена памяти.
+в идеале взять 20-ти ногий корпус, на там не хватает таймерных выходов.
+почти подходит STM32F031F4 -- но нужно отказаться или от ком-порта,
+или от части измерителей оборотов, или от датчика температуры --
+команду на изменение оборотов будет давать демон из основной системы.
+
+32-х ногий вроде как подохдит любой.
+но пока не могу решить, какой из имеющихся в наличии отдать под это дело.

+ 13 - 0
adc.txt

@@ -0,0 +1,13 @@
+http://forum.easyelectronics.ru/viewtopic.php?p=334529#p334529
+
+В общем случае калибровка по двум точкам дает наклон Kx и смещение Sx. 
+Вычисляются они следующим образом:
+
+Kx = (p2 - p1) / (c2 - c1);
+Sx = Kx * c1 - p1;
+
+где p1, p2 - калибровочные точки в мА, c1, c2 - коды АЦП, соответствующие этим точкам.
+При измерении ток в мА вычисляется из кода АЦП так: ma = Kx * code - Sx; 
+Чтобы привести вычисления к целочисленной арифметике, нужно масштабировать 
+все значения, чтобы не потерять точность. И не забывать об округлении при 
+каждой операции деления.

+ 102 - 0
floatToString.h

@@ -0,0 +1,102 @@
+// floatToString.h
+//
+// Tim Hirzel
+// tim@growdown.com
+// March 2008
+// float to string
+//
+// If you don't save this as a .h, you will want to remove the default arguments
+//     uncomment this first line, and swap it for the next.  I don't think keyword arguments compile in .pde files
+
+//char * floatToString(char * outstr, float value, int places, int minwidth=, bool rightjustify) {
+char * floatToString(char * outstr, float value, int places, int minwidth=0, bool rightjustify=false) {
+    // this is used to write a float value to string, outstr.  oustr is also the return value.
+    int digit;
+    float tens = 0.1;
+    int tenscount = 0;
+    int i;
+    float tempfloat = value;
+    int c = 0;
+    int charcount = 1;
+    int extra = 0;
+    // make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import
+    // if this rounding step isn't here, the value  54.321 prints as 54.3209
+
+    // calculate rounding term d:   0.5/pow(10,places)
+    float d = 0.5;
+    if (value < 0)
+        d *= -1.0;
+    // divide by ten for each decimal place
+    for (i = 0; i < places; i++)
+        d /= 10.0;
+    // this small addition, combined with truncation will round our values properly
+    tempfloat +=  d;
+
+    // first get value tens to be the large power of ten less than value
+    if (value < 0)
+        tempfloat *= -1.0;
+    while ((tens * 10.0) <= tempfloat) {
+        tens *= 10.0;
+        tenscount += 1;
+    }
+
+    if (tenscount > 0)
+        charcount += tenscount;
+    else
+        charcount += 1;
+
+    if (value < 0)
+        charcount += 1;
+    charcount += 1 + places;
+
+    minwidth += 1; // both count the null final character
+    if (minwidth > charcount){
+        extra = minwidth - charcount;
+        charcount = minwidth;
+    }
+
+    if (extra > 0 and rightjustify) {
+        for (int i = 0; i< extra; i++) {
+            outstr[c++] = ' ';
+        }
+    }
+
+    // write out the negative if needed
+    if (value < 0)
+        outstr[c++] = '-';
+
+    if (tenscount == 0)
+        outstr[c++] = '0';
+
+    for (i=0; i< tenscount; i++) {
+        digit = (int) (tempfloat/tens);
+        itoa(digit, &outstr[c++], 10);
+        tempfloat = tempfloat - ((float)digit * tens);
+        tens /= 10.0;
+    }
+
+    // if no places after decimal, stop now and return
+
+    // otherwise, write the point and continue on
+    if (places > 0)
+    outstr[c++] = '.';
+
+
+    // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
+    for (i = 0; i < places; i++) {
+        tempfloat *= 10.0;
+        digit = (int) tempfloat;
+        itoa(digit, &outstr[c++], 10);
+        // once written, subtract off that digit
+        tempfloat = tempfloat - (float) digit;
+    }
+    if (extra > 0 and not rightjustify) {
+        for (int i = 0; i< extra; i++) {
+            outstr[c++] = ' ';
+        }
+    }
+
+
+    outstr[c++] = '\0';
+    return outstr;
+}

+ 7 - 0
iar_interrupts.txt

@@ -0,0 +1,7 @@
+IAR
+intrinsics.h
+
+__isstate_t savestate = __get_interrupt_state(); // сохранить текущее состояние
+__disable_interrupt(); // запретить прерывания
+..... // работа
+__set_interrupt_state(savestate); // восстановить прежнее состояние

+ 100 - 0
key_process.c

@@ -0,0 +1,100 @@
+/**
+
+http://electronix.ru/forum/index.php?showtopic=93624&view=findpost&p=964475
+
+Примерно лет шесть делаю так:
+
+*/
+
+// в .h-файле:
+  // кол-во времени до события "длинное нажатие"
+  #define TIMER_COUNT 250
+  // кол-во кнопок
+  #define KEY_COUNT 4
+  // время автоинкремента
+  #define   TIMER_SCROLL  20
+
+  // состояние кнопки
+  enum {KN_DOWN =0, KN_UP =1,  KN_PRESS=2 };
+  // тип функции кнопки
+  typedef byte(KeyFunc)(void);
+
+  // структура хранящая набор переменных для каждой кнопки
+  typedef struct key_struct__
+   {
+    byte state; // состояние кнопки
+    byte mask;  // маска клавиши
+    byte pins;  // буфер значений с клавиши
+    byte count; // счетчик нажатий
+    KeyFunc * exec_down;
+    KeyFunc * exec_up;
+    KeyFunc * exec_pres;
+   }key_struct;
+
+// в .c-файле:
+//*****************************************************************************
+// Драйвер кнопок
+//    назначение кнопок
+//    1- MiNUS 2-PLUS  3- Select 4- Enter
+//*****************************************************************************
+
+//=============================================================================
+// состояния кнопок
+static key_struct key_mass [KEY_COUNT] = {
+ //state  mask            pins count exec_down exec_up       exec_pres
+  {KN_UP, PIN_KEY_MINUS,  0xFF,0x00, kn_empty, kn_minus_up  ,kn_minus_up    }
+ ,{KN_UP, PIN_KEY_PLUS,   0xFF,0x00, kn_empty, kn_plus_up   ,kn_plus_up     }
+ ,{KN_UP, PIN_KEY_SELECT, 0xFF,0x00, kn_empty, kn_select_up ,kn_empty       }
+ ,{KN_UP, PIN_KEY_ENTER,  0xFF,0x00, kn_empty, kn_empty     ,kn_enter_press }
+ };
+//=============================================================================
+
+ISR(TIMER1_COMPA_vect)
+ {
+  #define Sta     key->state
+  #define Pin     key->pins
+  #define Cnt     key->count
+  #define Msk     key->mask
+  #define Down    key->exec_down
+  #define Up      key->exec_up
+  #define Pres    key->exec_pres
+
+  key_struct * key = key_mass;
+  for(byte i=0; i< KEY_COUNT ; i++)
+   {
+    Pin *=2;        //  * or <<
+    if(KEY_PIN & Msk) Pin |= 0x01;
+
+    if(Sta == KN_UP)
+     {
+      if(!Pin)      // начало счета - нажатие
+       {
+        Down();
+        Sta = KN_DOWN;
+        Cnt = 0x00;
+       }
+     }
+    else       // down or press
+     {
+      if(Pin==0xFF)  // отпустили
+       {
+        if(Sta == KN_DOWN) Up();
+        Sta = KN_UP;
+       }
+      else// удерживаем
+       {
+        if(Cnt <= TIMER_COUNT) ++Cnt;
+        if(Cnt == TIMER_COUNT) // длительное удержание - попадаем один раз!!
+         {
+          if(Pres()) Cnt = TIMER_COUNT - TIMER_SCROLL;
+            else     Sta = KN_PRESS;
+         }
+       }
+     }
+key++;
+   }
+ }
+
+/**
+Таймер в CTC-режиме на порядка 5....15 мсек
+*/

+ 153 - 0
knopki.txt

@@ -0,0 +1,153 @@
+Для кнопки надо выбраную ножку I/O подключить через кнопку на землю. Сам же
+вывод надо сконфигурировать как вход с подтяжкой (DDRxy=0 PORTxy=1). Тогда,
+когда кнопка не нажата, через подтягивающий резистор, на входе будет высокий
+уровень напряжения, а из бит PINху будет при чтении отдавать 1. Если кнопку
+нажать, то вход будет положен на землю, а напряжение на нем упадет до нуля, а
+значит из PINxy будет читаться 0. По нулям в битах регистра PINх мы узнаем
+что кнопки нажаты.
+
+ Пунктиром показан дополнительный подтягивающий резистор. Несмотря на то, что
+внутри AVR на порт можно подключить подтяжку, она слабоватая — 100кОм. А
+значит ее легко придавить к земле помехой или наводкой, что вызовет ложное
+срабатывание. А еще эти внутренние подтягивающие резисторы очень любят гореть
+от наводок. У меня уже с десяток микроконтроллеров с убитыми PullUp
+резисторами. Все работает, но только нет подтяжки — сгорела. Вешаешь снаружи
+резистор и работает как ни в чем ни бывало. Поэтому, для ответственных схем я
+настоятельно рекомендую добавить внешнюю подтяжку на 10кОм — даже если
+внутреннюю накроет, внешняя послужит. В процессе обучения на это можно
+забить.
+===============================================================================
+
+если кнопка нажата и флага1 нет - ставим флаг и выход.
+если кнопка нажата и есть флаг1 - увеличиваем счётчик. если счётчик переполнился - фиксируем удержание.
+	если есть флаг удержания, счётчик не переполнен но достиг порога - можно фикисровать срабатывани атовповтора (при необходимости)
+
+если кнопка отпущена но есть флаг1 и при этом счётчик >= порога и нет флага удержания - фиксируем нажатие.
+сьросим флаг1, счётчик времени.
+
+флаги 2 и 3 сбросят п/п обработки
+
+
+кнопка нажата
+	флаг1 есть?
+		нет: установим и дальше
+		да: считаем время нажатия
+	переполнилось время нажатия?
+		да: удержание. ставим флаг3,
+
+кнопка отпущена
+	время нажатия >= 0.5сек?
+		да: есть флаг 3?
+			нет: ставим флаг2
+	сбросим флаг1, сбросим время нажатия
+
+	; *** начало бработки кнопки ***
+	sbic	ButPort,BTN1	; кнопка 1 нажата?
+	rjmp	T0L2		; нет, на обработку ненажатой кнопки
+	sbrs	flagb,BTN1P	; была нажата раньше?
+	rjmp	T0L4		; нет, вкл флаг и дальше...
+	inc	TIKB		; да, увеличим счётчик
+	brne	T0L3		; переполнения нет - на выход
+	mov	temp,flagb	; переполнение...
+	sbi	temp,1<<BTN1H
+	mov	flagb,temp	; установили флаг удержания
+	rjmp	T0L3		; дальше...
+T0L2:	sbrs	flagb,BTN1P	; кнопка не нажата
+	rjmp	T0L5
+	ldi	temp,64		; ~0.5 сек
+	cp	TIKB,temp	; тики достигли порога срабатывания?
+	brlo	T0L5		; нет, на очистку
+	mov	temp,flagb	; да, ставим флаг
+	cbi	temp,1<<BTN1R
+	mov	flagb,temp	; установили флаг отпускания
+T0L5:	clr	TIKB		; очистим тики кнопок
+	mov	temp,flagb
+	cbi	temp,1<<BTN1P
+	mov	flagb,temp	; сбросили флаг нажатия
+	rjmp	T0L3		; дальше...
+T0L4:	sbi	temp,1<<BTN1P
+	mov	flagb,temp	; установили флаг нажатия
+	; *** закончили обратоку кнопки ***
+T0L3:
+
+===============================================
+каждый раз -- всё с начала, нихера не помню, нихера не выходит...
+
+ещё раз:
+
+предположим, опрос кнопки идёт в таймере с периодичнойстью 1-10 мс.
+пороги -- антидребезг = 50 мс, срабатывания = 100 мс, длинное нажатие =
+500 мс, удержание = 2 с.
+
+опрос кнопок:
+  кнопка нажата (
+     если флага нет (
+	если счётчик достиг порога срабатывания (
+	  ставим флага нажатия
+	  очищаем счётчик	// можно не делать.
+	) если не достиг (
+	  увеличиваем счётчик
+	)
+     ) если флаг есть (
+	если счётчик меньше времени удержания (
+	    увеличиваем счётчик
+	)
+     )
+  ) если кнопка не нажата (
+     если флаг есть (
+	сбросить флаг
+	если счётчик меньше времени срабатывания (
+	  очистить счётчик
+	)
+     ) если флага нет (
+	 очистить счётчик
+     )
+  )
+// 10 проверок, 7(6) действий
+
+
+обработка кнопок:
+  тут просто проверяем время нажатия/удержания.
+  сначала двойные комбинации, потом одиночные.
+  непонятно как обрабатывать удержание, если должна быть реакция и на
+  нажатие...
+
+кроме того -- ещё нужен обратный счётчик.
+после фиксации факта срабатывания или отпускания -- заводим счётчик паузы,
+и пока он не дотикает до 0 -- кнопку не обрабатываем.
+
+
+по факту, из Печки, обработка текущеё кнопки:
+
+if(BTN[i].Pause == 0) { // текущая кнопка на паузе?
+
+  // нет, продолжаем
+  if (bit_is_clear(BTN_PIN,BTN[i].bit)) { // кнопка нажата
+    if (bit_is_clear(BTN[i].flg,PRESSED)) { // флага нет
+      if (BTN[i].Count >= BTN_Treshold) { // счётчик достиг антидребезга?
+        SetBit(BTN[i].flg,PRESSED); // да. ставим флаг
+      } else {
+        BTN[i].Count ++; // не достиг. увеличим счётчик
+      }
+    } else { // флаг уже есть -- антидребезг отработали
+      if (BTN[i].Count < BTN_Holded) { // счётчик меньше времени удержания?
+        BTN[i].Count ++; // увеличиваем счётчик
+      }
+    }
+  } else { // кнопка не нажата
+    if (bit_is_set(BTN[i].flg,PRESSED)) { // флаг есть
+      ResBit(BTN[i].flg,PRESSED); // и сбросим флаг
+      if (BTN[i].Count < BTN_Pressed) { // счётчик
+        BTN[i].Count = 0; // очистим счётчик
+      }
+    } else {
+      BTN[i].Count = 0; // очистим счётчик
+    }
+  }
+
+} else { // на паузе. уменьшаем счётчик
+  BTN[i].Pause --;
+}
+
+в обработчике кнопка обрабатывается если есть флаг и счётчик, сбрасывается
+счётчик кнопки и устанавливается счётчик паузы.

+ 35 - 0
ln.txt

@@ -0,0 +1,35 @@
+лографим от 1 до 256 (растущий-выпуклый), для 0 == - бесконечность
+0,31,50,63,74,82,89,95,101,105,110,114,117,121,124,127,
+130,132,135,137,140,142,144,146,148,149,151,153,154,156,157,159,
+160,162,163,164,166,167,168,169,170,171,172,174,175,176,177,178,
+178,179,180,181,182,183,184,185,185,186,187,188,189,189,190,191,
+191,192,193,194,194,195,196,196,197,197,198,199,199,200,200,201,
+202,202,203,203,204,204,205,205,206,206,207,207,208,208,209,209,
+210,210,211,211,212,212,213,213,214,214,214,215,215,216,216,216,
+217,217,218,218,218,219,219,220,220,220,221,221,222,222,222,223,
+223,223,224,224,224,225,225,225,226,226,226,227,227,227,228,228,
+228,229,229,229,230,230,230,231,231,231,231,232,232,232,233,233,
+233,233,234,234,234,235,235,235,235,236,236,236,236,237,237,237,
+238,238,238,238,239,239,239,239,240,240,240,240,241,241,241,241,
+242,242,242,242,242,243,243,243,243,244,244,244,244,245,245,245,
+245,245,246,246,246,246,246,247,247,247,247,248,248,248,248,248,
+249,249,249,249,249,250,250,250,250,250,251,251,251,251,251,252,
+252,252,252,252,252,253,253,253,253,253,254,254,254,254,254,255
+
+экспонента от 0 до 255 (растущий-вогнутый), для 256 == + бексконечность
+0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,
+2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,
+6,6,6,6,6,7,7,7,7,8,8,8,8,8,9,9,
+9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,12,
+13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,
+17,17,17,18,18,18,18,19,19,19,19,20,20,20,21,21,
+21,21,22,22,22,23,23,23,23,24,24,24,25,25,25,26,
+26,26,27,27,27,28,28,28,29,29,29,30,30,30,31,31,
+31,32,32,32,33,33,34,34,34,35,35,36,36,36,37,37,
+38,38,38,39,39,40,40,40,41,41,42,42,43,43,44,44,
+45,45,46,46,47,47,48,48,49,49,50,50,51,51,52,52,
+53,54,54,55,55,56,57,57,58,58,59,60,60,61,62,63,
+63,64,65,65,66,67,68,69,69,70,71,72,73,74,75,76,
+76,77,78,79,80,82,83,84,85,86,87,88,90,91,92,94,
+95,97,98,100,101,103,105,106,108,110,112,114,117,119,122,124,
+127,130,133,137,140,144,149,153,159,165,172,180,191,204,223,255

+ 21 - 0
median_filter.c

@@ -0,0 +1,21 @@
+// http://electronix.ru/forum/index.php?showtopic=114436&view=findpost&p=1180944
+
+datatype median( datatype array, int length)  // массив и его длина
+{
+    int  slit = length/2;
+
+    for( int i=0; i < length; i++) {
+        int s1=0, s2=0;
+        datatype val = array[i];
+        for( int j=0; j < length; j++) {
+            if( array[j] < val) {
+                if( ++s1 > slit) break;
+            } else if( array[j] > val) {
+                if( ++s2 > slit) break;
+            }
+        }
+        return val;
+    }
+
+    return 0;  // чистая формальность, досюда исполнение никогда не доходит
+}

+ 327 - 0
printf.c

@@ -0,0 +1,327 @@
+/** \file printf.c
+ * Simplified printf() and sprintf() implementation - prints formatted string to
+ * USART (or whereever). Most common % specifiers are supported. It costs you about
+ * 3k FLASH memory - without floating point support it uses only 1k ROM!
+ * \author Freddie Chopin, Martin Thomas, Marten Petschke and many others
+ * \date 16.2.2012
+ */
+
+/******************************************************************************
+* chip: STM32F10x
+* compiler: arm-none-eabi-gcc 4.6.0
+*
+* global functions:
+* 	int printf_(const char *format, ...)
+* 	int sprintf_(char *buffer, const char *format, ...)
+*
+* STM32 specific functions:
+*         init_UART1(void)
+*	void putc_UART1 (char);                // blocking put char, used by printf()
+*
+* local functions:
+* 	int putc_strg(int character, printf_file_t *stream)
+* 	int vfprintf_(printf_file_t *stream, const char *format, va_list arg)
+* 	void long_itoa (long val, int radix, int len, vfprintf_stream *stream)
+*
+******************************************************************************/
+
+/*
++=============================================================================+
+| includes
++=============================================================================+
+*/
+
+//#include <stdarg.h>     // (...) parameter handling
+//#include "config.h"     // select controller type, frequency plan
+
+//#include "stm32f10x.h"	// only this STM headerfile is used
+
+/*
++=============================================================================+
+| options
++=============================================================================+
+*/
+#define INCLUDE_FLOAT  // this enables float in printf() and costs you about 2kByte ROM
+//#define UART1_BAUDRATE  		115200
+/*
++=============================================================================+
+| global declarations
++=============================================================================+
+*/
+
+//int printf_(const char *format, ...);
+int sprintf_(char *buffer, const char *format, ...);
+
+/*
++=============================================================================+
+| local declarations
++=============================================================================+
+*/
+
+//void init_UART1(void);          // STM32 specific stuff
+
+//void putc_UART1 (char);         // blocking put char; used by printf_()
+//void putc_strg(char);          // the put() function for sprintf()
+char *SPRINTF_buffer;          //
+
+static int vfprintf_(void (*) (char), const char *format, va_list arg); //generic print
+void long_itoa (long, int, int, void (*) (char)); //heavily used by printf_()
+
+/*
++=============================================================================+
+| sample main()  file
++=============================================================================+
+*/
+/*
+int main(void){
+   pll_start();
+	init_UART1();
+   printf_("\nSTM32_Start\n");
+	int cnt;
+   for (cnt = 0; cnt < 12; cnt++)	// test
+      printf_("test unsigned negativ:      |%u|  \n", (unsigned int)(-cnt));
+
+   char s[30];
+   sprintf_(s,"Hallo!\n"); printf_("%s",s);
+
+#ifdef INCLUDE_FLOAT
+   float f=3.14f;
+
+   printf_("test float %3f,  negativ:  %f  \n", f, -f);
+#endif
+
+   return 1;
+}
+*/
+/*
++=============================================================================+
+| STM32 register definition only here and in interrupt handler
++=============================================================================+
+
+void init_UART1(void){
+
+	RCC->APB2ENR |= ( RCC_APB2ENR_IOPAEN |RCC_APB2ENR_AFIOEN | RCC_APB2ENR_USART1EN);  //Clock
+	AFIO->MAPR &= ~(AFIO_MAPR_USART1_REMAP);		//UART1 at the original pins
+	GPIOA->CRH  = 0x0090;
+   USART1->BRR  = (APB2CLK + UART1_BAUDRATE/2)/UART1_BAUDRATE;
+	             //0x008B;  Baud=FREQUENCY/(16*8,69)=115107;	// BRR simplified thanks to Uwe Hermann
+   USART1->CR1 |= (USART_CR1_RE | USART_CR1_TE | USART_CR1_UE);  // RX, TX enable
+}
+
+void putc_UART1 (char c)
+{
+	if (c == '\n') {
+		while ((USART1->SR & USART_SR_TXE) == 0);  //blocks until previous byte was sent
+		USART1->DR ='\r';
+	}
+	while ((USART1->SR & USART_SR_TXE) == 0);  //blocks until previous byte was sent
+	USART1->DR = c;
+}
+*/
+/*
++=============================================================================+
+| end of controller specific stuff  - no further controller dependent stuff below
++=============================================================================+
+*/
+
+/*
++=============================================================================+
+| global functions
++=============================================================================+
+
+int printf_(const char *format, ...)
+{
+	va_list arg;
+
+	va_start(arg, format);
+	vfprintf_((&putc_UART1), format, arg);
+	va_end(arg);
+
+	return 0;
+}
+*/
+int sprintf_(char *buffer, const char *format, ...)
+{
+	va_list arg;
+
+	SPRINTF_buffer=buffer;	 //Pointer auf einen String in Speicherzelle abspeichern
+
+	va_start(arg, format);
+	vfprintf_((&putc_strg), format, arg);
+	va_end(arg);
+
+	*SPRINTF_buffer ='\0';             // append end of string
+
+	return 0;
+}
+
+
+/*
++=============================================================================+
+| local functions
++=============================================================================+
+*/
+// putc_strg() is the putc()function for sprintf_()
+void putc_strg(char character)
+{
+	*SPRINTF_buffer = (char)character;	// just add the character to buffer
+	 SPRINTF_buffer++;
+
+}
+
+/*--------------------------------------------------------------------------------+
+ * vfprintf_()
+ * Prints a string to stream. Supports %s, %c, %d, %ld %ul %02d %i %x  %lud  and %%
+ *     - partly supported: long long, float (%ll %f, %F, %2.2f)
+ *     - not supported: double float and exponent (%e %g %p %o \t)
+ *--------------------------------------------------------------------------------+
+*/
+static int vfprintf_(void (*putc)(char), const char* str,  va_list arp)
+{
+	int d, r, w, s, l;  //d=char, r = radix, w = width, s=zeros, l=long
+	char *c;            // for the while loop only
+
+#ifdef INCLUDE_FLOAT
+	float f;
+	long int m, mv, p, w2;
+#endif
+
+	while ((d = *str++) != 0) {
+		if (d != '%') {
+			(*putc)(d);
+			continue;
+		}
+		d = *str++;
+		w = r = s = l = 0;
+		if (d == '%') {
+			(*putc)(d);
+			d = *str++;
+		}
+		if (d == '0') {
+			d = *str++; s = 1;  //padd with zeros
+		}
+		while ((d >= '0')&&(d <= '9')) {
+			w += w * 10 + (d - '0');
+			d = *str++;
+		}
+		if (s) w = -w;      //padd with zeros if negative
+
+	#ifdef INCLUDE_FLOAT
+		w2 = 2;            //default decimal places=2
+		if (d == '.'){
+			d = *str++; w2 = 0; }
+		while ((d >= '0')&&(d <= '9')) {
+			w2 += w2 * 10 + (d - '0');
+			d = *str++;
+		}
+	#endif
+
+		if (d == 's') {
+			c = va_arg(arp, char*);
+			while (*c)
+				(*putc)(*(c++));
+			continue;
+		}
+		if (d == 'c') {
+			(*putc)((char)va_arg(arp, int));
+			continue;
+		}
+		if (d == 'u') {     // %ul
+			r = 10;
+			d = *str++;
+		}
+		if (d == 'l') {     // long =32bit
+			l = 1;
+			if (r==0) r = -10;
+			d = *str++;
+		}
+		if (d =='\0') break;    //avoid crashing if format string is buggy
+		if (d == 'u') r = 10;//     %lu,    %llu
+		else if (d == 'd' || d == 'i') {if (r==0) r = -10;}  //can be 16 or 32bit int
+		else if (d == 'X' || d == 'x') r = 16;               // 'x' added by mthomas
+		else if (d == 'b') r = 2;
+   #ifdef INCLUDE_FLOAT
+		else if (d == 'f' || d == 'F') {
+			f=va_arg(arp, double);
+			if (f >= 0.0) {
+				r = 10;
+            mv = f;
+            m = mv;
+			}
+			else {
+				r = -10;
+            mv = f;
+				f = -f;
+            m = f;              // f and m are always positive
+			}
+			long_itoa(mv, r, w, (putc));
+			if (w2!=0) {
+            putc('.');
+            f=f-m;
+            w=-w2; p=1;
+            while (w2--) p = p*10;
+            m=f*p;
+            long_itoa(m, 10, w, (putc));
+			}
+			l=3; //do not continue with long
+		}
+	#endif
+		else str--;                                         // normal character
+
+		if (r==0) continue;  //
+		if (l==0) {
+			if (r > 0){      //unsigned
+				long_itoa((unsigned long)va_arg(arp, int), r, w, (putc)); //needed for 16bit int, no harm to 32bit int
+			}
+			else            //signed
+				long_itoa((long)va_arg(arp, int), r, w, (putc));
+		} else if (l==1){  // long =32bit
+				long_itoa((long)va_arg(arp, long), r, w, (putc));        //no matter if signed or unsigned
+		}
+	}
+
+	return 0;
+}
+
+
+void long_itoa (long val, int radix, int len, void (*putc) (char))
+{
+	char c, sgn = 0, pad = ' ';
+	char s[20];
+	int  i = 0;
+
+
+	if (radix < 0) {
+		radix = -radix;
+		if (val < 0) {
+			val = -val;
+			sgn = '-';
+		}
+	}
+	if (len < 0) {
+		len = -len;
+		pad = '0';
+	}
+	if (len > 20) return;
+	do {
+		c = (char)((unsigned long)val % radix); //cast!
+		if (c >= 10) c += ('A'-10); //ABCDEF
+		else c += '0';            //0123456789
+		s[i++] = c;
+		val = (unsigned long)val /radix; //cast!
+	} while (val);
+
+	if ((sgn!=0) && (pad!='0')) s[i++] = sgn;
+	while (i < len)
+		s[i++] = pad;
+	if ((sgn!=0) && (pad=='0')) s[i++] = sgn;
+
+	do
+		(*putc)(s[--i]);
+	while (i);
+}
+
+
+/******************************************************************************
+* END OF FILE
+******************************************************************************/

+ 252 - 0
printf.h

@@ -0,0 +1,252 @@
+/** \file printf.c
+ * Simplified printf() and sprintf() implementation - prints formatted string to
+ * USART (or whereever). Most common % specifiers are supported. It costs you about
+ * 3k FLASH memory - without floating point support it uses only 1k ROM!
+ * \author Freddie Chopin, Martin Thomas, Marten Petschke and many others
+ * \date 16.2.2012
+ * Get from http://www.firefly-power.de/ARM/printf.html
+ */
+
+/******************************************************************************
+* chip: STM32F10x
+* compiler: arm-none-eabi-gcc 4.6.0
+*
+* global functions:
+* 	int printf_(const char *format, ...)
+* 	int sprintf_(char *buffer, const char *format, ...)
+*
+* STM32 specific functions:
+*         init_UART1(void)
+*	void putc_UART1 (char);                // blocking put char, used by printf()
+*
+* local functions:
+* 	int putc_strg(int character, printf_file_t *stream)
+* 	int vfprintf_(printf_file_t *stream, const char *format, va_list arg)
+* 	void long_itoa (long val, int radix, int len, vfprintf_stream *stream)
+*
+******************************************************************************/
+
+/*
++=============================================================================+
+| includes
++=============================================================================+
+*/
+
+#include <stdarg.h>     // (...) parameter handling
+
+/*
++=============================================================================+
+| options
++=============================================================================+
+*/
+//#define INCLUDE_FLOAT  // this enables float in printf() and costs you about 2kByte ROM
+
+/*
++=============================================================================+
+| global declarations
++=============================================================================+
+*/
+
+int sprintf_(char *buffer, const char *format, ...);
+
+/*
++=============================================================================+
+| local declarations
++=============================================================================+
+*/
+
+void putc_strg(char);          // the put() function for sprintf()
+char *SPRINTF_buffer;          //
+
+static int vfprintf_(void (*) (char), const char *format, va_list arg); //generic print
+void long_itoa (long, int, int, void (*) (char)); //heavily used by printf_()
+
+/*
++=============================================================================+
+| global functions
++=============================================================================+
+*/
+
+int sprintf_(char *buffer, const char *format, ...)
+{
+	va_list arg;
+
+	SPRINTF_buffer=buffer;	 //Pointer auf einen String in Speicherzelle abspeichern
+
+	va_start(arg, format);
+	vfprintf_((&putc_strg), format, arg);
+	va_end(arg);
+
+	*SPRINTF_buffer ='\0';             // append end of string
+
+	return 0;
+}
+
+/*
++=============================================================================+
+| local functions
++=============================================================================+
+*/
+// putc_strg() is the putc() function for sprintf_()
+void putc_strg(char character)
+{
+	*SPRINTF_buffer = (char)character;	// just add the character to buffer
+	 SPRINTF_buffer++;
+}
+
+/*--------------------------------------------------------------------------------+
+ * vfprintf_()
+ * Prints a string to stream. Supports %s, %c, %d, %ld %ul %02d %i %x  %lud  and %%
+ *     - partly supported: long long, float (%ll %f, %F, %2.2f)
+ *     - not supported: double float and exponent (%e %g %p %o \t)
+ *--------------------------------------------------------------------------------+
+*/
+static int vfprintf_(void (*putc)(char), const char* str,  va_list arp)
+{
+	int d, r, w, s, l;  //d=char, r = radix, w = width, s=zeros, l=long
+	char *c;            // for the while loop only
+
+#ifdef INCLUDE_FLOAT
+	float f;
+	long int m, mv, p, w2;
+#endif
+
+	while ((d = *str++) != 0) {
+		if (d != '%') {
+			(*putc)(d);
+			continue;
+		}
+		d = *str++;
+		w = r = s = l = 0;
+		if (d == '%') {
+			(*putc)(d);
+			d = *str++;
+		}
+		if (d == '0') {
+			d = *str++; s = 1;  //padd with zeros
+		}
+		while ((d >= '0')&&(d <= '9')) {
+			w += w * 10 + (d - '0');
+			d = *str++;
+		}
+		if (s) w = -w;      //padd with zeros if negative
+
+	#ifdef INCLUDE_FLOAT
+		w2 = 2;            //default decimal places=2
+		if (d == '.'){
+			d = *str++; w2 = 0; }
+		while ((d >= '0')&&(d <= '9')) {
+			w2 += w2 * 10 + (d - '0');
+			d = *str++;
+		}
+	#endif
+
+		if (d == 's') {
+			c = va_arg(arp, char*);
+			while (*c)
+				(*putc)(*(c++));
+			continue;
+		}
+		if (d == 'c') {
+			(*putc)((char)va_arg(arp, int));
+			continue;
+		}
+		if (d == 'u') {     // %ul
+			r = 10;
+			d = *str++;
+		}
+		if (d == 'l') {     // long =32bit
+			l = 1;
+			if (r==0) r = -10;
+			d = *str++;
+		}
+		if (d =='\0') break;    //avoid crashing if format string is buggy
+		if (d == 'u') r = 10;//     %lu,    %llu
+		else if (d == 'd' || d == 'i') {if (r==0) r = -10;}  //can be 16 or 32bit int
+		else if (d == 'X' || d == 'x') r = 16;               // 'x' added by mthomas
+		else if (d == 'b') r = 2;
+   #ifdef INCLUDE_FLOAT
+		else if (d == 'f' || d == 'F') {
+			f=va_arg(arp, double);
+			if (f >= 0.0) {
+				r = 10;
+            mv = f;
+            m = mv;
+			}
+			else {
+				r = -10;
+            mv = f;
+				f = -f;
+            m = f;              // f and m are always positive
+			}
+			long_itoa(mv, r, w, (putc));
+			if (w2!=0) {
+            putc('.');
+            f=f-m;
+            w=-w2; p=1;
+            while (w2--) p = p*10;
+            m=f*p;
+            long_itoa(m, 10, w, (putc));
+			}
+			l=3; //do not continue with long
+		}
+	#endif
+		else str--;                                         // normal character
+
+		if (r==0) continue;  //
+		if (l==0) {
+			if (r > 0){      //unsigned
+				long_itoa((unsigned long)va_arg(arp, int), r, w, (putc)); //needed for 16bit int, no harm to 32bit int
+			}
+			else            //signed
+				long_itoa((long)va_arg(arp, int), r, w, (putc));
+		} else if (l==1){  // long =32bit
+				long_itoa((long)va_arg(arp, long), r, w, (putc));        //no matter if signed or unsigned
+		}
+	}
+
+	return 0;
+}
+
+
+void long_itoa (long val, int radix, int len, void (*putc) (char))
+{
+	char c, sgn = 0, pad = ' ';
+	char s[20];
+	int  i = 0;
+
+
+	if (radix < 0) {
+		radix = -radix;
+		if (val < 0) {
+			val = -val;
+			sgn = '-';
+		}
+	}
+	if (len < 0) {
+		len = -len;
+		pad = '0';
+	}
+	if (len > 20) return;
+	do {
+		c = (char)((unsigned long)val % radix); //cast!
+		if (c >= 10) c += ('A'-10); //ABCDEF
+		else c += '0';            //0123456789
+		s[i++] = c;
+		val = (unsigned long)val /radix; //cast!
+	} while (val);
+
+	if ((sgn!=0) && (pad!='0')) s[i++] = sgn;
+	while (i < len)
+		s[i++] = pad;
+	if ((sgn!=0) && (pad=='0')) s[i++] = sgn;
+
+	do
+		(*putc)(s[--i]);
+	while (i);
+}
+
+
+/******************************************************************************
+* END OF FILE
+******************************************************************************/

+ 1 - 0
stm32/ReadMe.txt

@@ -0,0 +1 @@
+STM32 сепецифичные вещи.

+ 70 - 0
stm32/delay_us_systick.c

@@ -0,0 +1,70 @@
+/*
+ * http://chipspace.ru/stm32-systick/
+ */
+
+#include "stm32f10x.h"
+
+static __IO uint32_t TimingDelay;
+
+void Delay_ms(__IO uint32_t nTime);
+
+GPIO_InitTypeDef    GPIO_InitStruct;
+
+int main()
+{
+  /*Вызов функции конфигурации системного таймера SysTick.
+  Эта функция находится в файле core_cm3.h и:
+  --Задает источник тактирования системного таймера (по умолчанию это SYSCLK = 24 МГц,
+    другой возможный вариант  - SysTick тактируется от SYSCLK/8);
+  --Задает уровень приоритета прерывания;
+  --Сбрасывает флаг ожидания прерывания, если он выставлен;
+  --Заносит в нужный регистр перезагружаемое значение для декрементирующего счетчика,
+    которое вычисляется по формуле:
+        Reload Value = SysTick Counter Clock (Hz) x  Desired Time base (s),
+        для базовой задержки длительностью 1 мс получим величину
+        Reload Value = 24 000 000 Гц х 0,001 с = 24 000
+    (Необходимо самостоятельно посчитать эту величину и вставить в качестве
+    параметра при вызове функции);
+  --Обнуляет счетчик
+  --Запускает счет системного таймера*/
+  SysTick_Config(24000);
+
+  //Включаем тактирование порта GPIOC
+  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
+  //Конфигурируем выводы, к которым подключены светодиоды платы
+  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; //Выбираем выводы PC8, PC9
+  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //Максимальная скорость работы
+  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //Выход Push-Pull
+  GPIO_Init(GPIOC, &GPIO_InitStruct); //Заносим заданные настройки в регистры порта
+
+  while(1)
+  {
+    GPIO_ResetBits(GPIOC, GPIO_Pin_9); //Гасим зеленый LED
+    GPIO_SetBits(GPIOC, GPIO_Pin_8);   //Зажигаем синий LED
+    Delay_ms(1000); //Временная задержка на 1 с
+    GPIO_ResetBits(GPIOC, GPIO_Pin_8); //Гасим синий LED
+    GPIO_SetBits(GPIOC, GPIO_Pin_9);   //Зажигаем зеленый LED
+    Delay_ms(1000); //Временная задержка на 1 с
+  }
+}
+
+//Функция временной задержки
+void Delay_ms(__IO uint32_t nTime)
+{
+  TimingDelay = nTime;
+  while(TimingDelay != 0);
+}
+
+void TimingDelay_Decrement(void)
+{
+  if (TimingDelay != 0x00)
+  {
+    TimingDelay--;
+  }
+}
+
+//Обработчик прерывания системного таймера
+void SysTick_Handler(void)
+{
+  TimingDelay_Decrement();
+}

+ 54 - 0
stm32/gpio.c

@@ -0,0 +1,54 @@
+/****************************gpio.c*********************************/
+// http://microtechnics.ru/stm32-uchebnyj-kurs-gpio-porty-vvoda-vyvoda/
+//Подключаем все нужные файлы
+#include "stm32f10x.h"
+#include "stm32f10x_rcc.h"
+#include "stm32f10x_gpio.h"
+/*******************************************************************/
+//Тут будет вся инициализация всей использующейся периферии
+void initAll()
+{
+    //Объявляем переменную port типа GPIO_InitTypeDef
+    GPIO_InitTypeDef port;
+    //Это функция из файла stm32f10x_rcc.c, включает тактирование на GPIOA
+    //GPIOA сидит на шине APB2
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
+    //Про эту функцию напишу чуть ниже
+    GPIO_StructInit(&port);
+    //Заполняем поля структуры нужными значениями
+    //Первый вывод – вход для обработки нажатия кнопки – PA1
+    port.GPIO_Mode = GPIO_Mode_IPD;
+    port.GPIO_Pin = GPIO_Pin_1;
+    port.GPIO_Speed = GPIO_Speed_2MHz;
+    //А про эту функцию мы уже говорили
+    //Отметим только что один из параметров – указатель(!) на
+    //нашу структуру
+    GPIO_Init(GPIOA, &port);
+    //Настраиваем вывод, на котором будет висеть диодик – PA0
+    port.GPIO_Mode = GPIO_Mode_Out_PP;
+    port.GPIO_Pin = GPIO_Pin_0;
+    port.GPIO_Speed = GPIO_Speed_2MHz;
+    GPIO_Init(GPIOA, &port);
+}
+/*******************************************************************/
+int main()
+{
+    //Объявляем переменную для хранения состояния кнопки
+    uint8_t buttonState = 0;
+    initAll();
+    while(1)
+    {
+        //С помощью функции из SPL считываем из внешнего мира
+        //состояние кнопки
+        buttonState = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1);
+        if (buttonState == 1)
+        {
+            GPIO_SetBits(GPIOA, GPIO_Pin_0);
+        }
+        else
+        {
+            GPIO_ResetBits(GPIOA, GPIO_Pin_0);
+        }
+    }
+}
+/****************************End of file****************************/

+ 66 - 0
stm32/pwm.c

@@ -0,0 +1,66 @@
+/*
+ * http://chipspace.ru/httpchipspace-rustm32-general-purpose-timers-3-pwm-stdperiph_lib/
+ */
+
+#include "stm32l1xx.h"
+
+GPIO_InitTypeDef GPIO_InitStructure;
+TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+TIM_OCInitTypeDef TIM_OCInitStructure;
+
+uint16_t F_output = 1000;//Частота выходного сигнала, Гц (задается)
+uint16_t duty_cycle = 10;//Коэффициент заполнения (duty cycle), от 0% до 100% (задается)
+uint16_t AutoReload_Value = 0;//Значение для записи в регистр TIM2_ARR (определяет период сигнала PWM, вычисляется в программе)
+uint16_t Pulse_Length = 0;//Значение для записи в регистр TIM2_CCR1 (определяет длительность импульса сигнала PWM, вычисляется в программе)
+
+int main()
+ {
+  /*Обновляем значение переменной SystemCoreClock - системной тактовой частоты, понадобится при дальнейших вычислениях*/
+  SystemCoreClockUpdate();
+
+  //Инициализация порта
+  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //Включаем тактирование GPIOA
+
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//Настраивать будем вывод PA0
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//Выход, альтернативная функция
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//Push-Pull - двухтактный
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//Без подтягивающих резисторов
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;//Работает на максимальной частоте
+  GPIO_Init(GPIOA, &GPIO_InitStructure);//Прописываем в регистры заданные значения
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2);//PA0 подключаем к TIM2
+
+  //Инициализация таймера TIM2
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//Включаем тактирование TIM2
+  /*Расчет значения для регистра автоперезагрузки, которым задается периoд сигнала PWM*/
+  AutoReload_Value = (uint16_t) (SystemCoreClock/F_output) - 1;
+  //Расчет значения для регистра CCR1, которым задается длительность импульса
+  Pulse_Length = (uint16_t) ((AutoReload_Value*duty_cycle)/100);
+
+  //Инициализация модуля Time base unit
+  /*Задаем коэффициенты деления внешних предделителей тактовой частоты.
+  В данном случае делители не используются,
+  входная частота таймера равна системной частоте*/
+  TIM_TimeBaseStructure.TIM_Prescaler = 0;
+  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
+  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//Направление счета - инкремент
+  /*Указываем, что в TIM2_ARR необходимо записать
+  вычисленное значение для нужного периода сигнала*/
+  TIM_TimeBaseStructure.TIM_Period = AutoReload_Value;
+  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//Записываем все заданные выше значения в регистры
+
+ //Настройка канала Capture/Compare для формирования PWM сигнала на выходе
+  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//Режим PWM1
+  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//Разрешаем подключение к выводу мк
+ /*Указываем, что в TIM2_CCR1 необходимо записать
+  вычисленное значение для нужной длительности импульса*/
+  TIM_OCInitStructure.TIM_Pulse = Pulse_Length;
+  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//Положительная полярность
+  TIM_OC1Init(TIM2, &TIM_OCInitStructure);//Записываем все заданные выше значения в регистры
+
+  TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);//Разрешаем предварительную загрузку регистра сравнения
+  TIM_ARRPreloadConfig(TIM2, ENABLE);//Разрешаем предварительную загрузку регистра автоперезагрузки
+  /* TIM2 enable counter */
+  TIM_Cmd(TIM2, ENABLE);//Запускаем счет таймера
+
+  while (1);
+ }

+ 35 - 0
stm32/spi.c

@@ -0,0 +1,35 @@
+/*
+   STM32: SPI: LCD — Вы всё делаете не так !
+   https://habrahabr.ru/post/276605/
+*/
+
+// передача данных на дисплей
+void SPI2_SendByte(uint8_t sendData)
+{
+  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
+  SPI_I2S_SendData(SPI2, sendData);
+}
+
+// определение области для вывода
+void ili9341c_SetWindow(uint16_t ystart, uint16_t xstart, uint16_t yend, uint16_t xend)
+{
+. . .
+  GPIO_ResetBits(GPIOB, GPIO_Pin_12); // DC=0;
+
+  SPI2_SendByte(LCD_PAGE_ADDR);
+
+  //ждем пока команда уйдет на дисплей (а не перейдет в shift reg)
+  while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
+
+  GPIO_SetBits(GPIOB, GPIO_Pin_12); // DC=1;
+
+  SPI2_SendByte(xstart>>8);	// данные
+  SPI2_SendByte(xstart&0xFF);	// передаются
+  SPI2_SendByte(xend>>8);	// в непрерывном
+  SPI2_SendByte(xend&0xFF);	// режиме без пауз !
+
+  // ждем пока данные передадутся до конца
+  while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
+
+. . .
+}

+ 204 - 0
stm8/Makefile.stm8l

@@ -0,0 +1,204 @@
+#########################
+# IAR Makefile for STM8 #
+#########################
+
+# Взял из проекта atomthreads и переиначил.
+
+# Location of build tools and atomthreads sources
+EWSTM8_DIR=C:\IAR\Embedded Workbench 7.0\stm8
+APP_SRC=src
+APP_INC=inc
+PERIPHS_SRC=StdPerphDrv/src
+PERIPHS_INC=StdPerphDrv/inc
+EWSTM8_BIN=C:/IAR/Embedded\ Workbench\ 7.0/stm8/bin
+CC=$(EWSTM8_BIN)/iccstm8
+ASM=$(EWSTM8_BIN)/iasmstm8
+LINK=$(EWSTM8_BIN)/ilinkstm8
+HEX=$(EWSTM8_BIN)/ielftool
+
+PROJECT=VAPC
+
+# CPU part number
+PART = STM8L05X_LD_VL
+ICF = lnkstm8l051f3.icf
+LIB_MODEL = dlstm8ssn.h
+
+# Directory for built objects
+OUT_DIR = Out
+OBJ_DIR = $(OUT_DIR)/Obj
+LIST_DIR = $(OUT_DIR)/List
+CODE_MODEL = small
+DATA_MODEL = small
+
+# Application object files
+#APP_OBJECTS = board.o delay.o HD44780.o stm8l15x_it.o
+APP_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(APP_SRC)/*.c)))
+#APP_ASM_OBJECTS = atomport-asm-iar.o
+
+# STM8S Peripheral driver object files
+PERIPH_OBJECTS = stm8l15x_adc.o
+#PERIPH_OBJECTS += stm8l15x_aes.o
+#PERIPH_OBJECTS += stm8l15x_beep.o
+PERIPH_OBJECTS += stm8l15x_clk.o
+#PERIPH_OBJECTS += stm8l15x_comp.o
+#PERIPH_OBJECTS += stm8l15x_dac.o
+PERIPH_OBJECTS += stm8l15x_dma.o
+PERIPH_OBJECTS += stm8l15x_exti.o
+#PERIPH_OBJECTS += stm8l15x_flash.o
+PERIPH_OBJECTS += stm8l15x_gpio.o
+#PERIPH_OBJECTS += stm8l15x_i2c.o
+#PERIPH_OBJECTS += stm8l15x_irtim.o
+PERIPH_OBJECTS += stm8l15x_itc.o
+#PERIPH_OBJECTS += stm8l15x_iwdg.o
+#PERIPH_OBJECTS += stm8l15x_lcd.o
+#PERIPH_OBJECTS += stm8l15x_pwr.o
+#PERIPH_OBJECTS += stm8l15x_rst.o
+PERIPH_OBJECTS += stm8l15x_rtc.o
+PERIPH_OBJECTS += stm8l15x_spi.o
+PERIPH_OBJECTS += stm8l15x_syscfg.o
+PERIPH_OBJECTS += stm8l15x_tim1.o
+PERIPH_OBJECTS += stm8l15x_tim2.o
+PERIPH_OBJECTS += stm8l15x_tim3.o
+PERIPH_OBJECTS += stm8l15x_tim4.o
+#PERIPH_OBJECTS += stm8l15x_tim5.o
+PERIPH_OBJECTS += stm8l15x_usart.o
+#PERIPH_OBJECTS += stm8l15x_wfe.o
+#PERIPH_OBJECTS += stm8l15x_wwdg.o
+
+###PERIPH_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(PERIPHS_SRC)/*.c)))
+
+# Kernel object files
+#KERNEL_OBJECTS = atomkernel.o atomsem.o atommutex.o atomtimer.o atomqueue.o
+
+# Collection of built objects (excluding test applications)
+ALL_OBJECTS = $(APP_OBJECTS) $(PERIPH_OBJECTS)
+BUILT_OBJECTS = $(patsubst %,$(OUT_DIR)/%,$(ALL_OBJECTS))
+
+# Test object files (dealt with separately as only one per application build)
+#PROJ_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(APP_SRC)/*.c)))
+#PROJ_OBJECTS = main.o
+
+# Target application filenames (.elf) for each test object
+#PROJ_ELFS = $(patsubst %.o,%.elf,$(PROJ_OBJECTS))
+#PROJ_S19S = $(patsubst %.o,%.s19,$(PROJ_OBJECTS))
+PROJ_ELFS = $(PROJECT).elf
+PROJ_S19S = $(PROJECT).s19
+PROJ_IHEX = $(PROJECT).hex
+
+# Search build/output directory for dependencies
+vpath %.c $(APP_SRC)
+vpath %.c $(PERIPHS_SRC)
+vpath %.o .\$(OBJ_DIR)
+vpath %.elf .\$(OUT_DIR)
+vpath %.hex .\$(OUT_DIR)
+
+# Include paths
+INCLUDES = -I $(APP_INC)
+INCLUDES += -I $(PERIPHS_INC)
+
+# Compiler/Assembler flags
+CFLAGS = -e -Oh
+CFLAGS += --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
+CFLAGS += --dlib_config "$(EWSTM8_DIR)\lib\$(LIB_MODEL)"
+CFLAGS += -D NDEBUG -D $(PART)
+CFLAGS += -lCN $(LIST_DIR) -lBN $(LIST_DIR)
+CFLAGS += --diag_suppress Pa050
+
+DBG_CFLAGS = -e -Ol --no_cse --no_unroll --no_inline --no_code_motion --no_tbaa
+DBG_CFLAGS += --no_cross_call --debug --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
+DBG_CFLAGS += --dlib_config "$(EWSTM8_DIR)\lib\$(LIB_MODEL)" -D $(PART)
+DBG_CFLAGS += -lC $(LIST_DIR) -lB $(LIST_DIR)
+DBG_CFLAGS += --diag_suppress Pa050 
+
+ASMFLAGS = -M'<>' -ld $(OUT_DIR)\list --diag_suppress Pa050 
+ASMFLAGS += --code_model small --data_model small
+
+DBG_ASMFLAGS = -M'<>' -r -ld $(OUT_DIR)\list --diag_suppress Pa050
+DBG_ASMFLAGS += --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
+
+LINKFLAGS = --redirect _Printf=_PrintfTinyNoMb
+LINKFLAGS += --redirect _Scanf=_ScanfSmallNoMb
+LINKFLAGS += --config "$(EWSTM8_DIR)\config\$(ICF)"
+LINKFLAGS += --config_def _CSTACK_SIZE=0x100
+LINKFLAGS += --config_def _HEAP_SIZE=0x100
+LINKFLAGS += --map $(OUT_DIR)
+LINKFLAGS += --entry __iar_program_start
+LINKFLAGS += --merge_duplicate_sections
+LINKFLAGS += --strip
+LINKFLAGS += -f "$(EWSTM8_DIR)\config\math_small.xcl"
+
+DBG_LINKFLAGS = --redirect _Printf=_PrintfTinyNoMb --redirect _Scanf=_ScanfSmallNoMb
+DBG_LINKFLAGS += --config "$(EWSTM8_DIR)\config\$(ICF)" --config_def
+DBG_LINKFLAGS += _CSTACK_SIZE=0x100 --config_def _HEAP_SIZE=0x100
+DBG_LINKFLAGS += --entry __iar_program_start
+
+
+#################
+# Build targets #
+#################
+
+# All tests
+all: $(OUT_DIR) $(PROJ_S19S) $(PROJ_IHEX)
+
+# Make build/output directory
+$(OUT_DIR):
+	mkdir $(OUT_DIR)
+	@mkdir $(OBJ_DIR)
+	@mkdir $(LIST_DIR)
+
+# Test HEX files (one application build for each test)
+$(PROJ_S19S): %.s19: $(PROJECT).elf
+	@echo
+	@echo Building $@
+	@$(HEX) $(OUT_DIR)/$(notdir $<) $(OUT_DIR)/$@ --srec --silent
+
+$(PROJ_IHEX): %.hex: $(PROJECT).elf
+	@echo Building $@
+	@$(HEX) $(OUT_DIR)/$(notdir $<) $(OUT_DIR)/$@ --ihex --silent
+
+# Test ELF files (one application build for each test)
+$(PROJ_ELFS): %.elf: $(PERIPH_OBJECTS) $(APP_OBJECTS)
+	@echo
+	@echo Linking $@
+	@$(LINK) $(OBJ_DIR)/*.o $(LINKFLAGS) -o $(OUT_DIR)/$@
+#	$(LINK) $(OUT_DIR)/$(notdir $<) $(BUILT_OBJECTS) $(LINKFLAGS) -o $(OUT_DIR)/$@
+
+# Kernel objects builder
+#$(KERNEL_OBJECTS): %.o: $(KERNEL_DIR)/%.c
+#	@echo Compiling $@
+#	$(CC) $< $(CFLAGS) -I . -I $(PERIPHS_SRC) -o $(OUT_DIR)
+
+# Project objects builder
+#$(PROJ_OBJECTS): %.o: main.c
+#	@echo Compiling $@
+#	$(CC) $< $(CFLAGS) $(INCLUDES) -o $(OBJ_DIR)
+
+# Peripheral objects builder
+#$(PERIPH_OBJECTS): %.o: %.c
+#	@echo
+#	@echo Compiling $@
+#	@$(CC) $< $(CFLAGS) $(INCLUDES) -o $(OBJ_DIR)
+
+# Application C objects builder
+#$(APP_OBJECTS): %.o: %.c
+#	@echo
+#	@echo Compiling $@
+#	@$(CC) $< $(CFLAGS) $(INCLUDES) -o $(OBJ_DIR)
+
+# All C objects builder
+$(ALL_OBJECTS): %.o: %.c
+	@echo
+	@echo Compiling $@
+	@$(CC) $< $(CFLAGS) $(INCLUDES) -o $(OBJ_DIR)
+
+# Application asm objects builder
+#$(APP_ASM_OBJECTS): %.o: ./%.s
+#	@echo Compiling $@
+#	@$(ASM) $< $(ASMFLAGS) $(INCLUDES) -o $(OUT_DIR)/$(notdir $@)
+
+# Clean
+clean:
+	rm -f *.o *.elf *.map *.hex *.bin *.lst *.stm8 *.s19 *.out *.s *.lst
+	rm -rf $(LIST_DIR)
+	rm -rf $(OBJ_DIR)
+	rm -rf $(OUT_DIR)

+ 172 - 0
stm8/Makefile.stm8s

@@ -0,0 +1,172 @@
+#########################
+# IAR Makefile for STM8 #
+#########################
+
+# Взял из проекта atomthreads и переиначил.
+
+PROJECT=SoldSt
+
+# Location of build tools and atomthreads sources
+EWSTM8_DIR=C:\IAR\Embedded Workbench 7.0\stm8
+EWSTM8_BIN=C:/IAR/Embedded\ Workbench\ 7.0/stm8/bin
+CC=$(EWSTM8_BIN)/iccstm8
+ASM=$(EWSTM8_BIN)/iasmstm8
+LINK=$(EWSTM8_BIN)/ilinkstm8
+HEX=$(EWSTM8_BIN)/ielftool
+
+APP_SRC = src
+LIB_SRC = lib
+
+# Sources pats
+vpath %.c $(APP_SRC)
+vpath %.c $(LIB_SRC)
+vpath %.c StdPerphDrv/src
+
+# Include paths
+INCLUDES = -I inc
+INCLUDES += -I lib
+INCLUDES += -I StdPerphDrv/inc
+
+# CPU part number
+PART=STM8S103
+ICF=lnkstm8s103k3.icf
+LIB_MODEL = dlstm8ssn.h
+
+# Directory for built objects
+OUT_DIR = Out
+OBJ_DIR = $(OUT_DIR)/Obj
+LIST_DIR = $(OUT_DIR)/List
+
+# Model
+CODE_MODEL = small
+DATA_MODEL = small
+
+# Application object files
+APP_OBJECTS = main.o
+APP_OBJECTS += stm8s_it.o
+#APP_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(APP_SRC)/*.c)))
+
+#APP_ASM_OBJECTS = atomport-asm-iar.o
+
+# Librarys object files
+LIB_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(LIB_SRC)/*.c)))
+
+# STM8S Peripheral driver object files
+PERIPH_OBJECTS = stm8s_adc1.o
+#PERIPH_OBJECTS += stm8s_awu.o
+#PERIPH_OBJECTS += stm8s_beep.o
+PERIPH_OBJECTS += stm8s_clk.o
+PERIPH_OBJECTS += stm8s_exti.o
+#PERIPH_OBJECTS += stm8s_flash.o
+PERIPH_OBJECTS += stm8s_gpio.o
+#PERIPH_OBJECTS += stm8s_i2c.o
+PERIPH_OBJECTS += stm8s_itc.o
+#PERIPH_OBJECTS += stm8s_iwdg.o
+#PERIPH_OBJECTS += stm8s_rst.o
+#PERIPH_OBJECTS += stm8s_spi.o
+PERIPH_OBJECTS += stm8s_tim1.o
+PERIPH_OBJECTS += stm8s_tim2.o
+PERIPH_OBJECTS += stm8s_tim4.o
+PERIPH_OBJECTS += stm8s_uart1.o
+#PERIPH_OBJECTS += stm8s_wwdg.o
+
+###PERIPH_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(PERIPHS_SRC)/*.c)))
+
+# Collection of built objects (excluding test applications)
+ALL_OBJECTS = $(APP_OBJECTS) $(LIB_OBJECTS) $(PERIPH_OBJECTS)
+BUILT_OBJECTS = $(patsubst %,$(OUT_DIR)/%,$(ALL_OBJECTS))
+
+# Target application filenames (.elf) for each test object
+#PROJ_ELFS = $(patsubst %.o,%.elf,$(PROJ_OBJECTS))
+#PROJ_S19S = $(patsubst %.o,%.s19,$(PROJ_OBJECTS))
+PROJ_ELF = $(PROJECT).elf
+PROJ_S19 = $(PROJECT).s19
+PROJ_HEX = $(PROJECT).hex
+
+# Search build/output directory for dependencies
+vpath %.o .\$(OBJ_DIR)
+vpath %.elf .\$(OUT_DIR)
+vpath %.hex .\$(OUT_DIR)
+
+# Compiler/Assembler flags
+CFLAGS = -e -Oh
+CFLAGS += --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
+CFLAGS += --dlib_config "$(EWSTM8_DIR)\lib\$(LIB_MODEL)"
+CFLAGS += -D NDEBUG -D $(PART)
+CFLAGS += -lCN $(LIST_DIR) -lBN $(LIST_DIR)
+CFLAGS += --diag_suppress Pa050
+
+DBG_CFLAGS = -e -Ol --no_cse --no_unroll --no_inline --no_code_motion --no_tbaa
+DBG_CFLAGS += --no_cross_call --debug --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
+DBG_CFLAGS += --dlib_config "$(EWSTM8_DIR)\lib\$(LIB_MODEL)" -D $(PART)
+DBG_CFLAGS += -lC $(LIST_DIR) -lB $(LIST_DIR)
+DBG_CFLAGS += --diag_suppress Pa050
+
+ASMFLAGS = -M'<>' -ld $(OUT_DIR)\list --diag_suppress Pa050
+ASMFLAGS += --code_model small --data_model small
+
+DBG_ASMFLAGS = -M'<>' -r -ld $(OUT_DIR)\list --diag_suppress Pa050
+DBG_ASMFLAGS += --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
+
+LINKFLAGS = --redirect _Printf=_PrintfTinyNoMb
+LINKFLAGS += --redirect _Scanf=_ScanfSmallNoMb
+LINKFLAGS += --config "$(EWSTM8_DIR)\config\$(ICF)"
+LINKFLAGS += --config_def _CSTACK_SIZE=0x100
+LINKFLAGS += --config_def _HEAP_SIZE=0x100
+LINKFLAGS += --map $(OUT_DIR)
+LINKFLAGS += --entry __iar_program_start
+LINKFLAGS += --merge_duplicate_sections
+LINKFLAGS += --strip
+LINKFLAGS += -f "$(EWSTM8_DIR)\config\math_small.xcl"
+
+DBG_LINKFLAGS = --redirect _Printf=_PrintfTinyNoMb --redirect _Scanf=_ScanfSmallNoMb
+DBG_LINKFLAGS += --config "$(EWSTM8_DIR)\config\$(ICF)" --config_def
+DBG_LINKFLAGS += _CSTACK_SIZE=0x100 --config_def _HEAP_SIZE=0x100
+DBG_LINKFLAGS += --entry __iar_program_start
+
+#################
+# Build targets #
+#################
+
+# All
+all: $(OUT_DIR) $(PROJ_S19) $(PROJ_HEX)
+
+# Make build/output directory
+$(OUT_DIR):
+	@mkdir $(OUT_DIR)
+	@mkdir $(OBJ_DIR)
+	@mkdir $(LIST_DIR)
+
+# Test HEX files (one application build for each test)
+$(PROJ_S19): %.s19: $(PROJ_ELF)
+	@echo
+	@echo Building $@
+	@$(HEX) $(OUT_DIR)/$(notdir $<) $(OUT_DIR)/$@ --srec --silent
+
+$(PROJ_HEX): %.hex: $(PROJ_ELF)
+	@echo Building $@
+	@$(HEX) $(OUT_DIR)/$(notdir $<) $(OUT_DIR)/$@ --ihex --silent
+
+# Test ELF files (one application build for each test)
+$(PROJ_ELF): %.elf: $(ALL_OBJECTS)
+	@echo
+	@echo Linking $@
+	@$(LINK) $(OBJ_DIR)/*.o $(LINKFLAGS) -o $(OUT_DIR)/$@
+
+# All C objects builder
+$(ALL_OBJECTS): %.o: %.c
+	@echo
+	@echo Compiling $@
+	@$(CC) $< $(CFLAGS) $(INCLUDES) -o $(OBJ_DIR)
+
+# Application asm objects builder
+#$(APP_ASM_OBJECTS): %.o: ./%.s
+#	@echo Compiling $@
+#	@$(ASM) $< $(ASMFLAGS) -I $(KERNEL_DIR) -o $(OUT_DIR)/$(notdir $@)
+
+# Clean
+clean:
+	rm -f *.o *.elf *.map *.hex *.bin *.lst *.stm8 *.s19 *.out *.s *.lst
+	rm -rf $(LIST_DIR)
+	rm -rf $(OBJ_DIR)
+	rm -rf $(OUT_DIR)

+ 1 - 0
stm8/ReadMe.txt

@@ -0,0 +1 @@
+STM8 специфичные вещи.

+ 29 - 0
stm8/lse.c

@@ -0,0 +1,29 @@
+/**
+  * @brief  Wait 1 sec for LSE stabilization .
+  * @param  None.
+  * @retval None.
+  * Note : TIM4 is configured for a system clock = 2MHz
+  */
+void LSE_StabTime(void)
+{
+
+  CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);
+
+  /* Configure TIM4 to generate an update event each 1 s */
+  TIM4_TimeBaseInit(TIM4_Prescaler_16384, 123);
+  /* Clear update flag */
+  TIM4_ClearFlag(TIM4_FLAG_Update);
+
+  /* Enable TIM4 */
+  TIM4_Cmd(ENABLE);
+
+  /* Wait 1 sec */
+  while ( TIM4_GetFlagStatus(TIM4_FLAG_Update) == RESET );
+
+  TIM4_ClearFlag(TIM4_FLAG_Update);
+
+  /* Disable TIM4 */
+  TIM4_Cmd(DISABLE);
+
+  CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, DISABLE);
+}

+ 125 - 0
stm8/mcu_gpio.h

@@ -0,0 +1,125 @@
+/*
+ *  File:   mcu_gpio.h
+ *  Date:   23.01.2011
+ *  Denis Zheleznyakov aka ZiB @ http://ziblog.ru
+ */
+
+#ifndef MCU_GPIO_H_
+#define MCU_GPIO_H_
+
+// PIN_TEST    A, 3, HIGH, INPUT_FLOATING_WITHOUT_ITERRUPT
+
+#define INPUT_FLOATING_WITHOUT_ITERRUPT     INPUT_FLOATING_WITHOUT_ITERRUPT
+#define INPUT_FLOATING_WITH_ITERRUPT        INPUT_FLOATING_WITH_ITERRUPT
+#define INPUT_PULL_UP_WITHOUT_ITERRUPT      INPUT_PULL_UP_WITHOUT_ITERRUPT
+#define INPUT_PULL_UP_WITH_ITERRUPT         INPUT_PULL_UP_WITH_ITERRUPT
+#define OUTPUT_OPEN_DRAIN_NOSPEED_LIMIT     OUTPUT_OPEN_DRAIN_NOSPEED_LIMIT
+#define OUTPUT_OPEN_DRAIN_SPEED_LIMIT_10MHZ OUTPUT_OPEN_DRAIN_SPEED_LIMIT_10MHZ
+#define OUTPUT_PUSH_PULL_NOSPEED_LIMIT      OUTPUT_PUSH_PULL_NOSPEED_LIMIT
+#define OUTPUT_PUSH_PULL_SPEED_LIMIT_10MHZ  OUTPUT_PUSH_PULL_SPEED_LIMIT_10MHZ
+
+//------------------------------------------------------------------------------
+#define GPIO_PIN_CONFIGURATION_OUTPUT_PUSH_PULL_SPEED_LIMIT_10MHZ(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR |= (1 << PIN); \
+			GPIO##PORT->CR1 |= (1 << PIN); \
+			GPIO##PORT->CR2 |= (1 << PIN); \
+		}
+
+#define GPIO_PIN_CONFIGURATION_OUTPUT_PUSH_PULL_NOSPEED_LIMIT(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR |= (1 << PIN); \
+			GPIO##PORT->CR1 |= (1 << PIN); \
+			GPIO##PORT->CR2 &= (uint8_t)(~(1 << PIN)); \
+		}
+
+#define GPIO_PIN_CONFIGURATION_OUTPUT_OPEN_DRAIN_SPEED_LIMIT_10MHZ(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR |= (1 << PIN); \
+			GPIO##PORT->CR1 &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR2 |= (1 << PIN); \
+		}
+
+#define GPIO_PIN_CONFIGURATION_OUTPUT_OPEN_DRAIN_NOSPEED_LIMIT(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR |= (1 << PIN); \
+			GPIO##PORT->CR1 &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR2 &= (uint8_t)(~(1 << PIN)); \
+		}
+
+#define GPIO_PIN_CONFIGURATION_INPUT_PULL_UP_WITH_ITERRUPT(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR1 |= (1 << PIN); \
+			GPIO##PORT->CR2 |= (1 << PIN); \
+		}
+
+#define GPIO_PIN_CONFIGURATION_INPUT_PULL_UP_WITHOUT_ITERRUPT(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR1 |= (1 << PIN); \
+			GPIO##PORT->CR2 &= (uint8_t)(~(1 << PIN)); \
+		}
+
+#define GPIO_PIN_CONFIGURATION_INPUT_FLOATING_WITH_ITERRUPT(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR1 &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR2 |= (1 << PIN); \
+		}
+
+#define GPIO_PIN_CONFIGURATION_INPUT_FLOATING_WITHOUT_ITERRUPT(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO##PORT->DDR &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR1 &= (uint8_t)(~(1 << PIN)); \
+			GPIO##PORT->CR2 &= (uint8_t)(~(1 << PIN)); \
+		}
+
+//------------------------------------------------------------------------------
+#define GPIO_PIN_CONFIGURATION(PORT, PIN, LEVEL, MODE) \
+		{ \
+			GPIO_PIN_CONFIGURATION_##MODE(PORT, PIN, LEVEL, MODE); \
+		}
+
+//------------------------------------------------------------------------------
+#define GPIO_PIN_OFF_HIGH(PORT, PIN, LEVEL, MODE) \
+		{ GPIO##PORT->ODR &= (uint8_t)((uint8_t)(~(1 << PIN))); }
+
+#define GPIO_PIN_OFF_LOW(PORT, PIN, LEVEL, MODE) \
+		{ GPIO##PORT->ODR |= (1 << PIN); }
+
+#define GPIO_PIN_OFF(PORT, PIN, LEVEL, MODE) \
+		{ GPIO_PIN_OFF_##LEVEL(PORT, PIN, LEVEL, MODE) }
+
+//------------------------------------------------------------------------------
+#define GPIO_PIN_ON_HIGH(PORT, PIN, LEVEL, MODE) \
+		{ GPIO##PORT->ODR |= (1 << PIN); }
+
+#define GPIO_PIN_ON_LOW(PORT, PIN, LEVEL, MODE) \
+		{ GPIO##PORT->ODR &= (uint8_t)(~(1 << PIN)); }
+
+#define GPIO_PIN_ON(PORT, PIN, LEVEL, MODE) \
+		{ GPIO_PIN_ON_##LEVEL(PORT, PIN, LEVEL, MODE) }
+
+//------------------------------------------------------------------------------
+#define GPIO_PIN_TOGGLE(PORT, PIN, LEVEL, MODE) \
+		{ GPIO##PORT->ODR ^= (uint8_t)(1 << PIN); }
+
+//------------------------------------------------------------------------------
+#define GPIO_PIN_SIGNAL_HIGH(PORT, PIN, LEVEL, MODE) \
+		( (GPIO##PORT->IDR & (1 << PIN)) == (1 << PIN) )
+
+#define GPIO_PIN_SIGNAL_LOW(PORT, PIN, LEVEL, MODE) \
+	( (GPIO##PORT->IDR & (1 << PIN)) != (1 << PIN) )
+
+#define GPIO_PIN_SIGNAL(PORT, PIN, LEVEL, MODE) \
+	( GPIO_PIN_SIGNAL_##LEVEL(PORT, PIN, LEVEL, MODE) )
+
+//------------------------------------------------------------------------------
+#define PIN_CONFIGURATION(PIN_DESCRIPTION) GPIO_PIN_CONFIGURATION(PIN_DESCRIPTION)
+#define PIN_ON(PIN_DESCRIPTION) GPIO_PIN_ON(PIN_DESCRIPTION)
+#define PIN_OFF(PIN_DESCRIPTION) GPIO_PIN_OFF(PIN_DESCRIPTION)
+#define PIN_TOGGLE(PIN_DESCRIPTION) GPIO_PIN_TOGGLE(PIN_DESCRIPTION)
+#define PIN_SIGNAL(PIN_DESCRIPTION) GPIO_PIN_SIGNAL(PIN_DESCRIPTION)
+
+#endif /* MCU_GPIO_H_ */

+ 2 - 0
Поливалки.txt

@@ -0,0 +1,2 @@
+Сеть контроллеров сухости почвы, с поливалками.
+на радиомодулях.

+ 43 - 0
классы.txt

@@ -0,0 +1,43 @@
+НАСЛЕДОВАНИЕ КЛАССОВ
+
+Ключевое слово virtual
+Чтобы производный класс получил возможность перекрывать методы, используйте ключевое
+слово *virtual*.
+
+// родительский метод
+class Bird {
+	public virtual void Fly() {
+		// код, заставляющий птицу летать
+	}
+}
+
+Добавление одноименного метода в производный класс
+Переопределенный метод должен иметь такую же сигнатуру, то есть то же самое возвращаемое
+значение и параметры. В его объявлении используется ключевое слово *override*.
+
+// дочерний метод
+class Penguin : Bird {
+	public override void Fly() {
+		MessageBox.Show("Пингвины не летают!")
+	}
+}
+
+!!!
+Используйте ключевое слово *override* для добавления в производный класс
+методов, замещающих методы унаследованные. Перекрывать можно методы,
+помеченные в базовом классе словом *virtual*.
+
+-=-=-=-=-=-=-=-=-=-=-=-
+
+Если в классе присутствуют конструкторы, то все классы, которые от
+него наследуют, должны вызывать хотя бы один из этих конструк-
+торов. При этом конструктор производного класса может иметь свои
+собственные параметры.
+
+class Subclass : BaseClass {
+	public Subclass(список параметров)
+		: base(список параметров базового класса) {
+		// сначала выполняется конструктор базового класса,
+		// а потом все остальные операторы
+	}
+}

+ 48 - 0
фнч.txt

@@ -0,0 +1,48 @@
+http://electronix.ru/forum/lofiversion/index.php/t12237.html
+Самый простой способ, аналогичный ФНЧ, т.е. для условий, что сигнал
+низкочастотый и сетевая частота в нём присутствует в виде наводки как
+единственный высокочастоный сигнал:
+Частота дискретизации 1000 Гц;
+Подавляемая частота 50 Гц;
+На одном периоде подавляемой частоты получается 20 отсчетов.
+Для синуса при данных условиях получается, что если брать сумму выборок
+X(n-10)+X(n), то в результате должен получаться ноль.
+Но кроме синуса, какую-то часть веса выборки составляет полезный сигнал и
+простое суммирование приведёт к удвоению его среднего значения. Тогда делаем
+так: (X(n-10)+X(n))/2.
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+http://chipenable.ru/index.php/programming-avr/item/162-prostoy-cifrovoy-filtr.html
+
+По сути, программа этого цифрового фильтра состоит всего из двух строчек на Си.:
+	Dacc = Dacc + Din - Dout
+	Dout = Dacc/K
+где Dout - выходное значение фильтра, Din - входное значение фильтра, K -
+постоянный коэффициент, который рассчитывается по формуле:
+	K = T x SPS
+где T - это постоянная времени фильтра, SPS - частота дискретизации АЦП.
+
+Dacc и Dout должны сохранять свои значения, после выполнения алгоритма. Если
+алгоритм реализовать в виде функции, то эти переменные можно просто сделать
+статическими.
+
+Для 8-ми разрядных входных данных алгоритм цифрового фильтра в Си коде может выглядеть так:
+
+#define SPS 9600UL
+#define Trc 0.001f
+#define K (SPS*Trc)
+
+uint8_t Filtr(uint8_t data)
+{
+   static uint16_t Dacc = 0;
+   static uint8_t Dout = 0;
+   uint8_t Din = data;
+
+   Dacc = Dacc + Din - Dout;
+   Dout = Dacc/(uint16_t)K;
+
+   return Dout;
+}
+
+---
+Моё: я думаю, что SPS нужно брать не частоту АЦП, а частоту выборок.