Светодиодные фонари и световые приборы. Всё о светотехнике.
Вернуться   Форум FONAREVKA.RU Лаборатория Разработка и модификация фонарей Разработка и модификация электроники фонарей
Расширенный поиск
Забыли пароль? Регистрация

  • О нашем проекте
  • Светотехника и световые приборы
  • Правила форума
Проект FONAREVKA.RU специализируется на предоставлении всей необходимой информации по светотехнике:

— светодиодные фонари;
— различные источники питания;
— разнообразные зарядные устройства;
— освещение помещений и наружное освещение;
— световые приборы для личного, пассажирского и грузового транспорта;
— специальные световые приборы для медицины, для растений, для аквариумов, для террариумов, а также аварийно-сигнальные световые приборы;
— альтернативные источники света;
— лазеры и лазерная техника.

Если у вас есть вопросы по выбору фонарей, аккумуляторов и зарядных устройств ознакомьтесь с FAQ от наших экспертов:

F.A.Q. по выбору фонарей различных типов;
F.A.Q. по выбору аккумуляторов;
F.A.Q. по выбору зарядных устройств.
Ответ  Создать новую тему
Просмотров в теме 229570   Ответов в теме 536   Подписчиков на тему 45   Добавили в закладки 31
Опции темы Поиск в этой теме
Старый 03.02.2014, 15:08   41
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Кто можетсказать, где в этой прошивке обрабатывается нажатие кнопки? Группы режимов, количество нажатий? Чтоб сократить их количество и поменять последовательность.
MSS вне форума   Ответить с цитированием Вверх
Старый 03.02.2014, 15:19   42
galex
сволочь фонарёвки
 
Регистрация: 27.05.2011
Последняя активность: Сегодня 22:43
Адрес: Россия, Пермский край
Сообщений: 38196
Сказал(а) спасибо: 5886
Поблагодарили: 32495 раз(а) в 15080 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

группы-режимы:
unsigned char Mode[5][3]={{6,6,6},{29,33,36},{73,117,146},{0b00001,0b01000,0b01001},{0b10000,0b10001,0b11001}};
первые режимы в трех группах, вторые режимы в трех и т.д. до 5-го (десятичные цифры - скажность, двоичные - управление выходными портами, чтобы включались соответствующие стабилизаторы )

нажатия обрабатываются в процедуре
static inline void SwitchMode()

[Исправлено: galex, 03.02.2014 в 15:20]
galex вне форума   Ответить с цитированием Вверх
Старый 03.02.2014, 18:49   43
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

допустим, я хочу оставить только одну группу

1 . 5 шимом из 350
2 . 50 шимом из 350
3 . 200 шимом из 350
4 . 1050 без шима
5 . 2800 без шима

Что из этого массива остается? Так?
unsigned char Mode[5]={6,36,146,0b01001,0b11001};

И я не вкурю никак, каким образом мы кнопку опрашиваем.
PORTB &= ~_BV(PB1); = сюда смотреть?
Как изменять число нажатий? По программе понятно, что по значению в (B == 0b/число/) выбирается режим.
Но как туда число попадает...
Голова сегодня уже квадратом от настроек ШИМ и портов
MSS вне форума   Ответить с цитированием Вверх
Старый 03.02.2014, 19:05 Автор темы   44
ceramic
Ветеран Фонарёвки
 
Аватар для ceramic
 
Регистрация: 08.10.2011
Последняя активность: 26.03.2024 21:08
Адрес: 哈尔滨
Сообщений: 8022
Сказал(а) спасибо: 934
Поблагодарили: 5193 раз(а) в 2784 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Цитата:
Посмотреть сообщение Сообщение от MSS :
Что из этого массива остается? Так?
unsigned char Mode[5]={6,36,146,0b01001,0b11001};
Так (ну и NGroupe удалить из программы).

Цитата:
Посмотреть сообщение Сообщение от MSS :
И я не вкурю никак, каким образом мы кнопку опрашиваем.
При нажатии/отпускании кнопки генерится прерывание ISR(INT0_vect).
ceramic вне форума   Ответить с цитированием Вверх
Старый 03.02.2014, 23:18   45
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Спасибо. Завтра днем буду дальше разбираться. Погуглю ISR
MSS вне форума   Ответить с цитированием Вверх
Старый 04.02.2014, 13:28   46
dralexandr
Увлеченный
 
Аватар для dralexandr
 
Регистрация: 14.04.2011
Последняя активность: 11.04.2015 10:51
Адрес: Беларусь
Сообщений: 52
Сказал(а) спасибо: 5
Поблагодарили: 7 раз(а) в 6 сообщениях

Отправить сообщение для dralexandr с помощью ICQ
По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

а можно вместо кнопки, подключить магнитный датчик ?
dralexandr вне форума   Ответить с цитированием Вверх
Старый 04.02.2014, 13:32   47
galex
сволочь фонарёвки
 
Регистрация: 27.05.2011
Последняя активность: Сегодня 22:43
Адрес: Россия, Пермский край
Сообщений: 38196
Сказал(а) спасибо: 5886
Поблагодарили: 32495 раз(а) в 15080 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

почему нет, вполне. который дискретный. но, управление ползунком/кольцом/кнопкой с большим ходом - вы сможете морзянку отбивать таким?
galex вне форума   Ответить с цитированием Вверх
Старый 04.02.2014, 13:45   48
dralexandr
Увлеченный
 
Аватар для dralexandr
 
Регистрация: 14.04.2011
Последняя активность: 11.04.2015 10:51
Адрес: Беларусь
Сообщений: 52
Сказал(а) спасибо: 5
Поблагодарили: 7 раз(а) в 6 сообщениях

Отправить сообщение для dralexandr с помощью ICQ
По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

мне всего 3 режима надо в подводн фонарь, а какой датчик взять подскажите , я так понял хола нельзя ?
dralexandr вне форума   Ответить с цитированием Вверх
Старый 04.02.2014, 13:55   49
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Пишу для себя коменты к коду, многое уже понятно. Но все равно еще не понял, как записываются биты в B, куда посмотреть?
B == 0b00000001 // < . >
B == 0b00010000 //< _ >
B == 0b00010010 // < _ . >
B == 0b00100001 //< . _ >
B == 0b00000011 // < . . >
B == 0b00110000 //< _ _ >
B == 0b01110000 //< _ _ _ >
B == 0b00000111 //< . . . >
Допишу коменты, выложу. Пока что разобрался с портами выхода и режимами.

static inline void SwitchMode()
{
unsigned char n;
if (B == 0b00000111) //тройное короткое нажатие < . . . >
{
for (n = 0; n<5; n++) //Индикация напряжения на батарее
// Полностью заряжено – 5 миганий, разряжено – одно мигание
{
blink();
if (adch_val<volt[n]) break; // сравниваем с порогом напряжений volt [4] = {146, 156, 165, 174}
}
delay_();
delay_();
goto m2;
}
else if ((B == 0b00000001) & (Power == 1)) //короткое нажатие < . >
{
if (Nmode<3) Nmode++; // Переключение вверх только в трех средних режимах яркости текущей группы
}
else if ((B == 0b00000011) & (Power == 1)) // двойное короткое < . . >
{
if (Nmode>1) Nmode--; //Переключение вниз только в трех средних режимах яркости текущей группы
}
else if (B == 0b00010010) //Переключение между группами 1-я: < _ . >
{
NGroupe=0;
blink();
}
else if (B == 0b00010110) //Переключение между группами 2-я: < _ . . >
{
NGroupe=1;
blink();
}
else if (B == 0b00011110) //Переключение между группами 3-я: < _ . . . >
{
NGroupe=2;
blink();
}

/*********************************************************************
ниже 5 команд на непосредственное включение сразу
в любом из пяти режимов текущей группы
(1: < _ _ _ >, 2: < . _ >, 3: < . . _ >, 4: < . . . _ >, 5 : < _ _ >)
**********************************************************************/

else if (B == 0b01110000) Nmode=0; //< _ _ _ > между длинным и коротким = четыре 0000
else if (B == 0b00100001) Nmode=1; //< . _ > длинные 0b001 слева , короткие справа 00001
else if (B == 0b01000011) Nmode=2; //< . . _ >
else if (B == 0b10000111) Nmode=3; //< . . . _ >
else if (B == 0b00110000) Nmode=4; //< _ _ > самый яркий

/*
Пример - назначить на двойное долгое нажатие < _ _ > младший режим;
else if (B == 0b00110000) Nmode=4; => поменять на Nmode=0
Длинное нажатие -- дольше 0,25с, пауза больше 0,5с -- окончание ввода
Пример - удаление
else if (B == 0b00110000) Nmode=4;
ограничивает максимальный ток до 1050мА (драйвер на 2800мА), уменьшая кол-во режимов (пропадает старший)
*/
/*
Группа режимов выбирается из Mode[5][3]
Для ШИМ первые три:{6,6,6},{29,33,36},{73,117,146} цифры - коэффициент заполнения, больше=ярче
Без ШИМ
четвертый режим:
0b00001 = 350мА = 1 чип на пятой ноге, включаем выход PB0
0b01000 = 700мА = 2 чипа на второй ноге, включаем выход PB3
0b01001 = 1050мА = 1чип+2чипа, включаем выход PB0 и PB3 = 5 и 2 нога
пятый режим:
0b10000 = 1750мА = 5 чипов на третьей ноге, включаем выход PB4
0b10001 = 2100мА = 1+5 чипов на пятой и третьей ноге, включаем выход PB0 и PB5
0b11001 = 2800мА = все 8 чипов, включены выход PB0, PB4, PB5

Расположение выходов МК
PB0 = 5 нога
PB1 = 6 нога (INT0)
PB2 = 7 нога
PB3 = 2 нога
PB4 = 3 нога
PB5 = 1 нога (ADC0)

6-й вывод для кнопки, ибо только замыканием этого вывода на землю
можно разбудить драйвер из глубокой спячки - прерывание INT0
*/
else if ((Power == 0) & (B == 0b00010000)); //Включение длинным нажатием < _ >
else
{
if ((Power == 0) || (B == 0b00010000)) Off(); //Выключение длинным нажатием < _ >
goto m2;
}
Power = 1;
MSS вне форума   Ответить с цитированием Вверх
Поблагодарили: 1 раз
Ikepod (07.12.2014)
Старый 04.02.2014, 14:03   50
galex
сволочь фонарёвки
 
Регистрация: 27.05.2011
Последняя активность: Сегодня 22:43
Адрес: Россия, Пермский край
Сообщений: 38196
Сказал(а) спасибо: 5886
Поблагодарили: 32495 раз(а) в 15080 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Цитата:
Посмотреть сообщение Сообщение от dralexandr :
мне всего 3 режима надо в подводн фонарь
посмотрите тогда еще один вариант драйвера под тактовую. как раз 3 режима +мунлайт, и очень простое управление

Цитата:
Посмотреть сообщение Сообщение от dralexandr :
я так понял хола нельзя ?
можно, почему нет. конкретную марку не подскажу, но надо искать дискретный (не аналоговый) с питанием от менее 3В, и как можно менее потребляющий в ждущем режиме (и все равно, скорее всего это будет в разы больше, чем 0.2мкА драйвера).
возможно из телефона-раскладушки можно выковырять такой.
galex вне форума   Ответить с цитированием Вверх
Старый 04.02.2014, 14:23   51
galex
сволочь фонарёвки
 
Регистрация: 27.05.2011
Последняя активность: Сегодня 22:43
Адрес: Россия, Пермский край
Сообщений: 38196
Сказал(а) спасибо: 5886
Поблагодарили: 32495 раз(а) в 15080 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Цитата:
Посмотреть сообщение Сообщение от MSS :
как записываются биты в B, куда посмотреть?
если просто записать, то PORTB =
если какой-то конкретный бит (например второй) установить/сбросить, то
PORTB |= _BV(PB2); / PORTB &= ~_BV(PB2);
ну или сразу несколько, первый и третийй, допустим:
PORTB |= 0b00101; / PORTB &=~ 0b00101;

вроде так.
galex вне форума   Ответить с цитированием Вверх
Старый 04.02.2014, 16:28   52
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

TCCR0A = 0x83;
задаем режим работы ШИМ 0b10000011 - это получается у нас FAST PWM?
режим сброса OC0A при совпадении, и установки OC0A при достижении конца
COM0A1=1|COM0A0=0|COM0B1=0|COM0B0=0|-|-|WGM01=1|WGM00=1

Зачем тогда используют ШИМ с фазовой коррекцией в других прошивках (с той же веломании 0х21 - выход на РВ1)?
MSS вне форума   Ответить с цитированием Вверх
Старый 04.02.2014, 18:41   53
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Еще вопрос по обработке прерывания INT0. Для чего каждая строчка подробно?
WDTCR |= (1<<WDCE) | (1<<WDE); //установка битов WDCE и WDE в 1? Это включение вочдога для атини13?
WDTCR = 0x40 - что это дает?

[Исправлено: MSS, 04.02.2014 в 18:44]
MSS вне форума   Ответить с цитированием Вверх
Старый 05.02.2014, 16:04   54
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Есть вопросы по обработке прерывания по вочдогу.
Посмотрите, кто разбирается и сможет дополнить?
кусок с проверкой напряжения на аккуме более менее понятен. (при Р=0)
Не понятно зачем включать и сразу выключать вочдог?

Далее по обработке короткого нажатия на кнопку
есть условие
if ((bit_is_set(PINB,PB1)))
{выполняем код и далее идет вочдог}
WDTCR = 0x46 - почему 46? в даташит это зарезервированное значение.
там же
MCUCR=0x00;//The low level of INT0 generates an interrupt request это находится в условии, что кнопка не нажата. как это работает?

Чуть ниже
else
{P=2
WDTCR |= (1<<WDCE) | (1<<WDE);// включили вочдог
WDTCR = 0x44; //опять не понятно, почему 44??WDP3,WDP2=1; WDP1,WDP0=0 - зарезервировано???????????????
}
}

MCUCR=0x03;// The rising edge of INT0 generates an interrupt request т.е. при отпускании нажатой кнопки прерывание?

И весь этот кусок заканчивается GIMSK=0x40;//101000 внешнее прерывание по INT0 не разрешено?? как это понимать?

Не понятна логика работы ISR(WDT_vect) обработчика прерывания вочдога (
например как это понять?
B|=((1<<NB)<<4) ???

[Исправлено: MSS, 05.02.2014 в 17:43]
MSS вне форума   Ответить с цитированием Вверх
Старый 06.02.2014, 15:19   55
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Вот, что у меня получилось откаментировать. Лично мне теперь на много понятней стало, что же там понаписано в программе было.
Только не понял с регистрами GIMSK=0x40 -почему записываем 40?


/*
* LED Driver Tactical Button
*
* Created: 09.04.2013 3:36:20
*
* FIRMWARE VERSION: 1.0
*
* This code is distributed under the GNU Public License
* which can be found at http://www.gnu.org/licenses...
*
* Author: Ceramic https://forum.fonarevka.ru/...
*/
#include<avr/io.h>
#include<avr/delay.h>
#include<avr/interrupt.h>

unsigned char P = 0;
volatile unsigned char B = 0;
unsigned char NB = 0;
volatile unsigned char Cod = 1;
unsigned char adch_val;
unsigned char nV=0;
unsigned char Power=0;
unsigned char Nmode=3;
unsigned char NGroupe=0;
unsigned char Mode[5][3]={{6,6,6},{29,33,36},{73,117,146},{0b00001,0b01000,0b01001},{0b10000,0b10001,0b11001}};
unsigned char volt [4] = {146, 156, 165, 174}; //порог напряжений (для смены режимов на меньший или индикации заряда аккум)

static inline void delay_()
{
_delay_ms(800); //задержка 800мс
}

static inline void blink() //моргает диод
{
TCCR0A = 0x00; //ШИМ выключен
PORTB &=~ 0b11001; // ~ знак поразрядного инвертирования PB4 PB3 PB0 по идее выключит все выходы ???
delay_(); //задержка (800мс)
PORTB |= 0b00001; //включаем выход PB0 (пятая нога, 1 чип)
delay_(); //задержка 800мс
PORTB &=~ 0b00001; //выключаем PB0
}

static inline void Off() // выключаем все и спим
{
Power = 0;
OCR0A = 0x00; //ШИМа нет 0 на выходе
TCCR0B = 0x00; //счетчик выключен
TCCR0A = 0x00; ///ШИМ выключен
PORTB = 0x02; ///0b00000010 выходы выключены PB4 PB3 PB0; PB1 Pull-up - лог "1" пока не нажата кнопка
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00; //отключение вочдог
MCUCR=0x30; //The falling edge of INT0 generates an interrupt request прерывание по нажатию кнопки
GIMSK=0x40;
BODCR = 0x03;
BODCR = 0x02;
sei();
asm("sleep");
MCUCR &=~(1<<SE);
TCCR0B = 0x1; /*
В качестве тактового сигнала выбирается один из выходов
со специального встроенного делителя тактовой частоты.
Для выбора одного из этих сигналов служит специальный регистр TCCR0B
TCCR0B=0x00 таймер остановлен. Можно использовать это значение как выключалку таймера-счетчика
TCCR0B=0x01 деление на единицу
TCCR0B=0x02 деление на 8
TCCR0B=0x03 деление на 64
TCCR0B=0x04 деление на 256
TCCR0B=0x05 деление на 1024 */
}

static inline void SwitchMode()
{
unsigned char n;
if (B == 0b00000111) //тройное короткое нажатие < . . . >
{
for (n = 0; n<5; n++) //Индикация напряжения на батарее
// Полностью заряжено – 5 миганий, разряжено – одно мигание
{
blink();
if (adch_val<volt[n]) break; // сравниваем с порогом напряжений volt [4] = {146, 156, 165, 174}
}
delay_();
delay_();
goto m2;
}
else if ((B == 0b00000001) & (Power == 1)) //короткое нажатие < . >
{
if (Nmode<3) Nmode++; // Переключение вверх только в трех средних режимах яркости текущей группы
}
else if ((B == 0b00000011) & (Power == 1)) // двойное короткое < . . >
{
if (Nmode>1) Nmode--; //Переключение вниз только в трех средних режимах яркости текущей группы
}
else if (B == 0b00010010) //Переключение между группами 1-я: < _ . >
{
NGroupe=0;
blink();
}
else if (B == 0b00010110) //Переключение между группами 2-я: < _ . . >
{
NGroupe=1;
blink();
}
else if (B == 0b00011110) //Переключение между группами 3-я: < _ . . . >
{
NGroupe=2;
blink();
}

/*********************************************************************
ниже 5 команд на непосредственное включение сразу
в любом из пяти режимов текущей группы
(1: < _ _ _ >, 2: < . _ >, 3: < . . _ >, 4: < . . . _ >, 5 : < _ _ >)
**********************************************************************/

else if (B == 0b01110000) Nmode=0; //< _ _ _ > между длинным и коротким = четыре 0000
else if (B == 0b00100001) Nmode=1; //< . _ > длинные 0b001 слева , короткие справа 00001
else if (B == 0b01000011) Nmode=2; //< . . _ >
else if (B == 0b10000111) Nmode=3; //< . . . _ >
else if (B == 0b00110000) Nmode=4; //< _ _ > самый яркий

/*
Пример - назначить на двойное долгое нажатие < _ _ > младший режим;
else if (B == 0b00110000) Nmode=4; => поменять на Nmode=0
Длинное нажатие -- дольше 0,25с, пауза больше 0,5с -- окончание ввода
Пример - удаление
else if (B == 0b00110000) Nmode=4;
ограничивает максимальный ток до 1050мА (драйвер на 2800мА), уменьшая кол-во режимов (пропадает старший)
*/
/*
Группа режимов выбирается из Mode[5][3]
Для ШИМ первые три:{6,6,6},{29,33,36},{73,117,146} цифры - коэффициент заполнения, больше=ярче
Без ШИМ
четвертый режим:
0b00001 = 350мА = 1 чип на пятой ноге, включаем выход PB0
0b01000 = 700мА = 2 чипа на второй ноге, включаем выход PB3
0b01001 = 1050мА = 1чип+2чипа, 5 и 2 нога, включаем выход PB0 и PB3
пятый режим:
0b10000 = 1750мА = 5 чипов на третьей ноге, включаем выход PB4
0b10001 = 2100мА = 1+5 чипов на пятой и третьей ноге, включаем выход PB0 и PB4
0b11001 = 2800мА = все 8 чипов, включены выход PB0, PB4, PB3

Расположение выходов МК
PB0 = 5 нога
PB1 = 6 нога (INT0)
PB2 = 7 нога
PB3 = 2 нога
PB4 = 3 нога
PB5 = 1 нога

6-й вывод для кнопки, ибо только замыканием этого вывода на землю
можно разбудить драйвер из глубокой спячки - прерывание INT0
*/
else if ((Power == 0) & (B == 0b00010000)); //Включение длинным нажатием < _ >
else
{
if ((Power == 0) || (B == 0b00010000)) Off(); //Выключение длинным нажатием < _ >
goto m2;
}
Power = 1;


m2: Cod=0;
n=Mode[Nmode][NGroupe];
if (Power==1)
{
TCCR0A = 0x00; //выключаем ШИМ
PORTB &=~ 0b11001; //~ знак поразрядного инвертирования выключаем все выходы PB4 PB3 PB0
if (Nmode>2) PORTB |= n; //Nmode>2 включает согласно режиму соответствующие выходы PB0 PB3 PB4 без ШИМ
else
{
TCCR0A = 0x83;
/*задаем режим работы ШИМ 0b10000011 -011 FAST PWM выход ШИМ на PB0
COM0A1=1|COM0A0=0|COM0B1|COM0B0|-|-|WGM01=1|WGM00=1

Микроконтроллер ATtiny13 имеет два независимых канала ШИМ.
Выход канала, который мы используем, называется OC0A (выходит на PB0).
А другой канал называется OC0B (выходит на PB1)

Установив COM0A1 (восьмой бит) = 1 и COM0A0 (седьмой бит) = 0, мы выбираем режим сброса OC0A при совпадении,
и установки OC0A при достижении конца.
Это означает, что в тот момент, когда значение счетного регистра TCNT0 таймера
окажется равным значению регистра OCR0A, выход OC0A (PB0) будет сброшен в "0".
Когда же таймер досчитает до своего максимального значения (TCNT0 = 255),
на выходе OC0A установится логическая "1".
Изменяя значение OC0A, можно менять ширину выходного импульса.
*/
OCR0A = n; //режим яркости в зависимости от группы режимов NGroupe и Mode
/*
на выходе PB0 микроконтроллера (ножка 5) будет присутствовать ШИМ сигнал
с заполнением пропорционально значению регистра OCR0A
OCR0A=0; — ШИМа небудет, ноль на выходе
OCR0A=127; — на выходе ровный меандр с заполнением 50/50
OCR0A=255; — на выходе единица, ШИМа нет
*/
}
}
else Off();
}

void main(void) __attribute__((__noreturn__));
void main(void)
/*
Очень хороший приемчик - сделать функцию main ничего не возвращающей.
Позволяет съэкономить на ненужных push и pop целых 36 байт!
По умолчанию функция main обычно определена как int main (void)
*/

{
DDRB = 0b11001; //порт PB4, PB3, PB0 настроен как выход; PB1,PB5??? вход
CLKPR = 0x80; //команды настройки регистра внутреннего делителя частоты
CLKPR = 0x01; /*01-делитель=1 CLKPR = 0x80 = для этого регистра для изменения делителя необходимо записать единичку в седьмой бит,
после чего микроконтроллер даст изменить и выбрать необходимый делитель в первых четырех битах этого регистра.
После того, как пройдет четыре такта выполнения команд процессора, изменить регистр будет уже нельзя.
Нужно снова сначала изменить седьмой бит CLKPR=0x80 а затем указать делитель CLKPR=нужный делитель
*/
ACSR = 0x80; /* Analog Comparator Control and Status Register – ACSR
установка единицы в Bit 7 – ACD: Analog Comparator Disable (0х80) отключает аналоговый компаратор,
его можно выключить в любой момент, это приводит к снижению потребления электричества
*/
ADMUX = 0x61; /*01100001 ADC Multiplexer Selection Register
внешний источник напряжения, вход PB2
Bit 6 – REFS0: Reference Selection Bit
0 VCC used as analog reference.
1 Internal Voltage Reference.
Bit 5 – ADLAR: ADC Left Adjust Result
The ADLAR bit affects the presentation of the ADC conversion result in the ADC Data
Register. Write one to ADLAR to left adjust the result.
Bits 1:0 – MUX1:0: Analog Channel Selection Bits
MUX1..0 Single Ended Input
00 ADC0 (PB5)
01 ADC1 (PB2) наш вариант -вход с делителя
10 ADC2 (PB4)
11 ADC3 (PB3)
*/
while(1)
{
if (Cod==1) SwitchMode(); //Основной цикл ?)
}
}

ISR(INT0_vect) //процедура обработки прерывания INT0 (кнопка порт PB1)
{
GIMSK=0x00; /*Если разряд INT1(бит7)/INT0(бит6) установлен в лог. 1,
то внешнее прерывание по входу INT1/INT0 будет разрешено до тех пор,
пока установлен в лог. 1 разряд I в регистре состояния SREG. */
if (P==0)
{
P=1;
B=0;
}
else if (P==2) P=3; //Р=2 при длинном нажатии (нажали и удержали) ???
else if (P==4) P=6;
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
/*бит разрешения изменений WDCE и бит включения WDE
для включения достаточно установить бит WDE в единичное состояние,
одновременно, если надо, устанавливается и период таймера битами WDP2. .0 того же регистра,
задающими коэффициент деления генератора
(состояние 000 соответствует минимальному периоду ~15 мс, 110 — примерно 1 с, 111 задает максимальный период немного менее 2 с).
Bit 7 - WDTIF: Watchdog Timer Interrupt Flag
Bit 6 - WDTIE: Watchdog Timer Interrupt Enable
Bit 4 - WDCE: Watchdog Change Enable
This bit is used in timed sequences for changing WDE and prescaler bits. To clear the
WDE bit, and/or change the prescaler bits, WDCE must be set.
Once written to one, hardware will clear WDCE after four clock cycles.
Bit 3 - WDE: Watchdog System Reset Enable
WDE is overridden by WDRF in MCUSR. This means that WDE is always set when
WDRF is set. To clear WDE, WDRF must be cleared first. This feature ensures multiple
resets during conditions causing failure, and a safe start-up after the failure.
Bit 5, 2..0 - WDP3..0: Watchdog Timer Prescaler 3, 2, 1 and 0
WDP3 WDP2 WDP1 WDP0 Number of WDT Oscillator Cycles
0 0 0 0 2K (204 cycles 16 ms
0 0 0 1 4K (4096) cycles 32 ms
0 0 1 0 8K (8192) cycles 64 ms
0 0 1 1 16K (16384) cycles 0.125 s
0 1 0 0 32K (3276 cycles 0.25 s
0 1 0 1 64K (65536) cycles 0.5 s
0 1 1 0 128K (131072) cycles 1.0 s
0 1 1 1 256K (262144) cycles 2.0 s
1 0 0 0 512K (52428 cycles 4.0 s
1 0 0 1 1024K (1048576) cycles 8.0 s
*/
WDTCR = 0x40; //изменяем таймаут. вочдог включен на 512К циклов (4с);00101000 WDE=1(бит включения) WDP3=1 WDP2,WDP1,WDP0=0 => 512K (52428 cycles 4.0 s

}

ISR(WDT_vect)
{
GIMSK=0x00;//внешнее прерывание по входу INT1/INT0 не разрешено
if (P==0) //если кнопка не была нажата
{
DDRB = 0x1B; //0011011 PB1(кнопка) настроен как выход, дальше станет землей для делителя
PORTB &= ~_BV(PB1); /*сбросить бит PB1, на выходе "0"
это сделано для периодического соединения делителя на землю и замера напряжения аккума, когда кнопку не трогают */

ADCSRA = 0x8F; /* замеряем напряжение на аккуме
10001111 включение ADC, включение прерывания ADIE, делитель частоты обработки установлен 128
Bit 7 – ADEN: ADC Enable
Writing this bit to one enables the ADC. By writing it to zero, the ADC is turned off. Turning
the ADC off while a conversion is in progress, will terminate this conversion.
Bit 6 – ADSC: ADC Start Conversion
In Single Conversion mode, write this bit to one to start each conversion. In Free Running
mode, write this bit to one to start the first conversion.
When the conversion is complete, it returns to zero. Writing zero to this bit has no effect.
Bit 5 – ADATE: ADC Auto Trigger Enable
When this bit is written to one, Auto Triggering of the ADC is enabled. The ADC will start
a conversion on a positive edge of the selected trigger signal. The trigger source is
selected by setting the ADC Trigger Select bits, ADTS in ADCSRB.
Bit 4 – ADIF: ADC Interrupt Flag
This bit is set when an ADC conversion completes and the data registers are updated.
Bit 3 – ADIE: ADC Interrupt Enable
When this bit is written to one and the I-bit in SREG is set, the ADC Conversion Complete
Interrupt is activated.
Bits 2:0 – ADPS2:0: ADC Prescaler Select Bits
These bits determine the division factor between the system clock frequency and the
input clock to the ADC.
ADPS2 ADPS1 ADPS0 Division Factor
0 0 0 2
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128 = наш вариант
*/
WDTCR |= (1<<WDCE) | (1<<WDE);//записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00;//выключение вочдог
ADCSRA |= (1<<ADSC); //запуск единичного ADC преобразования
}
else //кнопку нажимали, значение Р после обработки прерывания INT0 изменилось и не равно 0
{
if ((bit_is_set(PINB,PB1))) /*кнопка не нажата
проверили "1" на PB1
PB1 настроен как вход с подтягивающим резистором
на входе "1" если кнопка УЖЕ не нажата */
{ //Здесь получаем КОРОТКОЕ нажатие кнопки
if ((P==1) || (P==4)) /*лог ИЛИ;
Р=1 если была нажата кнопка первый раз <.>(короткое нажатие) ничего не делаем???

*/
{
if (P==4) Cod=1;
NB=0;
P=0;
}
else
{
if (P==3) //было нажатие, кнопку отпустили???
{ //короткое нажатие кнопки
B|=(1<<NB); //В число "В" в регистр № (NB) записывается единица
NB++; // увеличиваем на 1
}
P=4;
}
WDTCR |= (1<<WDCE) | (1<<WDE);// записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x46; // изменяет таймаут. зарезервированное????? ?????????????????????????
MCUCR=0x00;//The low level of INT0 generates an interrupt request т.е. удерживаемая? кнопка вызывает прерывание
}
else //кнопка еще нажата здесь получаем ДЛИННОЕ нажатие кнопки
{
if (P==5)
{
WDTCR |= (1<<WDCE) | (1<<WDE);//записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00; //выключаем вочдог
}
else
{
if (P==2)
{ //это длинное нажатие кнопки
P=5;
B|=((1<<NB)<<4);//В число "В" в регистр № (NB+4) записывается единица
NB++; // увеличение на единицу
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00; //выключаем вочдог
}
else //кнопка была нажата Р=1 и осталась нажатой = получили одно длинное нажатие и Р=2
{
P=2;//определили длинное нажатие кнопки <__>
WDTCR |= (1<<WDCE) | (1<<WDE);// записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x44; //изменяем таймаут. 101100 wde=1 3бит включения, WDP3,WDP2=1; WDP1,WDP0=0 - зарезервировано???????????????
}
}

MCUCR=0x03;// The rising edge of INT0 generates an interrupt request т.е. при отпускании нажатой кнопки прерывание
}
GIMSK=0x40;//101000 внешнее прерывание по INT0 не разрешено??
}
}

ISR (ADC_vect) //обработка прерывания измерения напряжения
{
adch_val = ADCH; //присваиваем измеренное значение напряжения переменной
ADCSRA = 0; //выключаем ADC
DDRB = 0x19; //10011 настраиваем на выход PB4,PB1,PB0
PORTB |= _BV(PB1); //установить бит PB1//т.о. делитель отсоединяем от земли и он не потребляет ток
if (adch_val<146) //146 - минимальное напряжение на аккуме
{
Cod=1; //перейдем в изменение режима по выходу из прерывания
B=0b00000011; //изменяем режим на 1 вниз
if (adch_val<130) //сравниваем полученное значение с минимально возможным 130
{
nV++; //увеличиваем на 1
if (nV>3) B=0b00010000; //выключаем фонарь после трехкратно измеренного низкого значения
}
else nV=0; //напряжение еще не минимально допустимое, а выше. сбрасываем в ноль nV
}
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x61; //изменяем таймаут вочдога //вочдог был выключен при измерении напряжения
GIMSK=0x40; //??? почему 40?
}
MSS вне форума   Ответить с цитированием Вверх
Поблагодарили: 1 раз
galex (07.02.2014)
Старый 06.02.2014, 19:40 Автор темы   56
ceramic
Ветеран Фонарёвки
 
Аватар для ceramic
 
Регистрация: 08.10.2011
Последняя активность: 26.03.2024 21:08
Адрес: 哈尔滨
Сообщений: 8022
Сказал(а) спасибо: 934
Поблагодарили: 5193 раз(а) в 2784 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Цитата:
Посмотреть сообщение Сообщение от MSS :
WDTCR = 0x46 - почему 46?
Ватчдог взводится на 1 секунду.
Цитата:
Посмотреть сообщение Сообщение от MSS :
в даташит это зарезервированное значение.
Где такое в даташите???

Цитата:
Посмотреть сообщение Сообщение от MSS :
GIMSK=0x40; //??? почему 40?
разрешение прерывания по 6-й ноге (INT0).

Цитата:
Посмотреть сообщение Сообщение от MSS :
GIMSK=0x40;//101000 внешнее прерывание по INT0 не разрешено??
GIMSK=0x40 = GIMSK=0b1000000
внешнее прерывание по INT0 разрешено.

[Исправлено: ceramic, 06.02.2014 в 19:53]
ceramic вне форума   Ответить с цитированием Вверх
Старый 06.02.2014, 20:47   57
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

WDTCR – Watchdog Timer Control Register стр 41 даташит
0x46=00101110
Bit 7 - WDTIF
Bit 6 - WDTIE
Bit 5 - WDP3 =1
Bit 4 - WDCE =0
Bit 3 - WDE = 1
Bit 2:0 - WDP[2:0] = 110
таблица 8.2
1 сек = 0110 - но у нас wdp3=1??? и wdp3=1, wdp2=1, wdp1=1, wdp0=0 в таблице - резерв
Я так понимаю - устанавливаем третий бит и по таблице для 1 сек второй и первый т.е. 0b1110 или 0x14??

[Исправлено: MSS, 06.02.2014 в 21:07]
MSS вне форума   Ответить с цитированием Вверх
Старый 06.02.2014, 22:00 Автор темы   58
ceramic
Ветеран Фонарёвки
 
Аватар для ceramic
 
Регистрация: 08.10.2011
Последняя активность: 26.03.2024 21:08
Адрес: 哈尔滨
Сообщений: 8022
Сказал(а) спасибо: 934
Поблагодарили: 5193 раз(а) в 2784 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Цитата:
Посмотреть сообщение Сообщение от MSS :
0x46=00101110
0x46=0b1000110
ceramic вне форума   Ответить с цитированием Вверх
Поблагодарили: 1 раз
MSS (06.02.2014)
Старый 06.02.2014, 23:01   59
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

вот блин, x - получается HEX ... теперь все понятно с прошивкой. нуб я еще

теперь попробую тут рампинг прилепить...

[Исправлено: MSS, 06.02.2014 в 23:38]
MSS вне форума   Ответить с цитированием Вверх
Старый 07.02.2014, 14:56   60
MSS
Ветеран Фонарёвки
 
Аватар для MSS
 
Регистрация: 28.04.2013
Последняя активность: 08.01.2024 23:25
Адрес: Харьков
Сообщений: 3980
Сказал(а) спасибо: 529
Поблагодарили: 921 раз(а) в 628 сообщениях

По умолчанию Re: Модифицируем народный линейный драйвер для тактовой кнопки

Исправил свои ошибки с переводом в двоичную систему. Окончательный вариант

/*
* LED Driver Tactical Button
*
* Created: 09.04.2013 3:36:20
*
* FIRMWARE VERSION: 1.0
*
* This code is distributed under the GNU Public License
* which can be found at http://www.gnu.org/licenses...
*
* Author: Ceramic https://forum.fonarevka.ru/...
*/
#include<avr/io.h>
#include<avr/delay.h>
#include<avr/interrupt.h>

unsigned char P = 0;
volatile unsigned char B = 0;
unsigned char NB = 0;
volatile unsigned char Cod = 1;
unsigned char adch_val;
unsigned char nV=0;
unsigned char Power=0;
unsigned char Nmode=3;
unsigned char NGroupe=0;
unsigned char Mode[5][3]={{6,6,6},{29,33,36},{73,117,146},{0b00001,0b01000,0b01001},{0b10000,0b10001,0b11001}};
unsigned char volt [4] = {146, 156, 165, 174}; //порог напряжений (для смены режимов на меньший или индикации заряда аккум)

static inline void delay_()
{
_delay_ms(800); //задержка 800мс
}

static inline void blink() //моргает диод
{
TCCR0A = 0x00; //ШИМ выключен
PORTB &=~ 0b11001; // ~ знак поразрядного инвертирования PB4 PB3 PB0 по идее выключит все выходы
delay_(); //задержка (800мс)
PORTB |= 0b00001; //включаем выход PB0 (пятая нога, 1 чип)
delay_(); //задержка 800мс
PORTB &=~ 0b00001; //выключаем PB0
}

static inline void Off() // выключаем все и спим
{
Power = 0;
OCR0A = 0x00; //ШИМа нет 0 на выходе
TCCR0B = 0x00; //счетчик выключен
TCCR0A = 0x00; ///ШИМ выключен
PORTB = 0x02; ///0b00000010 выходы выключены PB4 PB3 PB0; PB1 Pull-up - лог "1" пока не нажата кнопка
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00; //отключение вочдог
MCUCR=0x30; //b110000 бит5(SE)=1 спящий режим разрешен.бит4=1 режим сна - power down останавливается практически всё, кроме обработки внешних прерываний, сторжевого таймера
GIMSK=0x40; //b1000000 Bit 6 – INT0: External Interrupt Request 0 Enable
BODCR = 0x03; /*11 Brown-Out Detector Control Register Writing this bit to one turns off BOD in
Power-Down and Stand-By, while writing a zero keeps the BOD active.
First, both BODS and BODSE must be set to one. Second, within four clock cycles,
BODS must be set to one and BODSE must be set to zero*/
BODCR = 0x02; //10
sei();
/*При вызове обработчика любого прерывания бит глобального разрешения прерываний I регистра SREG
status register - регистр состояния сбрасывается в "0"и только по завершении обработки прерывания
снова устанавливается в "1" и разрешает начать обработку следующего прерывания в очереди.
Чтобы установить ручками этот бит существует функция sei(), а чтобы сбросить - cli().
При запуске программы этот бит всегда сброшен и чтобы прерывания срабатывали его нужно установить (вызвать sei()).
*/
asm("sleep"); //переводит МК спать с заданным режимом (powerDown)
MCUCR &=~(1<<SE); //обнуляем бит SE - спящий режим не разрешен
TCCR0B = 0x1; /*
В качестве тактового сигнала выбирается один из выходов
со специального встроенного делителя тактовой частоты.
Для выбора одного из этих сигналов служит специальный регистр TCCR0B
TCCR0B=0x00 таймер остановлен. Можно использовать это значение как выключалку таймера-счетчика
TCCR0B=0x01 деление на единицу
TCCR0B=0x02 деление на 8
TCCR0B=0x03 деление на 64
TCCR0B=0x04 деление на 256
TCCR0B=0x05 деление на 1024 */
}

static inline void SwitchMode()
{
unsigned char n;
if (B == 0b00000111) //тройное короткое нажатие < . . . >
{
for (n = 0; n<5; n++) //Индикация напряжения на батарее
// Полностью заряжено – 5 миганий, разряжено – одно мигание
{
blink();
if (adch_val<volt[n]) break; // сравниваем с порогом напряжений volt [4] = {146, 156, 165, 174}
}
delay_();
delay_();
goto m2;
}
else if ((B == 0b00000001) & (Power == 1)) //короткое нажатие < . >
{
if (Nmode<3) Nmode++; // Переключение вверх только в трех средних режимах яркости текущей группы
}
else if ((B == 0b00000011) & (Power == 1)) // двойное короткое < . . >
{
if (Nmode>1) Nmode--; //Переключение вниз только в трех средних режимах яркости текущей группы
}
else if (B == 0b00010010) //Переключение между группами 1-я: < _ . >
{
NGroupe=0;
blink();
}
else if (B == 0b00010110) //Переключение между группами 2-я: < _ . . >
{
NGroupe=1;
blink();
}
else if (B == 0b00011110) //Переключение между группами 3-я: < _ . . . >
{
NGroupe=2;
blink();
}

/*********************************************************************
ниже 5 команд на непосредственное включение сразу
в любом из пяти режимов текущей группы
(1: < _ _ _ >, 2: < . _ >, 3: < . . _ >, 4: < . . . _ >, 5 : < _ _ >)
**********************************************************************/

else if (B == 0b01110000) Nmode=0; //< _ _ _ > между длинным и коротким = четыре 0000
else if (B == 0b00100001) Nmode=1; //< . _ > длинные 0b001 слева , короткие справа 00001
else if (B == 0b01000011) Nmode=2; //< . . _ >
else if (B == 0b10000111) Nmode=3; //< . . . _ >
else if (B == 0b00110000) Nmode=4; //< _ _ > самый яркий

/*
Пример - назначить на двойное долгое нажатие < _ _ > младший режим;
else if (B == 0b00110000) Nmode=4; => поменять на Nmode=0
Длинное нажатие -- дольше 0,25с, пауза больше 0,5с -- окончание ввода
Пример - удаление
else if (B == 0b00110000) Nmode=4;
ограничивает максимальный ток до 1050мА (драйвер на 2800мА), уменьшая кол-во режимов (пропадает старший)
*/
/*
Группа режимов выбирается из Mode[5][3]
Для ШИМ первые три:{6,6,6},{29,33,36},{73,117,146} цифры - коэффициент заполнения, больше=ярче
Без ШИМ
четвертый режим:
0b00001 = 350мА = 1 чип на пятой ноге, включаем выход PB0
0b01000 = 700мА = 2 чипа на второй ноге, включаем выход PB3
0b01001 = 1050мА = 1чип+2чипа, 5 и 2 нога, включаем выход PB0 и PB3
пятый режим:
0b10000 = 1750мА = 5 чипов на третьей ноге, включаем выход PB4
0b10001 = 2100мА = 1+5 чипов на пятой и третьей ноге, включаем выход PB0 и PB4
0b11001 = 2800мА = все 8 чипов, включены выход PB0, PB4, PB3

Расположение выходов МК
PB0 = 5 нога
PB1 = 6 нога (INT0)
PB2 = 7 нога
PB3 = 2 нога
PB4 = 3 нога
PB5 = 1 нога

6-й вывод для кнопки, ибо только замыканием этого вывода на землю
можно разбудить драйвер из глубокой спячки - прерывание INT0
*/
else if ((Power == 0) & (B == 0b00010000)); //Включение длинным нажатием < _ >
else
{
if ((Power == 0) || (B == 0b00010000)) Off(); //Выключение длинным нажатием < _ >
goto m2;
}
Power = 1;


m2: Cod=0;
n=Mode[Nmode][NGroupe];
if (Power==1)
{
TCCR0A = 0x00; //выключаем ШИМ
PORTB &=~ 0b11001; //~ знак поразрядного инвертирования выключаем все выходы PB4 PB3 PB0
if (Nmode>2) PORTB |= n; //Nmode>2 включает согласно режиму соответствующие выходы PB0 PB3 PB4 без ШИМ
else
{
TCCR0A = 0x83;
/*задаем режим работы ШИМ 0b100000011 -011 FAST PWM выход ШИМ на PB0
COM0A1=1|COM0A0=0|COM0B1|COM0B0|-|-|WGM01=1|WGM00=1

Микроконтроллер ATtiny13 имеет два независимых канала ШИМ.
Выход канала, который мы используем, называется OC0A (выходит на PB0).
А другой канал называется OC0B (выходит на PB1)

Установив COM0A1 (восьмой бит) = 1 и COM0A0 (седьмой бит) = 0, мы выбираем режим сброса OC0A при совпадении,
и установки OC0A при достижении конца.
Это означает, что в тот момент, когда значение счетного регистра TCNT0 таймера
окажется равным значению регистра OCR0A, выход OC0A (PB0) будет сброшен в "0".
Когда же таймер досчитает до своего максимального значения (TCNT0 = 255),
на выходе OC0A установится логическая "1".
Изменяя значение OC0A, можно менять ширину выходного импульса.
*/
OCR0A = n; //режим яркости в зависимости от группы режимов NGroupe и Mode
/*
на выходе PB0 микроконтроллера (ножка 5) будет присутствовать ШИМ сигнал
с заполнением пропорционально значению регистра OCR0A
OCR0A=0; — ШИМа небудет, ноль на выходе
OCR0A=127; — на выходе ровный меандр с заполнением 50/50
OCR0A=255; — на выходе единица, ШИМа нет
*/
}
}
else Off();
}

void main(void) __attribute__((__noreturn__));
void main(void)
/*
Очень хороший приемчик - сделать функцию main ничего не возвращающей.
Позволяет съэкономить на ненужных push и pop целых 36 байт!
По умолчанию функция main обычно определена как int main (void)
*/

{
DDRB = 0b11001; //порт PB4, PB3, PB0 настроен как выход; PB1,PB5??? вход
CLKPR = 0x80; //команды настройки регистра внутреннего делителя частоты
CLKPR = 0x01; /*01-делитель=1 CLKPR = 0x80 = для этого регистра для изменения делителя необходимо записать единичку в седьмой бит,
после чего микроконтроллер даст изменить и выбрать необходимый делитель в первых четырех битах этого регистра.
После того, как пройдет четыре такта выполнения команд процессора, изменить регистр будет уже нельзя.
Нужно снова сначала изменить седьмой бит CLKPR=0x80 а затем указать делитель CLKPR=нужный делитель
*/
ACSR = 0x80; /*10000000 Analog Comparator Control and Status Register – ACSR
установка единицы в Bit 7 – ACD: Analog Comparator Disable (0х80) отключает аналоговый компаратор,
его можно выключить в любой момент, это приводит к снижению потребления электричества
*/
ADMUX = 0x61; /*01100001 ADC Multiplexer Selection Register
внешний источник напряжения, вход PB2
Bit 6 – REFS0: Reference Selection Bit
0 VCC used as analog reference.
1 Internal Voltage Reference.
Bit 5 – ADLAR: ADC Left Adjust Result
The ADLAR bit affects the presentation of the ADC conversion result in the ADC Data
Register. Write one to ADLAR to left adjust the result.
Bits 1:0 – MUX1:0: Analog Channel Selection Bits
MUX1..0 Single Ended Input
00 ADC0 (PB5)
01 ADC1 (PB2) наш вариант -вход с делителя
10 ADC2 (PB4)
11 ADC3 (PB3)
*/
while(1)
{
if (Cod==1) SwitchMode(); //Основной цикл ?)
}
}

ISR(INT0_vect) //процедура обработки прерывания INT0 (кнопка порт PB1)
{
GIMSK=0x00; /*Если разряд INT1(бит7)/INT0(бит6) установлен в лог. 1,
то внешнее прерывание по входу INT1/INT0 будет разрешено до тех пор,
пока установлен в лог. 1 разряд I в регистре состояния SREG. */
if (P==0)
{
P=1;
B=0;
}
else if (P==2) P=3; //Р=2 при длинном нажатии (нажали и удержали) ???
else if (P==4) P=6;
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
/*бит разрешения изменений WDCE и бит включения WDE
для включения достаточно установить бит WDE в единичное состояние,
одновременно, если надо, устанавливается и период таймера битами WDP2. .0 того же регистра,
задающими коэффициент деления генератора
(состояние 000 соответствует минимальному периоду ~15 мс, 110 — примерно 1 с, 111 задает максимальный период немного менее 2 с).
Bit 7 - WDTIF: Watchdog Timer Interrupt Flag
Bit 6 - WDTIE: Watchdog Timer Interrupt Enable
Bit 4 - WDCE: Watchdog Change Enable
This bit is used in timed sequences for changing WDE and prescaler bits. To clear the
WDE bit, and/or change the prescaler bits, WDCE must be set.
Once written to one, hardware will clear WDCE after four clock cycles.
Bit 3 - WDE: Watchdog System Reset Enable
WDE is overridden by WDRF in MCUSR. This means that WDE is always set when
WDRF is set. To clear WDE, WDRF must be cleared first. This feature ensures multiple
resets during conditions causing failure, and a safe start-up after the failure.
Bit 5, 2..0 - WDP3..0: Watchdog Timer Prescaler 3, 2, 1 and 0
WDP3 WDP2 WDP1 WDP0 Number of WDT Oscillator Cycles
0 0 0 0 2K (204 cycles 16 ms
0 0 0 1 4K (4096) cycles 32 ms
0 0 1 0 8K (8192) cycles 64 ms
0 0 1 1 16K (16384) cycles 0.125 s
0 1 0 0 32K (3276 cycles 0.25 s
0 1 0 1 64K (65536) cycles 0.5 s
0 1 1 0 128K (131072) cycles 1.0 s
0 1 1 1 256K (262144) cycles 2.0 s
1 0 0 0 512K (52428 cycles 4.0 s
1 0 0 1 1024K (1048576) cycles 8.0 s
*/
WDTCR = 0x40; //b01000000 Watchdog Timer Interrupt Enable установка таймера вочдог в 16мс.
}

ISR(WDT_vect)
{
GIMSK=0x00;//внешнее прерывание по входу INT1/INT0 не разрешено
if (P==0) //если кнопка не была нажата
{
DDRB = 0x1B; //0011011 PB1(кнопка) настроен как выход, дальше станет землей для делителя
PORTB &= ~_BV(PB1); /*сбросить бит PB1, на выходе "0"
это сделано для периодического соединения делителя на землю и замера напряжения аккума, когда кнопку не трогают */

ADCSRA = 0x8F; /* замеряем напряжение на аккуме
10001111 включение ADC, включение прерывания ADIE, делитель частоты обработки установлен 128
Bit 7 – ADEN: ADC Enable
Writing this bit to one enables the ADC. By writing it to zero, the ADC is turned off. Turning
the ADC off while a conversion is in progress, will terminate this conversion.
Bit 6 – ADSC: ADC Start Conversion
In Single Conversion mode, write this bit to one to start each conversion. In Free Running
mode, write this bit to one to start the first conversion.
When the conversion is complete, it returns to zero. Writing zero to this bit has no effect.
Bit 5 – ADATE: ADC Auto Trigger Enable
When this bit is written to one, Auto Triggering of the ADC is enabled. The ADC will start
a conversion on a positive edge of the selected trigger signal. The trigger source is
selected by setting the ADC Trigger Select bits, ADTS in ADCSRB.
Bit 4 – ADIF: ADC Interrupt Flag
This bit is set when an ADC conversion completes and the data registers are updated.
Bit 3 – ADIE: ADC Interrupt Enable
When this bit is written to one and the I-bit in SREG is set, the ADC Conversion Complete
Interrupt is activated.
Bits 2:0 – ADPS2:0: ADC Prescaler Select Bits
These bits determine the division factor between the system clock frequency and the
input clock to the ADC.
ADPS2 ADPS1 ADPS0 Division Factor
0 0 0 2
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128 = наш вариант
*/
WDTCR |= (1<<WDCE) | (1<<WDE);//записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00;//выключение вочдог
ADCSRA |= (1<<ADSC); //запуск единичного ADC преобразования
}
else //кнопку нажимали, значение Р после обработки прерывания INT0 изменилось и не равно 0
{
if ((bit_is_set(PINB,PB1))) /*кнопка не нажата
проверили "1" на PB1
PB1 настроен как вход с подтягивающим резистором
на входе "1" если кнопка УЖЕ не нажата */
{ //Здесь получаем КОРОТКОЕ нажатие кнопки
if ((P==1) || (P==4)) /*лог ИЛИ;
Р=1 если была нажата кнопка первый раз <.>(короткое нажатие) ничего не делаем???

*/
{
if (P==4) Cod=1;
NB=0;
P=0;
}
else
{
if (P==3) //было нажатие, кнопку отпустили???
{ //короткое нажатие кнопки
B|=(1<<NB); //В число "В" в регистр № (NB) записывается единица
NB++; // увеличиваем на 1
}
P=4;
}
WDTCR |= (1<<WDCE) | (1<<WDE);// записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x46; //0b01000110 изменяет таймаут = 128K (131072) cycles 1.0 s
MCUCR=0x00;//The low level of INT0 generates an interrupt request т.е. удерживаемая? кнопка вызывает прерывание
}
else //кнопка еще нажата здесь получаем ДЛИННОЕ нажатие кнопки
{
if (P==5)
{
WDTCR |= (1<<WDCE) | (1<<WDE);//записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00; //выключаем вочдог
}
else
{
if (P==2)
{ //это длинное нажатие кнопки
P=5;
B|=((1<<NB)<<4);//В число "В" в регистр № (NB+4) записывается единица
NB++; // увеличение на единицу
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x00; //выключаем вочдог
}
else //кнопка была нажата Р=1 и осталась нажатой = получили одно длинное нажатие и Р=2
{
P=2;//определили длинное нажатие кнопки <__>
WDTCR |= (1<<WDCE) | (1<<WDE);// записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x44; //0b01000100 изменяем таймаут. 32K (3276 cycles 0.25 s
}
}

MCUCR=0x03;// The rising edge of INT0 generates an interrupt request т.е. при отпускании нажатой кнопки прерывание
}
GIMSK=0x40;//0b01000000 внешнее прерывание по INT0 разрешено
}
}

ISR (ADC_vect) //обработка прерывания измерения напряжения
{
adch_val = ADCH; //присваиваем измеренное значение напряжения переменной
ADCSRA = 0; //выключаем ADC
DDRB = 0x19; //11001 настраиваем на выход PB4,PB3,PB0
PORTB |= _BV(PB1); //установить бит PB1//т.о. делитель отсоединяем от земли и он не потребляет ток
if (adch_val<146) //146 - минимальное напряжение на аккуме
{
Cod=1; //перейдем в изменение режима по выходу из прерывания
B=0b00000011; //изменяем режим на 1 вниз
if (adch_val<130) //сравниваем полученное значение с минимально возможным 130
{
nV++; //увеличиваем на 1
if (nV>3) B=0b00010000; //выключаем фонарь после трехкратно измеренного низкого значения
}
else nV=0; //напряжение еще не минимально допустимое, а выше. сбрасываем в ноль nV
}
WDTCR |= (1<<WDCE) | (1<<WDE); //записываем 1 в биты WDCE и WDE для разрешения изменений в течении 4 циклов
WDTCR = 0x61; //0b01100001 изменяем таймаут вочдога 1024K (1048576) cycles 8.0 s //вочдог был выключен при измерении напряжения
GIMSK=0x40; //0b01000000 внешнее прерывание по INT0 разрешено
}
MSS вне форума   Ответить с цитированием Вверх
Поблагодарили: 4 раз(а)
AVTOELEKTRIK (17.03.2015), Memorized (13.07.2015), Techno (10.06.2017), Volosaty (21.01.2015)
Ответ  Создать новую тему
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск





Copyright ©2007 - 2024, FONAREVKA.RU

Powered by vBulletin®
Copyright ©2000 - 2022, Jelsoft Enterprises Ltd. Перевод: zCarot

Правила форума | Отказ от ответственности

Время генерации страницы 0.27285 секунды с 17 запросами