Добавлено спустя 24 минуты 1 секунду:Мыслей много и их нужно причесать.
Дано:
. grbl
.
электронная гитара..
ручное управление(с шаговиком).
Начну от самого необходимого. Ручное управление. Тиньки 2313 должно хватить. Выкинуть из проекта ленту и втулить один лед_знак.
Скрестить энкодер с лимбом хз как. Трещётка с тормозом нужна наверно. На сколько делений?
Добавлено спустя 3 часа 30 минут 17 секунд:Dmitry__ писал(а):
У меня тахометр тоже показывает, но он никак не относится к обработке
Имел в виду
этот тахометр. Тот, что в станке(родной) тормознутый на секунду-две.
Привёл в пример его, как вариант шустрого просчёта и вывода на экран.
Если ничего не путаю, то это он(от асма там только вставки похоже):
Код:
#define TRUE (!FALSE)
#define FALSE 0
#define BYTE unsigned char
#define WORD unsigned short int
#define BOOLEAN char
#define TIMER_OVF_ENOUGHT 49
#define NO_PULSES_INTERVAL 200
#define LED_delay 250
#define Light_delay 2500
#define Anode
//#define Cathode
#define CNT_100_MS 6250
#define byBladeCnt 1 //1- две катушки, 2 - одна катушка, 4 - мотоцикл...
#define Prescaler 0x01 //0x00 - для кварца 4MHz, 0x01 - для кварца 8MHz...
#define UpCount 4 // +1 = количество пропусков (0,1S) до обновления
#include <tiny2313.h>
#include <delay.h>
BOOLEAN btTimeUpdate; // = 1, когда нужно обновить время на дисплее
WORD wTime; // Время, которое показывает секундомер (в десятых секунды)
BOOLEAN btTimerOn; // TRUE - таймер запущен, FALSE - остановлен
BYTE byTcnt; // счетчик десятых секунд
BYTE byDisplayRefreshCnt; //
void ShowDisplayData(void); // Вывод экранного буфера
void PrepareRpmData(WORD wRpm);
BOOLEAN btDisplayUpdate; // = TRUE, если пришло время обновить дисплей
BYTE byDisplay[5]; // буфер данных, для вывода на экран
WORD wLockedRpm;
// Массив знакогенератора
BYTE byCharacter[12] = {0xFA, //0
0x82, //1
0xB9, //2
0xAB, //3
0xC3, //4
0x6B, //5
0x7B, //6
0xA2, //7
0xFB, //8
0xEB, //9
0x00, //blank
0x01 //-
};
WORD wRpm; // Скорость вращения ротора (об/мин)
//BOOLEAN btRpmUpdate; // = 1, когда измеряно новое значение оборотов
WORD wTimerOvfCnt; // Счетчик переполнений таймера (нужен для
// увеличения разрядности
WORD wFlashCnt; // Счетчик срабатываний датчика прохождения допасти
BOOLEAN btFirstLowRateFlash; // FALSE - если отсчет периода еще не начался
// (датчик ни разу не сработал)
/************************************************************************\
Обновление дисплея.
Вход: -
Выход: -
\************************************************************************/
void RefreshDisplay(void)
{
#asm("cli");
if (btDisplayUpdate)
{
wLockedRpm = wRpm;
btDisplayUpdate = FALSE;
}
#asm("sei");
PrepareRpmData(wLockedRpm);
ShowDisplayData();
}
/************************************************************************\
Преобразование скорости мотора и количества лопастей
в данные экранного буфера
Вход: wRpm - обороты ротора, byBladeCnt - количество лопастей
Выход: -
\************************************************************************/
void PrepareRpmData(WORD wRpm)
{
BYTE i;
WORD R;
R = wRpm;
byDisplay[4] = wRpm % 10;
wRpm /= 10;
if (byDisplay[4] > 4) //округляем
{
wRpm++;
R += 10;
}
byDisplay[4] = 0;
// Первые 5 цифр - обороты двигателя
for(i=0; i<4; i++)
{
byDisplay[3-i] = wRpm % 10;
wRpm /= 10;
}
if (R < 10)
{
byDisplay[0] = 10;
byDisplay[1] = 10;
byDisplay[2] = 10;
byDisplay[3] = 10;
goto exit;
}
if ((R >= 10) & (R <100))
{
byDisplay[0] = 10;
byDisplay[1] = 10;
byDisplay[2] = 10;
goto exit;
}
if ((R >= 100) & (R <1000))
{
byDisplay[0] = 10;
byDisplay[1] = 10;
goto exit;
}
if ((R >= 1000) & (R <10000))
{
byDisplay[0] = 10;
goto exit;
}
exit:
}
/************************************************************************\
Вывод экранного буфера на дисплей.
Вход: -
Выход: -
\************************************************************************/
void ShowDisplayData(void)
{
#ifdef Cathode
PORTB = byCharacter[byDisplay[0]];
PORTD.3 = 0;
delay_us(LED_delay);
PORTD.3 = 1;
PORTB = byCharacter[byDisplay[1]];
PORTD.5 = 0;
delay_us(LED_delay);
PORTD.5 = 1;
PORTB = byCharacter[byDisplay[2]];
PORTD.1 = 0;
delay_us(LED_delay);
PORTD.1 = 1;
PORTB = byCharacter[byDisplay[3]];
PORTD.0 = 0;
delay_us(LED_delay);
PORTD.0 = 1;
PORTB = byCharacter[byDisplay[4]];
PORTD.4 = 0;
delay_us(LED_delay);
PORTD.4 = 1;
#endif
#ifdef Anode
PORTB = ~byCharacter[byDisplay[0]];
PORTD.3 = 1;
delay_us(LED_delay);
PORTD.3 = 0;
PORTB = ~byCharacter[byDisplay[1]];
PORTD.5 = 1;
delay_us(LED_delay);
PORTD.5 = 0;
PORTB = ~byCharacter[byDisplay[2]];
PORTD.1 = 1;
delay_us(LED_delay);
PORTD.1 = 0;
PORTB = ~byCharacter[byDisplay[3]];
PORTD.0 = 1;
delay_us(LED_delay);
PORTD.0 = 0;
PORTB = ~byCharacter[byDisplay[4]];
PORTD.4 = 1;
delay_us(LED_delay);
PORTD.4 = 0;
#endif
if (! PIND.6)
{
delay_us(Light_delay);
}
}
/**************************************************************************\
Обработка прерываний от OC1 (для отсчета импульсов 0.1 сек)
Вход: -
Выход: -
\**************************************************************************/
interrupt [TIM1_COMPA] void SYSTEM_TICK_interrupt(void)
{
// Вычисляем оммент следующего срабатывания таймера
OCR1A += CNT_100_MS;
// 3 раза в секунду перерисовываем дисплей,
// независимо от обстоятельств.
if( ++byDisplayRefreshCnt == UpCount )
{
byDisplayRefreshCnt = 0;
btDisplayUpdate = TRUE;
}
// Если секундомер запущен - инкрементируем его показания
if( btTimerOn )
{
if (++byTcnt == 10)
{
byTcnt = 0;
if( ++wTime == 60000)
wTime = 0;
}
}
}
/**************************************************************************\
Обработка прерываний от управляющих импульсов
Вход: -
Выход: -
\**************************************************************************/
interrupt [EXT_INT0] void RPM_PULSE_interrupt(void)
{
long lTmp;
GIMSK &= ~0x40;
if(btFirstLowRateFlash)
{
// Первый импульс, сбрасываем счетчик периода и
// счетчик импульсов
wTimerOvfCnt = 0;
wFlashCnt = 0;
TCNT0 = 0;
TIFR = 0x02;
TCCR0B = 0x03; // FCK / 64 ( 62.5 KHz )
TCNT0 = 0;
TIMSK |= 0x02; // Разрешаем прерывания от TMR0
btFirstLowRateFlash = FALSE;
}
else
{
wFlashCnt++;
// Проверяем, не пора ли закончить измерения
if( wTimerOvfCnt > TIMER_OVF_ENOUGHT )
{
TCCR0B = 0; // Останавливаем TMR0
GIMSK &= 0x40; // Запрещаем прерывания от INT0
TIMSK &= ~0x02; // Запрещаем прерывания от TMR0
if(TIFR & 0x02)
wTimerOvfCnt++; // Учитываем возможность переполнения
lTmp = (62500L * 60L * (long)wFlashCnt);
lTmp /= ((wTimerOvfCnt << 8) + TCNT0);
lTmp /= byBladeCnt;
wRpm = lTmp;
// Перезапускаем измерения
btFirstLowRateFlash = TRUE;
wTimerOvfCnt = 0;
TCNT0 = 0;
TCCR0B = 0x03; // FCK / 64 ( 62.5 KHz )
TCNT0 = 0;
TIFR = 0x02;
TIMSK |= 0x02; // Разрешаем прерывания от TMR0
// GIFR = 0x40;
}
}
EIFR = 0x40;
GIMSK |= 0x40;
}
/**************************************************************************\
Обработка переполнений TMR0 (добавляем к счетчику еще 8 разрядов)
Вход: -
Выход: -
\**************************************************************************/
interrupt [TIM0_OVF] void TIMER0_interrupt(void)
{
wTimerOvfCnt++;
// Если импульсов не было слишком долго, то показываем
// 0 оборотов и запускаем измерение заново
if( wTimerOvfCnt > NO_PULSES_INTERVAL )
{
wRpm = 0;
btFirstLowRateFlash = TRUE;
wTimerOvfCnt = 0;
}
}
/**************************************************************************\
Головная функция. Инициализация всех модулей. Цикл вызова рабочих
подпрограмм.
Вход: -
Выход: -
\**************************************************************************/
void main(void)
{
// Crystal Oscillator division factor:
#pragma optsize-
CLKPR=0x80;
CLKPR=Prescaler; //0x00 - для кварца 4MHz, 0x01 - для кварца 8MHz...
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
#asm("cli");
MCUCR = 0x00; // Запрещаем SLEEP, режимы прерывания пока не важны.
// В принципе, этого можно и не делать.
GIMSK = 0x00; // Запрещаем внешние прерывания
EIFR = 0xFF; // Очищаем флаги прерываний
TIMSK = 0x00; // Запрещаем прерывания от таймеров
TIFR = 0xFF; // Очищаем флаги прерываний
//Разряд DDRx - определяет направление передачи данных (0 - вход, 1 - выход).
//Разряд PORTx - если вывод определен выходом (DDRx = 1), то:
// если установлена 1 - то на выводе устанавливается лог. 1
// если установлена 0 - то на выводе устанавливается лог. 0
// если вывод определен входом (DDRx = 0), то PORTx - определяет состояние подтягивающего резистора (при PORTx = 1 резистор подключен)
//Разряд PINx - доступен только для чтения и содержит физическое значение вывода порта
PORTA=0b00000011;
DDRA= 0b00000011;
PORTB=0b00000000;
DDRB= 0b11111111;
#ifdef Cathode
PORTD=0b01111111;
DDRD= 0b00110011;
#endif
#ifdef Anode
PORTD=0b01000100;
DDRD= 0b00111011;
#endif
// Инициализируем модули
//time------------------------------------
btTimerOn = FALSE;
wTime = 0;
byTcnt = 0;
byDisplayRefreshCnt = 0;
btTimeUpdate = FALSE;
TCNT1 = 0;
TCCR1A = 0x00; // Отключаем управление выводом OC1 и PWM
TCCR1B = 0x03; // На таймер подается FCK через делитель на 64,
// шумодав отключен, никакого сброса нет
OCR1A = TCNT1 + CNT_100_MS;
TIFR |= 0x40; // Сбрасываем флаг прерываний от Output-Compare
TIMSK |= 0x40; // Разрешаем прерывание от Output-Compare
//time------------------------------------
//rmp-------------------------------------
btFirstLowRateFlash = TRUE;
wRpm = 0;
// Разрешаем прервание INT1
EIFR = 0x40;
GIMSK |= 0x40;
MCUCR = 0x02; // Настраиваем INT0 на спад, остальные биты не важны.
// Таймер запускаем сразу, чтобы проверять
// отсутствие сигнала
wTimerOvfCnt = 0;
TCNT0 = 0;
TCCR0B = 0x03; // FCK / 64 ( 62.5 KHz )
TCNT0 = 0;
TIMSK |= 0x02; // Разрешаем прерывания от TMR0
//rmp-------------------------------------
#asm("sei");
// StartLowRateRpm();
while(TRUE)
{
RefreshDisplay();
}
}