Автор работы: Пользователь скрыл имя, 25 Декабря 2011 в 15:25, курсовая работа
Используя средства языка программирования необходимо создать цифровой тахометр на основе микроконтроллера ATtiny 2313 семейства AVR. Должны выполняться действия: измерение оборотов двигателя, вывод значений оборотов на светодиодный индикатор, возможность уменьшения яркости индикатора при включении габаритных огней.
1 Теоретическая часть 3
1.1 Аннотация 3
1.2 Постановка задачи 3
1.3 Общие сведения о микроконтроллерах AVR 3
1.4 Описание ATtiny2313 3
1.5 Основные параметры ATtiny2313 4
1.6 Блок-схема ATtiny2313 6
1.7 Расположение выводов ATtiny2313 7
1.8 Программирование микроконтроллера с использованием программы на языке С 8
2 Конструкторская часть 9
2.1 Общие сведения.Функциональное назначение используемых программ 9
2.2 Реальзация 10
2.3 Схема принципиальная 10
2.4 Вызов и загрузка 11
3 Заключение 11
4 Быблиографический список 11
{
wRpm++;
R += 10;
}
byDisplay[3] = 0;
// Первые 4 цифр - обороты двигателя
for(i=0; i<3; i++)
{
byDisplay[2-i] = wRpm % 10;
wRpm /= 10;
}
if (R < 10)
{
byDisplay[0] = 10;
byDisplay[1] = 10;
byDisplay[2] = 10;
goto exit;
}
if ((R >= 10) & (R <100))
{
byDisplay[0] = 10;
byDisplay[1] = 10;
goto exit;
}
if ((R >= 100) & (R <1000))
{
byDisplay[0] = 10;
goto exit;
}
exit:
}
/************************
Вывод экранного буфера на дисплей.
Вход: -
Выход: -
\************************
void ShowDisplayData(void)
{
#ifdef Cathode
PORTB = byCharacter[byDisplay[0]];
PORTD.5 = 0;
delay_us(LED_delay);
PORTD.5 = 1;
PORTB = byCharacter[byDisplay[1]];
PORTD.1 = 0;
delay_us(LED_delay);
PORTD.1 = 1;
PORTB = byCharacter[byDisplay[2]];
PORTD.0 = 0;
delay_us(LED_delay);
PORTD.0 = 1;
PORTB = byCharacter[byDisplay[3]];
PORTD.4 = 0;
delay_us(LED_delay);
PORTD.4 = 1;
#endif
#ifdef Anode
PORTB = ~byCharacter[byDisplay[0]];
PORTD.5 = 1;
delay_us(LED_delay);
PORTD.5 = 0;
PORTB = ~byCharacter[byDisplay[1]];
PORTD.1 = 1;
delay_us(LED_delay);
PORTD.1 = 0;
PORTB = ~byCharacter[byDisplay[2]];
PORTD.0 = 1;
delay_us(LED_delay);
PORTD.0 = 0;
PORTB = ~byCharacter[byDisplay[3]];
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=0b01001100;
DDRD= 0b00110011;
#endif
// Инициализируем модули
//time------------------------
btTimerOn = FALSE;
wTime = 0;