Показаны сообщения с ярлыком STM32. Показать все сообщения
Показаны сообщения с ярлыком STM32. Показать все сообщения
суббота, 23 ноября 2013 г.
пятница, 25 октября 2013 г.
пятница, 27 сентября 2013 г.
четверг, 19 сентября 2013 г.
пятница, 13 сентября 2013 г.
Программирование множества кнопок
http://www.adafruit.com/blog/2009/10/20/example-code-for-multi-button-checker-with-debouncing/
#define DEBOUNCE 10 // button debouncer, how many ms to debounce, 5+ ms is usually plenty // here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc byte buttons[] = {14, 15, 16, 17, 18, 19}; // the analog 0-5 pins are also known as 14-19 // This handy macro lets us determine how big the array up above is, by checking the size #define NUMBUTTONS sizeof(buttons) // we will track if a button is just pressed, just released, or 'currently pressed' byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS]; void setup() { byte i; // set up serial port Serial.begin(9600); Serial.print("Button checker with "); Serial.print(NUMBUTTONS, DEC); Serial.println(" buttons"); // pin13 LED pinMode(13, OUTPUT); // Make input & enable pull-up resistors on switch pins for (i=0; i< NUMBUTTONS; i++) { pinMode(buttons[i], INPUT); digitalWrite(buttons[i], HIGH); } } void check_switches() { static byte previousstate[NUMBUTTONS]; static byte currentstate[NUMBUTTONS]; static long lasttime; byte index; if (millis() < lasttime) { // we wrapped around, lets just try again lasttime = millis(); } if ((lasttime + DEBOUNCE) > millis()) { // not enough time has passed to debounce return; } // ok we have waited DEBOUNCE milliseconds, lets reset the timer lasttime = millis(); for (index = 0; index < NUMBUTTONS; index++) { justpressed[index] = 0; // when we start, we clear out the "just" indicators justreleased[index] = 0; currentstate[index] = digitalRead(buttons[index]); // read the button /* Serial.print(index, DEC); Serial.print(": cstate="); Serial.print(currentstate[index], DEC); Serial.print(", pstate="); Serial.print(previousstate[index], DEC); Serial.print(", press="); */ if (currentstate[index] == previousstate[index]) { if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { // just pressed justpressed[index] = 1; } else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { // just released justreleased[index] = 1; } pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed } //Serial.println(pressed[index], DEC); previousstate[index] = currentstate[index]; // keep a running tally of the buttons } } void loop() { check_switches(); // when we check the switches we'll get the current state for (byte i = 0; i < NUMBUTTONS; i++) { if (justpressed[i]) { Serial.print(i, DEC); Serial.println(" Just pressed"); // remember, check_switches() will CLEAR the 'just pressed' flag } if (justreleased[i]) { Serial.print(i, DEC); Serial.println(" Just released"); // remember, check_switches() will CLEAR the 'just pressed' flag } if (pressed[i]) { Serial.print(i, DEC); Serial.println(" pressed"); // is the button pressed down at this moment } } }
#define DEBOUNCE 10 // button debouncer, how many ms to debounce, 5+ ms is usually plenty // here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc byte buttons[] = {14, 15, 16, 17, 18, 19}; // the analog 0-5 pins are also known as 14-19 // This handy macro lets us determine how big the array up above is, by checking the size #define NUMBUTTONS sizeof(buttons) // we will track if a button is just pressed, just released, or 'currently pressed' volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS]; void setup() { byte i; // set up serial port Serial.begin(9600); Serial.print("Button checker with "); Serial.print(NUMBUTTONS, DEC); Serial.println(" buttons"); // pin13 LED pinMode(13, OUTPUT); // Make input & enable pull-up resistors on switch pins for (i=0; i< NUMBUTTONS; i++) { pinMode(buttons[i], INPUT); digitalWrite(buttons[i], HIGH); } // Run timer2 interrupt every 15 ms TCCR2A = 0; TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20; //Timer2 Overflow Interrupt Enable TIMSK2 |= 1<<TOIE2; } SIGNAL(TIMER2_OVF_vect) { check_switches(); } void check_switches() { static byte previousstate[NUMBUTTONS]; static byte currentstate[NUMBUTTONS]; static long lasttime; byte index; if (millis() < lasttime) { // we wrapped around, lets just try again lasttime = millis(); } if ((lasttime + DEBOUNCE) > millis()) { // not enough time has passed to debounce return; } // ok we have waited DEBOUNCE milliseconds, lets reset the timer lasttime = millis(); for (index = 0; index < NUMBUTTONS; index++) { currentstate[index] = digitalRead(buttons[index]); // read the button /* Serial.print(index, DEC); Serial.print(": cstate="); Serial.print(currentstate[index], DEC); Serial.print(", pstate="); Serial.print(previousstate[index], DEC); Serial.print(", press="); */ if (currentstate[index] == previousstate[index]) { if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { // just pressed justpressed[index] = 1; } else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { // just released justreleased[index] = 1; } pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed } //Serial.println(pressed[index], DEC); previousstate[index] = currentstate[index]; // keep a running tally of the buttons } } void loop() { for (byte i = 0; i < NUMBUTTONS; i++) { if (justpressed[i]) { justpressed[i] = 0; Serial.print(i, DEC); Serial.println(" Just pressed"); // remember, check_switches() will CLEAR the 'just pressed' flag } if (justreleased[i]) { justreleased[i] = 0; Serial.print(i, DEC); Serial.println(" Just released"); // remember, check_switches() will CLEAR the 'just pressed' flag } if (pressed[i]) { Serial.print(i, DEC); Serial.println(" pressed"); // is the button pressed down at this moment } } }
четверг, 20 июня 2013 г.
Синхронизация таймеров STM32(Работают не синхронно)
http://forum.easyelectronics.ru/viewtopic.php?f=35&t=12983
Имеет место какой таймер запускать первым! Сначала необходимо запустить ведомый так как он не запустится пока не запустится ведущий.
Ведомый TIM3 запускаем первым
Ведущий TIM1 запускаем вторым.
void TIMERS_Start(void)
{
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM1, ENABLE); // запуск таймера после инициализации АЦП и его синхронизации с TIMER3
TIM_CtrlPWMOutputs(TIM3, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
#include "timer.h"
uint16_t TimerPeriod = 0;
uint8_t TIM1_HalfPeriodCNT = 1;
void TIMER1_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TimerPeriod = (SystemCoreClock / 40000) - 1;
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 1, 2, 3, 4 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
//PWM for Cell3_PWM_EN
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
//TIM_OC2FastConfig(TIM1, TIM_OCFast_Enable);
TIM_OCInitStructure.TIM_Pulse = 1;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
//PWM for Primary WIND and Cell3_PWM_OGR
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 2;
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
//TIM_OC3FastConfig(TIM1, TIM_OCFast_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_CCPreloadControl(TIM1, ENABLE);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Automatic Output enable, Break, dead time and lock configuration*/
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 0;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
// Allow interruput from TIM_1 update event
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE );
/* Master Mode selection */
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Enable);//TIM_TRGOSource_Enable);
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
}
//--------------------------------------
void TIMER3_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TimerPeriod = (SystemCoreClock / 40000 ) - 1;
// Time Base configuration
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1FastConfig(TIM3, TIM_OCFast_Enable);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2FastConfig(TIM3, TIM_OCFast_Enable);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3FastConfig(TIM3, TIM_OCFast_Enable);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4FastConfig(TIM3, TIM_OCFast_Enable);
TIM_CCPreloadControl(TIM3, ENABLE);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR0);
}
//--------------------------------------
void TIMERS_Start(void)
{
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM1, ENABLE); // запуск таймера после инициализации АЦП и его синхронизации с TIMER3
TIM_CtrlPWMOutputs(TIM3, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
Имеет место какой таймер запускать первым! Сначала необходимо запустить ведомый так как он не запустится пока не запустится ведущий.
Ведомый TIM3 запускаем первым
Ведущий TIM1 запускаем вторым.
void TIMERS_Start(void)
{
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM1, ENABLE); // запуск таймера после инициализации АЦП и его синхронизации с TIMER3
TIM_CtrlPWMOutputs(TIM3, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
#include "timer.h"
uint16_t TimerPeriod = 0;
uint8_t TIM1_HalfPeriodCNT = 1;
void TIMER1_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TimerPeriod = (SystemCoreClock / 40000) - 1;
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 1, 2, 3, 4 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
//PWM for Cell3_PWM_EN
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
//TIM_OC2FastConfig(TIM1, TIM_OCFast_Enable);
TIM_OCInitStructure.TIM_Pulse = 1;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
//PWM for Primary WIND and Cell3_PWM_OGR
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 2;
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
//TIM_OC3FastConfig(TIM1, TIM_OCFast_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_CCPreloadControl(TIM1, ENABLE);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Automatic Output enable, Break, dead time and lock configuration*/
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 0;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
// Allow interruput from TIM_1 update event
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE );
/* Master Mode selection */
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Enable);//TIM_TRGOSource_Enable);
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
}
//--------------------------------------
void TIMER3_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TimerPeriod = (SystemCoreClock / 40000 ) - 1;
// Time Base configuration
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1FastConfig(TIM3, TIM_OCFast_Enable);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2FastConfig(TIM3, TIM_OCFast_Enable);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3FastConfig(TIM3, TIM_OCFast_Enable);
// PWM for
TIM_OCInitStructure.TIM_Pulse = TimerPeriod >> 3;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4FastConfig(TIM3, TIM_OCFast_Enable);
TIM_CCPreloadControl(TIM3, ENABLE);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR0);
}
//--------------------------------------
void TIMERS_Start(void)
{
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM1, ENABLE); // запуск таймера после инициализации АЦП и его синхронизации с TIMER3
TIM_CtrlPWMOutputs(TIM3, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
понедельник, 10 июня 2013 г.
Транс.01
Измеряется напряжение. Если необходимо только на одной поднять уровень то рассчитывается мощность для одной, на двух значит для двух и т.д. По этой мощности рассчитывается скважность первичной обмотки(при заряде трасформатора) и затем вторичной.
вторник, 4 июня 2013 г.
вторник, 28 мая 2013 г.
Отладочная плата STM32
http://robobuild.ru/index.php?itid=1
http://we.easyelectronics.ru/Telek/demoplata-na-stm32.html
http://we.easyelectronics.ru/alexander/ocherednaya-plata-dlya-stm32.html
http://mycontroller.ru/stm32-usb-nemnogo-teorii/
http://forum.easyelectronics.ru/viewtopic.php?f=16&t=5979
http://we.easyelectronics.ru/Telek/demoplata-na-stm32.html
http://we.easyelectronics.ru/alexander/ocherednaya-plata-dlya-stm32.html
http://mycontroller.ru/stm32-usb-nemnogo-teorii/
http://forum.easyelectronics.ru/viewtopic.php?f=16&t=5979
Кстати я тоже на всех девайсах делаю кольцевую землю вокруг платы. И никаких багов-глюков не было. Главное пошире сделать эту землю да и залудить припоем дюже. На частотах до 8МГц (выше просто не было задач делать) все без глюков работало. Мало того, так помню даже на курсе КТО Пр ЭВМ (Конструкторско-техническое обеспечение производства ЭВМ) именно так и учили делать платы для вычислительной техники.
суббота, 23 марта 2013 г.
воскресенье, 24 февраля 2013 г.
суббота, 16 февраля 2013 г.
Одна кнопка.
http://we.easyelectronics.ru/HomeTech/odnokomponentnaya-payalnaya-maska-s-uf-otverzhdeniem.html
Иногда приходится делать очень маленькое устройство, например, велокомпьютер. Или конструктив не позволяет разместить много кнопок. В общем есть у нас одна кнопка на ввод и ничего более.
Спартанские условия, но и тут можно развернуть мощный функционал, многоуровневые меню и прочие прелести жизни. сейчас я покажу одну из реализаций такого управления.
Итак, что у умеет наша кнопка?
Не густо, но вполне ничего. Для одной кнопки то. Главный затык при написании этого не просрать массу системных ресурсов (время процессора, таймеры и тыды) на обработку этой несчастной кнопки. Ведь нам придется отслеживать факт нажатия, факт отжатия, время нажатия, число нажатий с разным временем. Я видел такие адовые реализации этого интерфейса, что просто диву давался как можно нагородить столько тупняков и тормозов в этой одной сосне, да еще потратить все таймеры :)
Так что ТЗ выставим следующее:
Алгоритм
Сделаем все на конечном автомате. У него будут три состояния:
А также будет одна служебная процедура, которая спустя mode_time (2c) после первого экшна с кнопкой сгребет все результаты и что-нибудь с ними сделает. Что — это уже не важно. От программы зависит.
И вся эта дребедень будет крутиться в цикле, вызывая сама себя через диспетчер (или каким еще образом) раз в 20мс.

Up
Входим.
Смотрим не нажата ли кнопка? Если нет — выходим. Если нажата, то переводим автомат в положение Dn
Проверяем первый ли раз за интервал мы тут? Если первый, то поставим нашу служебную процедуру на отложенный запуск (через 2с), взведем флаг, что процесс пошел.
Выходим.
Dn
Входим.
Еще нажата? Если нет, значит кнопка уже отпущена, скидываемся в состояние в Up и засчитываем одно короткое нажатие, увеличивая счетчик коротких нажатий cnt_s. Если еще нажата, то щелкаем счетчиком времени замера длительности нажатия Timе. Замер длительности у нас идет в итерациях автомата. Одна итерация 20мс. В лимит длинного нажатия я заложил 20 итераций, что дает около 400мс. Все что больше 0.4с считаем длинным нажатием. Как натикает больше 20 итераций, то засчитываем одно длинное нажатие и перекидываем автомат в состояние Al. Выходим.
Al
Входим.
Еще не отпустили? Если нет, то выходим. Если кнопка отпущена, то перебрасываемся в Up, скинув переменную Time.

За время mode_time, за те две секунды, сколько успеем натыкать — все наше. Запустится процедура анализа собранных данных и разгребет натыканное. Там уже все просто. Банальным case’ом делаем нужный нам экшн. Я вот, например, флажки выставляю которые перехватывает другая задача. Главное не блокировать эту задачу ничем тяжелым, чтобы не прозевать следующую комбинацию.
Код
Показать »
Код написан так, что на AVR там завязана буквально пара строчек. По крайней мере в коде обработчика нажатий кнопки. Все привязки на железо идут в хидере, да и их там всего ничего:
Так что портировать это на другую архитектуру дело смены двух строчек. Ну и, возможно, вам потребуется изменить механизм автозапуска и запуска функции обработчика. Если вы будете использовать какой то свой диспетчер, ОС или еще какую систему организации прошивки. Но это две строчки в коде поправить.
Все описанное в статье мясо лежит в двух файлах button.c и button.h
Видео работы
Дребезг
Боротся с дребезгом тут уже не обязательно. Т.к. частота сканирования небольшая, так что даже голимая и наглухо окисленная кнопка модели ТМ2 не давала дребезга — он кончался раньше, чем наступал следующий скан. А вот что тут можно докурить, так это защиту от ложных сработок в результате наводок. Ведь стоит помехе продавить линию в момент считывания и засчитается сработка однократного нажатия. Это можно избежать сделав проверочные состояния автомата. Скажем добавив в Up счетчик итераций, чтобы в течении, скажем, двух-трех итераций подтвердить, что кнопка таки нажата и только тогда переходить в Dn.
Варианты
Правда в своем проекте я несколько изменил обработку. Т.к. мне не нужны были множественные длинные нажатия, то я сделал выставление флага «Длинное нажатие» сразу же в обработчике AL и, заодно, убрал подсчет числа длинных нажатий. Что позволило повысить отзывчивость работы интерфейса прибора, где длительным нажатием осуществлялся вход в пункт меню, а комбинаций с двумя длинными нажатиями не использовались вообще.
Ну и, разумеется, этот же конечный автомат можно поставить на разбор чего угодно. Например на отслеживание какого-либо другого флажка, от матричной клавиатуры или какого сигнального устройства.
Иногда приходится делать очень маленькое устройство, например, велокомпьютер. Или конструктив не позволяет разместить много кнопок. В общем есть у нас одна кнопка на ввод и ничего более.
Спартанские условия, но и тут можно развернуть мощный функционал, многоуровневые меню и прочие прелести жизни. сейчас я покажу одну из реализаций такого управления.
Итак, что у умеет наша кнопка?
- Ее можно нажимать кратко
- Можно жать длинно
- Можно делать разные комбинации нажатий
- Ее можно отпускать в нужный момент
Не густо, но вполне ничего. Для одной кнопки то. Главный затык при написании этого не просрать массу системных ресурсов (время процессора, таймеры и тыды) на обработку этой несчастной кнопки. Ведь нам придется отслеживать факт нажатия, факт отжатия, время нажатия, число нажатий с разным временем. Я видел такие адовые реализации этого интерфейса, что просто диву давался как можно нагородить столько тупняков и тормозов в этой одной сосне, да еще потратить все таймеры :)
Так что ТЗ выставим следующее:
- Никаких аппаратных таймеров, кроме таймера диспетчера.
- Никаких временных задержек, только вызов себя же по таймеру.
- Никаких ожиданий нажатия-отжатия в цикле. Зашли, проверили — отдали управление.
- Введем временной интервал mode_time, в течении которого будем отслеживать комбинацию нажатий. Скажем 2с
- На выходе будем иметь число коротких и длинных нажатий за данный интервал
Алгоритм
Сделаем все на конечном автомате. У него будут три состояния:
- Up — кнопка не нажата
- Dn — кнопка нажата
- Al — кнопка отпущена после длительного нажатия
А также будет одна служебная процедура, которая спустя mode_time (2c) после первого экшна с кнопкой сгребет все результаты и что-нибудь с ними сделает. Что — это уже не важно. От программы зависит.
И вся эта дребедень будет крутиться в цикле, вызывая сама себя через диспетчер (или каким еще образом) раз в 20мс.
Up
Входим.
Смотрим не нажата ли кнопка? Если нет — выходим. Если нажата, то переводим автомат в положение Dn
Проверяем первый ли раз за интервал мы тут? Если первый, то поставим нашу служебную процедуру на отложенный запуск (через 2с), взведем флаг, что процесс пошел.
Выходим.
Dn
Входим.
Еще нажата? Если нет, значит кнопка уже отпущена, скидываемся в состояние в Up и засчитываем одно короткое нажатие, увеличивая счетчик коротких нажатий cnt_s. Если еще нажата, то щелкаем счетчиком времени замера длительности нажатия Timе. Замер длительности у нас идет в итерациях автомата. Одна итерация 20мс. В лимит длинного нажатия я заложил 20 итераций, что дает около 400мс. Все что больше 0.4с считаем длинным нажатием. Как натикает больше 20 итераций, то засчитываем одно длинное нажатие и перекидываем автомат в состояние Al. Выходим.
Al
Входим.
Еще не отпустили? Если нет, то выходим. Если кнопка отпущена, то перебрасываемся в Up, скинув переменную Time.
За время mode_time, за те две секунды, сколько успеем натыкать — все наше. Запустится процедура анализа собранных данных и разгребет натыканное. Там уже все просто. Банальным case’ом делаем нужный нам экшн. Я вот, например, флажки выставляю которые перехватывает другая задача. Главное не блокировать эту задачу ничем тяжелым, чтобы не прозевать следующую комбинацию.
Код
Показать »
Код написан так, что на AVR там завязана буквально пара строчек. По крайней мере в коде обработчика нажатий кнопки. Все привязки на железо идут в хидере, да и их там всего ничего:
1 2 3 4 5 6 7 8 9 10 11 | #include <avrlibtypes.h> #include <avrlibdefs.h> #define Open (BTN_PIN & 1<<BTN) #define Close (!Open) extern void bt_scan(void); void bt_ok(void); extern u08 bt1,bt2,bt3,bt4,bt5,bt_l,bt_l2,bt_al; extern u16 bt_mode_time; |
Так что портировать это на другую архитектуру дело смены двух строчек. Ну и, возможно, вам потребуется изменить механизм автозапуска и запуска функции обработчика. Если вы будете использовать какой то свой диспетчер, ОС или еще какую систему организации прошивки. Но это две строчки в коде поправить.
Все описанное в статье мясо лежит в двух файлах button.c и button.h
Видео работы
Дребезг
Боротся с дребезгом тут уже не обязательно. Т.к. частота сканирования небольшая, так что даже голимая и наглухо окисленная кнопка модели ТМ2 не давала дребезга — он кончался раньше, чем наступал следующий скан. А вот что тут можно докурить, так это защиту от ложных сработок в результате наводок. Ведь стоит помехе продавить линию в момент считывания и засчитается сработка однократного нажатия. Это можно избежать сделав проверочные состояния автомата. Скажем добавив в Up счетчик итераций, чтобы в течении, скажем, двух-трех итераций подтвердить, что кнопка таки нажата и только тогда переходить в Dn.
Варианты
Правда в своем проекте я несколько изменил обработку. Т.к. мне не нужны были множественные длинные нажатия, то я сделал выставление флага «Длинное нажатие» сразу же в обработчике AL и, заодно, убрал подсчет числа длинных нажатий. Что позволило повысить отзывчивость работы интерфейса прибора, где длительным нажатием осуществлялся вход в пункт меню, а комбинаций с двумя длинными нажатиями не использовались вообще.
Ну и, разумеется, этот же конечный автомат можно поставить на разбор чего угодно. Например на отслеживание какого-либо другого флажка, от матричной клавиатуры или какого сигнального устройства.
суббота, 2 февраля 2013 г.
четверг, 31 января 2013 г.
Отличные методички по СТМ32, RS232
http://www-micrel.deis.unibo.it/LABARCH/slidecorso2012/ - Примеры кода. Для DMA, Timers - Очень подробные.
http://www.cs.indiana.edu/~geobrown/book.pdf
http://www.cs.indiana.edu/~geobrown/book.pdf
воскресенье, 13 января 2013 г.
понедельник, 7 января 2013 г.
ZiBlog об стм32
Чувак с зиблога:
zheleznjakov
http://kazus.ru/forums/showthread.php?t=28338&page=5
http://ziblog.ru/
http://www.emcu.it/STM32/What_should_I_use_to_develop_on_STM32/What_should_I_use_to_develop_on_STM32.html
zheleznjakov
http://kazus.ru/forums/showthread.php?t=28338&page=5
http://ziblog.ru/
http://www.emcu.it/STM32/What_should_I_use_to_develop_on_STM32/What_should_I_use_to_develop_on_STM32.html
Подписаться на:
Сообщения (Atom)