Есть задача - в зависимости от скорости,оборотов и температуры двигателя, открывать клапан.
Температура - аналоговый сигнал, примерно от 4 до 1 вольт.
Обороты - импульсы, причем длинна импульса означает время, потраченное на работу одного цилиндра за полный оборот двигателя.
Скорость - 9 импульсов за полный оборот колеса.
Условие срабатывания клапана - температура более 50 гр. (~2.5 вольт), обороты более 1200 либо скорость более 60 км/ч.
Написал код (до этого с программированием не связывался практически совсем):
CODE
#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned int spd_impulse = 0;
volatile unsigned int spd = 0;
volatile unsigned int rpm = 65535;
volatile unsigned int temp_flag = 0;
ISR(INT0_vect) {
spd_impulse++; // Считаем импульсы с датчика скорости
}
ISR(TIMER2_COMP_vect) {
spd = spd_impulse; // Передаем переменной spd колличество импульсов за 0.2 сек
spd_impulse = 0; // обнуляем счетчик
}
ISR(TIMER1_CAPT_vect) {
if((TCCR1B & (1<<ICES1)) != 0 ) {
TCNT1 = 0;
ICR1 = 0;
TCCR1B &= ~(1<<ICES1); // Прерывание по нисходящему фронту
}
else {
TCCR1B |= (1<<ICES1); // Прерывание по восходящему фронту
rpm = (ICR1); // Передаем переменной rpm количество тиков счетчика, поместившихся в длину импульса от тахометра
}
}
ISR(ADC_vect){
temp_flag = ADC; // Присваиваем переменной значение ЦАП
ADCSRA |=(1<<ADSC); // Запускаем ЦАП
}
int main(void)
{
sei();
// настройка прерываний по импульсам с датчика скорости
GICR |= (1 << INT0);
MCUCR |= (1 << ISC01)|(1 << ISC00); // Прерывание формируется по переднему фронту
// Настройка таймера для подсчета количества импульсов скорости каждые 0.2 сек
OCR2 = 0xC4; // Отчитываем 0.2 секунды.
TIMSK |= (1<<OCIE2); // Прерывание по совпадению
TCCR2 |= 0x07; // делитель на 1024
TCCR2 |= (1<<WGM21); // Сброс при совпадении
// Настройка прерываний и таймера тахометр
TIMSK |= (1<<TICIE1); // разрешить прерывание на захват
TCCR1B |= (1<<ICES1); // Прерывание по восходящему фронту
TCCR1B |= (1<<CS10)|(1<<CS11); // тактирование счетчика 64
// Датчик температуры
ADCSRA |=(1<<ADEN)|(1<<ADIE)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);
ADMUX |=(1<<REFS0)|(1<<REFS1)|(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3);
ADCSRA |=(1<<ADSC); // Запускаем ЦАП
DDRC &= ~(1<<0); // Порт датчика температуры
DDRD |= (1<<0); // Порт включения клапана
DDRB |= (1<<1); // Индикация температура
DDRB |= (1<<2); // Индикация обороты
DDRB |= (1<<3); // Индикация скорость
volatile unsigned char rpm_flag = 0;
volatile unsigned char spd_flag = 0;
while(1) {
// Задаем люфт условий открывания клапана
if (rpm < 130) {
rpm_flag = 1;
}
else if (rpm > 135) {
rpm_flag = 0;
}
if (spd > 11) {
spd_flag = 1;
}
else if (spd < 10) {
spd_flag = 0;
}
// Проверяем условия
if (temp_flag < 1000) { // Ждем пока температура достигнет рабочей
ADCSRA &= ~(1<<ADSC)|(1<<ADIE); // Отключаем работу АЦП до следующего холодного старта
PORTB |= (1<<1); // Сигнализируем, что температура в норме
if (spd_flag == 1) { // Проверка флага скорости
PORTD |= (1<<0); // Открываем клапан
PORTB |= (1<<3); // Сигнализируем открытие клапана по скорости
}
else if (rpm_flag == 1 ) { // // Проверка флага оборотов
PORTD |= (1<<0); // Открываем клапан
PORTB |= (1<<2); // Сигнализируем открытие клапана по оборотам
}
else {
PORTD &= ~(1<<0); // Отключаем клапан
}
}
PORTB &= ~(1<<1)||(1<<2)|(1<<3); // Гасим всю индикацию.
}
}
Вроде работает исправно. Прошу если кому не сложно, указать на ошибки программирования, может можно что-то оптимизировать.
Забыл добавить - делаю устройство на Atmega8
Сообщение отредактировал Herz - Apr 20 2016, 08:11