она и есть глобальная сразу после #define идет))
Проект - тахометр +кнопка START-STOP engine
volatile bit err;
она и есть глобальная сразу после #define идет))
она и есть глобальная сразу после #define идет))
- Реклама
используйте только стандартные (и производные от них) для языка Си типы переменных - это поможет вам не только сию минуту, но и вообще по жизни программистаrxstart1 писал(а):volatile bit err;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
да кстати я не успел отписаться исправил на char и эта ошибка исчезла. Но все ровно спазибо буду иметь ввиду на будущее
Изменил код, подключил 8 битный таймер Timer0 настроил по переполнению (предделитель 1024, частота 8Мгц, 1сек.-30 переполнений) и ничего не работает таймер все время обнулен, не могу понять где это происходит? Нужна помощь. Проект прилагаю.
- Вложения
-
- mega16.rar
- (263.1 КБ) 144 скачивания
- Реклама
А оно у Вас вообще компилируется? Или компилятор Вас матом кроет, а Вы не видите и не слышите?
Для начала
tachValue у Вас переменная. Нельзя в дефайне пользовать переменные. Только значения, которые заранее известны на этапе компиляции, т.е. константы. Либо TAHO_M делайте переменной.
К тому же заметил, что Вы везде пихаете надо и не надо volatile. Сильно плохо от этого не будет - но и хорошего мало. Volatile нужно ставить рядом с той переменной, которая помимо основной программы используется в прерывании. А уж внутри прерывания объявление переменной с модификатором volatile - вообще бессмысленно.
Далее, здесь
Вы молодец, предусмотрели деление на ноль. Но не предусмотрели, что будет, если переменная равна нулю. У Вас получаются 0-я частота. (Хотя по логике должна быть бесконечно большая, т.е. максимальное значение)
Для начала
Код: Выделить всё
#define TAHO_M 8000000UL/tachValue // частота вращения коленвала об/минК тому же заметил, что Вы везде пихаете надо и не надо volatile. Сильно плохо от этого не будет - но и хорошего мало. Volatile нужно ставить рядом с той переменной, которая помимо основной программы используется в прерывании. А уж внутри прерывания объявление переменной с модификатором volatile - вообще бессмысленно.
Далее, здесь
Код: Выделить всё
tachValue = TIM_GetTachBuf(); //берем "захваченное значение" и запоминаем
if (tachValue>0) tachValue = 8000000UL/tachValue; //вычисляем значение частотыспасибо сейчас пересмотрю код, на счет объявления переменных volatile, я поначалу так и делал, но в дебаге било ошибку, что переменная вне блока памяти, поставил volatile и все ок.
если частота равна 0 то двигатель выключен, не понимаю суть вопроса?Вы молодец, предусмотрели деление на ноль. Но не предусмотрели, что будет, если переменная равна нулю. У Вас получаются 0-я частота. (Хотя по логике должна быть бесконечно большая, т.е. максимальное значение)
Последний раз редактировалось rxstart1 Чт апр 24, 2014 19:38:28, всего редактировалось 1 раз.
исправил но ничего не изменилось так переменная tim2 и обнуляется (((
- Вложения
-
- mega16.rar
- (261.88 КБ) 140 скачиваний
для начала не надо давать неправильные советы.ИС-пытатель писал(а):Для началаtachValue у Вас переменная. Нельзя в дефайне пользовать переменные. Только значения, которые заранее известны на этапе компиляции, т.е. константы.Код: Выделить всё
#define TAHO_M 8000000UL/tachValue // частота вращения коленвала об/мин
в дефайне можно пользовать все, что заблагорассудится
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Виноват! Мой косяк!)) Можно все писать. )
Вам необходимо поправить все конструкции вида на предмет деления на 0. При делении на 0 программа зависнет. К тому же, эта конструкция всегда будет истинна при tachValue <= 8000000. Вообще мысленно прогоните свою программу при этой переменной равной 0. что у Вас получится?
Что у Вас сейчас конкретно не работает? или ничего не работает?
Вам необходимо поправить все конструкции вида
Код: Выделить всё
if (8000000UL/tachValue)Что у Вас сейчас конкретно не работает? или ничего не работает?
можно конечно поставить условие, но я думаю скорость работы упадет. Какие еще есть варианты?
Скорость у Вас там бешеная. Вы этого даже не заметите. Что не работает? К тому же, 70% Ваших ресурсов отжирают операции деления.
Избавился вот так,
if (tachValue>12500) //двигатель не работает
но результата нет, какие еще варианты?
if (tachValue>12500) //двигатель не работает
но результата нет, какие еще варианты?
тахометр работает переключение без нажатой CLUTCH работает
не работает если нажато сцепление CLUTCH и долго удерживается кнопка START ENGINE или кратковременно тоже не пашет((
не работает если нажато сцепление CLUTCH и долго удерживается кнопка START ENGINE или кратковременно тоже не пашет((
Под дебагом не заходит в этот кусок переменная tim2=0 ?????
if (tim2>SEC_2) // если кнопка удерживается более 2 сек.
{
if (!CLUTCH) // выжато сцепление
{
ACC=0; // выключить реле АСС <- точка останова
if (tim2>SEC_2) // если кнопка удерживается более 2 сек.
{
if (!CLUTCH) // выжато сцепление
{
ACC=0; // выключить реле АСС <- точка останова
Переключение чего?rxstart1 писал(а):тахометр работает переключение без нажатой CLUTCH работает
Не работает что? Тахометр?rxstart1 писал(а):не работает если нажато сцепление CLUTCH и долго удерживается кнопка START ENGINE или кратковременно тоже не пашет((
разбираю Вашу программу. Замечания по ходу буду добавлять.
1. Вы используете для захвата значений оборотов таймер1. Он 16-разрядный. Т.е. максимальное значение 65535. Делитель у Вас 1:1. На больших частотах вращения коленвала - это нормально. давайте посмотрим, что произойдет при запуске, когда обороты не достигли заданного значения. С какой частотой вращает стартер двигатель? вряд ли больше 100-150 оборотов в сек. + эти обороты возникают не мгновенно, а нарастают за какое-то время, хоть и малое. Итак, допустим у Вас 100 оборотов/ в мин. в какой-то период. получаем количество циклов, которое протикает через счетчик таймера = 8000000/100 = 80 000. т.к. макксимальное значение 65535, то пройдя по кругу в счетном регистре будет 14 464. Что соответствует 553 об/мин. а при 10 об/мин. в счетчике значение 4608, что соответствует 1736 об/мин.
Вам необходимо в более простом варианте увеличить коэффициент деления до 128 (с данной тактовой частотой - 256, либо в два раза уменьшаете тактовую частоту и коэффициент 64), либо вводите прерывание по переполнению этого таймера и дополнительно считаете переполнения.
2. Вот здесь правильнее будет написать
Чтобы у Вас лишний раз не вычислялось k, когда нет значения с буфера захвата.
3.
Здесь ACC=0; , но key=2;. И в результате при входе в void change_key_pos(char num) у Вас там ACC=1;, т.е. оно будет щелкать туда-сюда.
4. У каждого реле есть время включения. Неплохо было бы добавлять небольшие задержки в местах, где Вы включаете реле и ждете результата этого включения.
5. Случай отпускания кнопки.
if (8000000UL/tachValue) при tachValue = 0 программа зависнет. а при любом другом, возможном у Вас, будет всегда выполнятся. Проще просто проверять tachValue на превышение определенного значения.
6. if (tim2>SEC_05) // антидребезг
не правильно организован.
7.
даже при малых оборотах (которые, например обеспечивает сам стартер) у Вас выполнится условие и стартер тут же выключится. К тому же, он выключится нижней строкой в любом случае. Даже если завелась.
8. Кстати, я бы еще добавил какую-нить блокировку на случай, если коробка не в нейтральном положении.
1. Вы используете для захвата значений оборотов таймер1. Он 16-разрядный. Т.е. максимальное значение 65535. Делитель у Вас 1:1. На больших частотах вращения коленвала - это нормально. давайте посмотрим, что произойдет при запуске, когда обороты не достигли заданного значения. С какой частотой вращает стартер двигатель? вряд ли больше 100-150 оборотов в сек. + эти обороты возникают не мгновенно, а нарастают за какое-то время, хоть и малое. Итак, допустим у Вас 100 оборотов/ в мин. в какой-то период. получаем количество циклов, которое протикает через счетчик таймера = 8000000/100 = 80 000. т.к. макксимальное значение 65535, то пройдя по кругу в счетном регистре будет 14 464. Что соответствует 553 об/мин. а при 10 об/мин. в счетчике значение 4608, что соответствует 1736 об/мин.
Вам необходимо в более простом варианте увеличить коэффициент деления до 128 (с данной тактовой частотой - 256, либо в два раза уменьшаете тактовую частоту и коэффициент 64), либо вводите прерывание по переполнению этого таймера и дополнительно считаете переполнения.
2. Вот здесь правильнее будет написать
Код: Выделить всё
if (tachValue>0)
{ tachValue = 8000000UL/tachValue; //вычисляем значение частоты
k=(tachValue+50)/DIVIDER; // вычисляем количество диодов которые надо зажечь
}3.
Код: Выделить всё
if (tim2>SEC_2) // если кнопка удерживается более 2 сек.
{
if (!CLUTCH) // выжато сцепление
{
ACC=0; // выключить реле АСС
IGN=!err; // в зависимости от исправности
IGN_FAULT=err; // включить реле IGN
while (CHANGE_HEAT); // подождать пока не погаснет лампа свечей накала
STARTER=1; // крутить стартер пока нажата кнопка
key=2; // положение ключа зажигания IGN
}
}4. У каждого реле есть время включения. Неплохо было бы добавлять небольшие задержки в местах, где Вы включаете реле и ждете результата этого включения.
5. Случай отпускания кнопки.
if (8000000UL/tachValue) при tachValue = 0 программа зависнет. а при любом другом, возможном у Вас, будет всегда выполнятся. Проще просто проверять tachValue на превышение определенного значения.
6. if (tim2>SEC_05) // антидребезг
не правильно организован.
7.
Код: Выделить всё
while (tim2<SEC_10) // крутить 10 сек. или пока не завелась
{
if (8000000UL/tachValue) STARTER=1;// крутить пока не завелась
else
{
key=2; // завелась
tim2=SEC_10+2;
}
}
if (8000000UL/tachValue)key=0; //если не завелась потушить все приборы8. Кстати, я бы еще добавил какую-нить блокировку на случай, если коробка не в нейтральном положении.
1. По поводу таймера я не подумал. Покажите в программе как, пожалуйста. Я не разу не работал с таймером по захвату а этот кусок выдрал из программы частотомера, но она считала и выводила на дисплей и малые значения. Алгоритм подкупил тем, что считает усредненную частоту по моему 8 прерываний. Просто если как Вы говорите сделать по переполнению 8 битного счетчика тоже может возникнуть сл. ситуация: допустим угол между датчиком положения распредвала и меткой скажем 15 град. Возникает прерывание при прохождении через метку и считается частота и она в переводе на кол-во оборотов запросто может составить 1500-4500 об/мин. Т. е. стартер просто дернеться и все
((
2. почему антидребезг неправильно организован? Если кнопка удерживается менее полсекунды программа никуда не попадает и ничего не происходит или я неправ?
3. if (8000000UL/tachValue) STARTER=1;// крутить пока не завелась
Тут Вы правы на 100% забыл поставить
if (8000000UL/tachValue>640) STARTER=1;// крутить пока не завелась
4. По поводу блокировки если не на нейтрали, в этом нет смысла, ведь сцепление выжато))
5. По поводу паузы Вы абсолютно правы, я обязатьльно бы сделал ее потом, но для начала надо сделать более или менее рабочую версию, а потом можно и поизвращаться:))
6. Все таки, что не так с переменной tim2 ? Почему она обнуляется и почему программа не заходит в ручную и автоматическую заводку?
7. посмотрите последнюю версию, что я присылал я там переделал, вот например как выглядит отпускание, деления но 0 не будет
if (START_BUTTON && trig) // кнопка отпущена
{
if (tim2>SEC_05) // антидребезг
{
if (!CLUTCH) // выжато сцепление
{
//______________________
// АВТОЗАПУСК (Крутить стартер пока обороты не достигнут 640/об мин либо 10сек)
//______________________
if (tachValue>12500) //двигатель не работает
{
ACC=0; // выключить реле АСС
key=2; // положение ключа зажигания IGN
IGN=!err; // в зависимости от исправности
IGN_FAULT=err; // включить реле IGN
tim2=0; //сбросить счетчик T2
while (CHANGE_HEAT); // подождать пока не погаснет лампа свечей накала
while (tim2<SEC_10) // крутить 10 сек. или пока не завелась
{
if (tachValue>12500) STARTER=1;// крутить пока не завелась
else
{
key=2; // завелась
tim2=SEC_10+2;
}
}
if (!tachValue)key=0; //если не завелась потушить все приборы
}
}
change_key_pos(key);
}
trig=0; // сбросить триггер
}
2. почему антидребезг неправильно организован? Если кнопка удерживается менее полсекунды программа никуда не попадает и ничего не происходит или я неправ?
3. if (8000000UL/tachValue) STARTER=1;// крутить пока не завелась
Тут Вы правы на 100% забыл поставить
if (8000000UL/tachValue>640) STARTER=1;// крутить пока не завелась
4. По поводу блокировки если не на нейтрали, в этом нет смысла, ведь сцепление выжато))
5. По поводу паузы Вы абсолютно правы, я обязатьльно бы сделал ее потом, но для начала надо сделать более или менее рабочую версию, а потом можно и поизвращаться:))
6. Все таки, что не так с переменной tim2 ? Почему она обнуляется и почему программа не заходит в ручную и автоматическую заводку?
7. посмотрите последнюю версию, что я присылал я там переделал, вот например как выглядит отпускание, деления но 0 не будет
if (START_BUTTON && trig) // кнопка отпущена
{
if (tim2>SEC_05) // антидребезг
{
if (!CLUTCH) // выжато сцепление
{
//______________________
// АВТОЗАПУСК (Крутить стартер пока обороты не достигнут 640/об мин либо 10сек)
//______________________
if (tachValue>12500) //двигатель не работает
{
ACC=0; // выключить реле АСС
key=2; // положение ключа зажигания IGN
IGN=!err; // в зависимости от исправности
IGN_FAULT=err; // включить реле IGN
tim2=0; //сбросить счетчик T2
while (CHANGE_HEAT); // подождать пока не погаснет лампа свечей накала
while (tim2<SEC_10) // крутить 10 сек. или пока не завелась
{
if (tachValue>12500) STARTER=1;// крутить пока не завелась
else
{
key=2; // завелась
tim2=SEC_10+2;
}
}
if (!tachValue)key=0; //если не завелась потушить все приборы
}
}
change_key_pos(key);
}
trig=0; // сбросить триггер
}


