реклама на сайте
подробности

 
 
> Первый проект на АТМЕГА
ddwrt
сообщение Apr 18 2016, 09:19
Сообщение #1





Группа: Участник
Сообщений: 6
Регистрация: 18-04-16
Пользователь №: 91 345



Есть задача - в зависимости от скорости,оборотов и температуры двигателя, открывать клапан.
Температура - аналоговый сигнал, примерно от 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
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
XVR
сообщение Apr 18 2016, 10:17
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Квалификаторы volatile на переменных rpm_flag и spd_flag излишни
sei(); переставить после настройки портов и прерываний
Сравнения типа spd_flag == 1 переделать на spd_flag != 0

По коду -
При старте переменная temp_flag находится в 0, и если ADC не успеет получить результат до проверки if (temp_flag < 1000) то if сработает и в первой же строке выключит ADC насовсем. Кажется это не совсем желаемое поведение sm.gif

Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th June 2025 - 23:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01377 секунд с 7
ELECTRONIX ©2004-2016