Перейти к содержанию

С нуля Программирование AVR Купил программатор и Контроллер Что дальше...


Рекомендуемые сообщения

11 час назад, Alexeyslav сказал:

специализированную микросхему 8-канального 12-битного ШИМ работающего по I2C шине?

Не могли бы озвучить название такой микросхемы?

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

10 часов назад, Alexeyslav сказал:

Впрочем, почему 10... удобней определять каждые 16 циклов, младшие 4 бита счетчика будут равны нулю. Вот в этот момент прочитать кнопки, если какая-то кнопка нажата - инкрементировать второй счетчик, и каждые 16 таких событий прибавлять/убавлять переменную ШИМ. Опрос кнопок получится каждые 16мс если и попадёшь на дребезг максимум что произойдёт - определишь нажатие через 16 мс от настоящего момента. Второй счетчик даст период в 256мс - это определит время автоповтора, примерно 4-5 тактов за секунду.<...>

Про второй счётчик не очень понятно.

Если первый счётчик равен 0b0001 0000 - проверяем кнопки.

Как автоповтор получается? Ну, какое условие проверять?...

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Я вам в теме ссылку давал. Цикл статей Татарчевского. В этом цикле подробно расписывается как сделать программные таймеры. И как сделать опрос кнопок. Удержание, автоповтор. Все разжевано и расписано.

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Микросхема tlc5940. соврал, там 16-канальный 12-битный ШИМ, с SPI.

Цитата

Если первый счётчик равен 0b0001 0000 - проверяем кнопки.

Не так, если счётчик равен 0bxxxx 0000 то проверяем кнопки. x - это любое значение бита.

Второй счетчик он индивидуален КАЖДОЙ КНОПКЕ, и считает только когда кнопка нажата, и обнуляется когда кнопка отпущена, проверка кнопок как и реализация этой логики происходит в условии по первому счетчику т.е. один раз в 16 итераций. Тут же, проверяем значение каждого индивидуального счетчика на равенство 0bxxxx x000 и если равно - выполняем действие закреплённое за этой кнопкой. итого, повтор действия будет происходить каждые 8 таких итераций, но поскольку каждая итерация это 16 циклов ШИМ, то происходить это будет каждые 8*16 = 128 циклов, а при длительности цикла примерно 1мс это будет интервал в 128мс. Можно увеличить до 16, и это уже будет 256мс. Можно взять любое другое число, но сложнее будет управлять счетчиком - его надо будет сравнивать с константой и обнулять при превышении. А тут простая логика AND 0x00001111 и дешёвое сравнение на равенство нулю.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Alexeyslav сказал:

<...> тут простая логика AND 0x00001111 и дешёвое сравнение на равенство нулю.

Если n - общий счётчик, то так?

if(n == (n &= ~((1<<1)|(1<<2)|(1<<3)|(1<<4))))

Не уверен, что у меня в голове правильные сдвиги...)

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

Присвоение внутри оператора сравнения? Пока не рекомендую.

У меня есть некоторый опыт работы с логическими операциями, но гарантировать результат этого шаманства и его воспроизводимость на разных компиляторах я не берусь.

3 часа назад, Alexeyslav сказал:

если счётчик равен 0bxxxx 0000 то проверяем кнопки

@pliss, заводите временную переменную, копируете в нее счетчик, логическими операциями зануляете старшие биты, потом пишете проверку того что получилось на равенство нулю. Если сработает - оптимизируете до одной строчки (хотя компилятор все равно развернет обратно в то что я описал).

mov r16, n ;//r16 - временный регистр, n - счетчик. На самом деле компилятор может использовать другие, это не важно
andi r16, 0b00001111
brne DONT_TEST_BTNS ;//если не младшие биты не равны нулю, пропускаем тест
  rcall TEST_BTNS ;//если же равны - запускаем подпрограмму проверки
DONT_TEST_BTNS:

Что-то мне подсказывает что с ассемблером вы знакомы слабо так что процессу творческого поиска не помешаю.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

11 минуту назад, COKPOWEHEU сказал:

Присвоение внутри оператора сравнения? Пока не рекомендую.

@plissУ меня есть некоторый опыт работы с логическими операциями, но гарантировать результат этого шаманства и его воспроизводимость на разных компиляторах я не берусь.<...>

Мне воспроизводимость не сильно нужна. На разных компиляторах.

А в чём проблема с результатом на одном компиляторе?

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, COKPOWEHEU сказал:

так что процессу творческого поиска не помешаю.

Абсолютно. Поиска нет. Тарищ желает, чтобы ему разжевывали и в рот клали.

Ссылка на комментарий
Поделиться на другие сайты

Не понимаю, а почему не катит простая логическая операция if (n&0x0F) == 0 {} или С так принципиально не умеет? или сразу хак if !(n&0x0F) {} представляя результат логической функции как булеву переменную, для которой false = 0, true = <любое другое число>.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Есть такая категория, этакий еврей из программизма. Самому лень извилины напрячь, пусть другие напрягаются.

Я понял бы, если товарищ спрашивает о более глобальных вещах, чем ковыряние в битах. Типа, пацаны, народ, хочу забубенить что-нить этакое (называется). Вот я представляю как то-то сделать, то-то. А вот то-то мозги уже набекрень. И народ подтягивается, подкидывет идеи. Потому что видно, что товарищ действительно пытается. ТС-у остается только выбирать. А здесь... Если ему даже лень в книжку по программированию на си заглянуть. Аб чем тут речь, спрашивается? Как битики гонять?

Изменено пользователем demiurg1978
Ссылка на комментарий
Поделиться на другие сайты

Ровно второй пост этой темы - отсылка к двум книгам. На второй странице - дал ссылку на третий и четвёртый учебники. Судя по вопросам - чукча не читатель...

Изменено пользователем oldmao
Ссылка на комментарий
Поделиться на другие сайты

9 часов назад, Alexeyslav сказал:

<...>почему не катит простая логическая операция if (n&0x0F) == 0 {} или С так принципиально не умеет? или сразу хак if !(n&0x0F) {} представляя результат логической функции как булеву переменную, для которой false = 0, true = <любое другое число>.

Спасибо.)

Вот так катит:

if(n==(n&~((1<<0)|(1<<1)|(1<<2)|(1<<3))))   //если общий счётчик == "0bxxxx 0000"
{
<....>;
}

Прикольно.

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

Почему не воспользовались советами? Ваша запись сложнее, ее сложнее модифицировать и разбираться как она должна работать.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

В 09.03.2017 в 07:19, COKPOWEHEU сказал:

Почему не воспользовались советами? Ваша запись сложнее, ее сложнее модифицировать и разбираться как она должна работать.

Почему же не воспользовался?!

Воспользовался. Вас же ваш совет интересует, так?

По вашему совету я завёл временную переменную и сразу увидел ошибку в выражении.

Это было именно

В 08.03.2017 в 13:39, COKPOWEHEU сказал:

Присвоение внутри оператора сравнения<...>

В смысле, ошибка была не в "присвоении внутри оператора", а именно - само "присвоение".

Не надо в этом выражении присвоения.

Вот такая запись получилась:

if(n==(n&   ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)))),

а была вот такая:

if(n==(n&  =  ~((1<<0)|(1<<1)|(1<<2)|(1<<3)))).

 

Вашем же советом с кодом на asm я, как вам "что-то" подсказало совершенно верно, действительно, воспользоваться не могу.

В 08.03.2017 в 18:47, oldmao сказал:

<...>Судя по вопросам - чукча не читатель...

Ну почему же.)

Вот, например, из журнальной публикации С.М.Рюмика. Своими словами.

Что Билл Гейтс со товарищи, что - вашими словами "чукча", решая задачу чукчи - напишут программы конечно разные, но работать они будут совершенно одинаково.

Книг много хороших. Вот, например, Уоррен младший про алгоритмические трюки хорошую написал...

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

Вам советовали проверять на ноль а не на равенство себе. В вашем случае, когда надо отбросить несколько младших битов, лучше их задать одним числом а не несколькими не связанными сдвигами. То есть

#define IGNORE_BITS 4 //если вдруг захочется изменить количество затираемых битов
uint8_t temp = n; //пишу без оптимизации
temp &= (0xFF << IGNORE_BITS); //0xFF годится только для 8-битных переменных. 0xFFFF - для 8- и 16-битных и т.д.
if(temp == 0){...} //проверка на равенство нулю
if( !temp ){...} //учитывая особенность TRUE в Си, тоже самое можно записать и так

После оптимизации такая запись будет короче и понятнее вашей.

А Ассемблер все равно стоит освоить. Даже если не будете на нем писать программы (хотя поначалу стоило бы!) прочувствуете контроллер, поймете какие операции для него предпочтительнее. Ну и ассемблерные вставки, позволяющие ускорить и ужать отдельные участки на порядок. Но даже сейчас можно было найти справочник по командам и разобрать что же этот кусок делает и перевести на тот же Си. Там же всего 4 команды!

Для примера, я недавно начал осваивать stm32. Первым делом написал макросы для удобного управления портами (хоть там этого будет меньше чем в AVR), и для проверки выполняются ли за один такт команды вроде

#define GPO_ON(descr) \
  do{ \
    GPIO(marg1(descr))->BSRR = (1<<marg2(descr)<<((1-marg3(descr))*16)); \
  }while(0)

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

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

С системой команд стоит ознакомиться хотя бы для того, чтобы понимать что накомпилировал компилятор. Бывают случаи, когда программа работает не так как нужно. Приходится заглядывать в дизассемблер, чтобы увидеть в чем причина. В бобине или в водителе.

Ссылка на комментарий
Поделиться на другие сайты

Причем в 90% случаев дело в "водителе". Часто бывает полезно смотреть дизассемблерный код прерываний, посмотреть не слишком ли компилятор много регистров задействовал и в случае чего поменять пару строчек местами. Ну и "битовая магия", когда надо преобразовать данные одного формата в другой, например, PWM в BAM, на асме гораздо эффективнее чем на ЯВУ.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

В 11.03.2017 в 09:58, COKPOWEHEU сказал:

Вам советовали проверять на ноль а не на равенство себе.

Это не совсем так. Посмотрите что вы мне советовали:

В 08.03.2017 в 13:39, COKPOWEHEU сказал:

заводите временную переменную< , - запятая> копируете в нее счетчик< , - запятая> логическими операциями зануляете старшие биты< , - запятая> потом пишете проверку того что получилось на равенство нулю. Если сработает - оптимизируете до одной строчки

До проверки равенства на ноль мне нужно было пройти ТРИ шага.)

Если бы вы вместо запятой написали бы "и" - тогда да, ваши претензии были бы обоснованны.

За первый шаг я отчитался.

Второй, похоже - не обязательный. Посмотрите, если я ничего не напутал -я пробую сразу   "занулить" не интересующие меня биты и логически умножить маску и значение регистра. Потом - логическое отрицание... Наверное...

Если не лень - глянте, может какой принципиальный косяк есть... Здесь для одной кнопки кусок кода.

В протеусе, вариант на два канала с "+" и "-" работает нормально...

Скрытый текст

#define F_CPU 4000000UL
#include  <avr/io.h>

int main()

{	
//DDRA=0xFF;
DDRB=0x00;//кнопки
DDRD=0xFF;//выход
DDRC=0xFF;//контроль

//PORTA=0x00;
PORTB=0xFF;//кнопки с резисторами
PORTD=0x00;//выход высокий
PORTC=0x00;//контроль низкий

volatile int  ton0=0, ton0_=ton0, d0=15;//время PORTD0_on, 
 //дубль PORTD0_on и приращение
volatile int  T=150, T_=T;//период и дубль
volatile unsigned char  n=0, n0=0, r=0;//общий и инд счётчик,
//и разрешение изменения

while(1)

{

//  ************* проверка кнопок ***********************  //
			
//  ************* кнопки канала PORTD0 *******************  //													

              // **** кнопка "+" *** //
										
if((!(PINB&0b00000001))&&(T>=(ton0+d0)))//если нажат "+" и есть 
  //возможность расширения импульса

{	
	n++;//инкр общий счётчик

	if(!(n&=0b00000111))//если у общего счётчика три мл разряда ==0

	{
		n0++;//увеличиваем инд счётчик										     

		if((!(n0&=0b00000111))&&(!(PINB&0b00000001))&&(r==0))//если нажат "+" и 
          //у инд счётчика три мл разряда ==0

		{		
			ton0=ton0+d0;//увеличиваем время PORTD0_on
			ton0_=ton0;//обновляем дубль
			r=1;//запрещаем изменения
		}
	}
}

// ********************** ШИМ *************************  //

PORTD=0xFF;//включаем всё
		
while(T>=0)//период

{						
	if(ton0>=0)ton0--;//считаем время PORTD0_on
	else PORTD&=0b11111110;//выключаем PORTD0_on}
			
	T--;//считаем период				
}
		
T=T_;//восстанавливаем период
	
ton0=ton0_;//обновляем или восстанавливаем время PORTD0_on
		
if(PINB==0b11111111)r=0;//если кнопки отпущены разрешаем изменение

}
}

 

 

Изменено пользователем pliss

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

1) лучше в начале бесконечного цикла while(1) один раз считать значение разрядов порта PINB и далее работать с переменной. Иначе как говориться "за время пути собачка могла подрасти" - измениться состояние на порту PINB, а вы этого и не ждали:

unsigned char state_pin_b;
while(1)
{
  state_pin_b = PINB;
  ...
  if(state_pin_b & 0b00000001)
  ...
}

2) данная конструкция скорее всего не правильная
if(!(n &= 0b00000111))
наверно хотели так if(!(n & 0b00000111)) , ну и с n0 аналогично

3) (r==0) можно заменить на (!r)

4) вот этот кусок мне кажется категорически не правильный, внутри основного бесконечного цикла вы вводите ещё цикл для формирования сигнала ШИМ. Это должно делаться не в своём цикле while(T>=0), а в основном бесконечном цикле

while(T>=0)//период

{						
	if(ton0>=0)ton0--;//считаем время PORTD0_on
	else PORTD&=0b11111110;//выключаем PORTD0_on}
			
	T--;//считаем период				
}

 

Изменено пользователем dm37
Ссылка на комментарий
Поделиться на другие сайты

5 минут назад, dm37 сказал:

1) лучше в начале бесконечного цикла while(1) один раз считать значение разрядов порта PINB и далее работать с переменной. Иначе как говориться "за время пути собачка могла подрасти" - измениться состояние на порту PINB, а вы этого и не ждали:

В общем случае, на верное, вы правы.

Но у меня частный случай - я об этом писал.

У меня основной процесс - это само вращение моторчиков с заданной скоростью, а не управление этим вращением кнопками, состояние которых надо строго отслеживать. Более того, "подрастание собачки за время пути" - явление с одной стороны неприемлемое, с другой стороны - в принципе невозможное.

Я включаю устройство. Если меня устраивает скорость вращения установленная ранее и записанная в память - я не трогаю кнопки и пользуюсь тем вращением, которое есть.

Если нужно - подхожу к устройству, устанавливаю новую скорость вращения (которая должна запомниться в памяти) и пользуюсь ей. Возможно - мне вообще не каждый раз нужно будет изменять скорость в период между включением и выключением устройства.

По этому - постоянный опрос кнопок мне кажется лишним...

25 минут назад, dm37 сказал:

2) данная конструкция скорее всего не правильная
if(!(n &= 0b00000111))
наверно хотели так if(!(n & 0b00000111)) , ну и с n0 аналогично

3) (r==0) можно заменить на (!r)

Это да, но скорее - избыточная. Мозг кипит, я именно без присваивания хотел записать... Пол-дня осознавал что для "if()" важно - ноль или не ноль, а рука всё равно дрогнула.))

Исправил - протеус перестал подвисать при изменении ширины импульса. Круть!

Спасибо.)

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, pliss сказал:

Это не совсем так. Посмотрите что вы мне советовали:

Описание последовательности действий. Неужели это можно было принять за список вариантов?

2 часа назад, pliss сказал:

volatile int ton0=0, ton0_=ton0, d0=15;//время PORTD0_on,

объявлять как volatile локальные переменные бессмысленно, разве что хотите передать указатель на нее в прерывание. Но это то еще извращение.

 

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

57 минут назад, pliss сказал:

Но у меня частный случай - я об этом писал.

у вас вполне обычная задача, изменять длительность импульса ШИМ с помощью кнопок
Для того чтобы узнать, нажата кнопка или нет вам надо их постоянно опрашивать, хотите вы этого или нет.
У вас по условию 4 ШИМ и каждый управляется своими кнопками, по вашей структуре программы это не реализовать (я имею ввиду цикл while(T>=0)).
Пока оставьте кнопки в покое и сделайте 4 ШИМ. Введите 1 переменную, которая будет отвечать за период ШИМ и 4 переменные, которые будут отвечать за длительность импульса 4 ШИМ.
И далее в основном цикле (раз уж вы так не хотите использовать прерывания таймера):
увеличивайте период на 1, когда период будет равен заданному значению сбрасывйте в 0. После сравнивайте значение периода с заданными значениями ШИМ (PWM1,...) и выключайте канал ШИМ

#define PWM_Period 200
...
T = PWM_Period;
...

while(1)
{
  // обработка кнопок (меняем значения PWM1,...)
  ...
  if(T >= PWM_Period)
  {
   // включаем все ШИМ
  ...
    T = 0;
  }
  else
  {
    if(PWM1 >= T)
     // выключаем данный ШИМ
    if(PWM2 >= T)
     // выключаем данный ШИМ
    if(PWM3 >= T)
     // выключаем данный ШИМ
    if(PWM4 >= T)
     // выключаем данный ШИМ
    ...
    T++;
   }
}

могут быть неточности, но принцип думаю понятен
в данном примере канал ШИМ не отключается, не знаю надо это вам или нет

Изменено пользователем dm37
Ссылка на комментарий
Поделиться на другие сайты

 

15 минут назад, COKPOWEHEU сказал:

Описание последовательности действий. Неужели это можно было принять за список вариантов?

Нет, конечно... Именно - последовательные действия. Сначала первое, потом - второе, третье и т.д.

Именно в той последовательности, которую вы описали. Но, это так, к слову..)

Вот это - гораздо важней:

16 минут назад, COKPOWEHEU сказал:

объявлять как volatile локальные переменные бессмысленно, разве что хотите передать указатель на нее в прерывание. Но это то еще извращение.

Ну, вам виднее. Но смотрите, один вариант с указанием VOLATILE, другой - без указания. Больше ничего не менялось. Как так?

volatile.JPG.10f51f49518af886f2ffc62d4f63955c.JPG      NON_volatile.JPG.c1bdca3322f9ca5c9a2e232f974ee0ac.JPG

Период в два раза изменился...

 

 

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

25 минут назад, dm37 сказал:

У вас по условию 4 ШИМ и каждый управляется своими кнопками, по вашей структуре программы это не реализовать (я имею ввиду цикл while(T>=0))

Ну, как это - "не реализовать"?..

Вот код:

Скрытый текст

/*
 * PVM_ATmega16.c
 увеличение и уменьшение заполнения ШИМ нажатием кнопок
 */ 
#define F_CPU 4000000UL
#include  <avr/io.h>

int main()

{	
//DDRA=0xFF;
DDRB=0x00;//кнопки
DDRD=0xFF;//выход
DDRC=0xFF;//контроль

//PORTA=0x00;
PORTB=0xFF;//кнопки с резисторами
PORTD=0x00;//выход низкий
PORTC=0x00;//контроль низкий

volatile int  ton0=0, ton0_=ton0, d0=15;//время PORTD0_on, дубль PORTD0_on и приращение
volatile int  ton1=0, ton1_=ton1, d1=15;//время PORTD1_on, дубль PORTD1_on и приращение
volatile int  T=150, T_=T;//период и дубль
unsigned char  n=0, n0=0, r=0;//общий и инд счётчик, и разрешение изменения

while(1)

{

//  ************************************ проверка кнопок *********************************************** //
			
//  ************************************* кнопки канала PORTD0 ********************************************  //													

									// **** кнопка "+" *** //
										
if((!(PINB&0b00000001))&&(T>=(ton0+d0)))//если нажат "+" и есть возможность расширения импульса

{	
	n++;//инкр общий счётчик

	if(!(n&0b00000111))//если у общего счётчика три мл разряда ==0

	{
		n0++;//увеличиваем инд счётчик										     

		if((!(n0&0b00000111))&&(!(PINB&0b00000001))&&(!r))//если нажат "+" и у инд счётчика три мл разряда ==0

		{		
			ton0=ton0+d0;//увеличиваем время PORTD0_on
			ton0_=ton0;//обновляем дубль
			r=1;//запрещаем изменения
		}
	}
}		
									// **** кнопка "-" *** //
									
if((!(PINB&0b00000010))&&(0<=(ton0-d0)))//если нажат "-" и есть возможность сужения импульса

{
	n++;//инкр общий счётчик

	if(!(n&0b00000111))//если у общего счётчика три мл разряда ==0

	{
		n0++;//увеличиваем инд счётчик

		if((!(n0&0b00000111))&&(!(PINB&0b00000010))&&(!r))//если нажат "-" и у инд счётчика три мл разряда ==0

		{
			ton0=ton0-d0;//уменьшаем время PORTD0_on
			ton0_=ton0;//обновляем дубль
			r=1;//запрещаем изменения
		}
	}
}
							
//  ************************************* кнопки канала PORTD1 ********************************************  //
										// **** кнопка "+" *** //

if((!(PINB&0b00000100))&&(T>=(ton1+d1)))//если нажат "+" и есть возможность расширения импульса

{
	n++;//инкр общий счётчик

	if(!(n&0b00000111))//если у общего счётчика три мл разряда ==0

	{
		n0++;//увеличиваем инд счётчик

		if((!(n0&0b00000111))&&(!(PINB&0b00000100))&&(!r))//если нажат "+" и у инд счётчика три мл разряда ==0 и если разрешено изменение

		{
			ton1=ton1+d1;//увеличиваем время PORTD1_on
			ton1_=ton1;//обновляем дубль
			r=1;//запрещаем изменения
		}		
	}
}
										// **** кнопка "-" *** //

if((!(PINB&0b00001000))&&(0<=(ton1-d1)))//если нажат "-" и есть возможность сужения импульса

{
	n++;//инкр общий счётчик

	if(!(n&0b00000111))//если у общего счётчика три мл разряда ==0

	{
		n0++;//увеличиваем инд счётчик

		if((!(n0&0b00000111))&&(!(PINB&0b00001000))&&(!r))//если нажат "-" и у инд счётчика три мл разряда ==0

		{
			ton1=ton1-d1;//уменьшаем время PORTD1_on
			ton1_=ton1;//обновляем дубль
			r=1;//запрещаем изменения
		}
	}
}

// *********************************************** ШИМ ********************************************  //
PORTD=0xFF;//включаем всё
		
while(T>0)//период

{						
	if(ton0>0)ton0--;//считаем время PORTD0_on
	else PORTD&=0b11111110;//выключаем PORTD0_on
	
	
	if(ton1>0)ton1--;//считаем время PORTD1_on
	else PORTD&=0b11111101;//выключаем PORTD1_on
			
	T--;//считаем период				
}
		
T=T_;//восстанавливаем период
	
ton0=ton0_;//обновляем или восстанавливаем время PORTD0_on
ton1=ton1_;//обновляем или восстанавливаем время PORTD1_on
		
if(PINB==0b11111111)r=0;//если кнопки отпущены разрешаем изменение

}
}

 

Вот "протеус":

New_Button.rar

Цикл "while(T>0)" - в конце кода.

Пока - для двух каналов. Всё крутится. Что может помешать добавить ещё два?...

36 минут назад, dm37 сказал:

Для того чтобы узнать, нажата кнопка или нет вам надо их постоянно опрашивать, хотите вы этого или нет.

Вот это не понятно совершенно... Зачем мне всю неделю опрашивать кнопки, когда у меня даже мыслей не будет нажимать на них. Может, мне месяц тренироваться надо будет, чтобы на следующую скорость перейти.

А может не месяц. Может - год. И весь год опрашивать? Это же не клавиатура для скоростного набора текста...

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

41 минуту назад, dm37 сказал:

(раз уж вы так не хотите использовать прерывания таймера)

Вовсе нет. И, скорее всего, окончательный вариант будет именно на таймере... Но я не только хочу управиться с моим роботом (он, кстати, вполне себе управляется на трёх NE555), я хочу, хотя бы в минимальном объёме, познакомиться с программированием. Начать решил с программирования микроконтроллеров.

P.S. И я знаю, что есть мнение, и оно, скорее всего верно, что надо наоборот.

Сначала программирование, потом - контроллеры.

Пионер - всем ребятам пример.

There should be information on the web about this, but it may take some digging.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Сообщения

    • А где в вышеприведённой схеме стоит КП103?
    • Установить диапазон измерения 200Ком. Один  крокодил мультиметра подключить к стоку, другой к истоку. Полярность подключения не имеет значения. Пальцем нужно  руки прикоснуться к затвору. При рабочем транзисторе мультиметр будет показывать меняющиеся показания. MMBF5459 имеет другой тип проводимост и может использоваться при изменённой полярности включения.
    • Затвор исток 700-600 ом что туда что туда,как понимаю он мерт 
    • ТС к чтению относится, как тот кот Васька ...
    • @_abk_ у да, раз речь шла про тиньки, давайте еще сайт микрочипа процитируем для полноты картины...  
    • Да, глянул я эту тему, вроде даже отметился в обсуждении, сейчас уже забыл что конкретно мне не понравилось, но в целом конструкция достойная. В голосовалке как-то её задавили минусами, несправедливо, на мой взгляд. МК там не на отображении, чисто так, сервисный. И их вообще два - один спаян с платы частотомера   Очень много ключиков, и схема нарисована в диптрейсе, вникать не стал, потому что неудобно для чтения, но скелет +/- понятен. sot-23 на 3 и шесть ног я ещё кое-как приловчился паять. В этих корпусах идут некоторые опорники и китайские чопперы (у них есть вариант в со-8 но он раза в два дороже в чипе). А вот 0805 - уже не мой размерчик, ограничиваюсь 1206, но и то, вы можете видеть, как криво сидят элементы.           По этой причине платка на ADS1210, отметившаяся на фотке выше, была отправлена в помойку. Увидел график нелинейности в даташите, цену на али, и заказал. Пришло, спаял платку, залез в секцию даташита "интерфейс", поковырялся, почитал форумы с обсуждениями подобных АЦП - не выдержал, выпаял всё, кроме АЦП, и провёл ему "видларизацию". Уж больно сложный интерфейс, у 7135 он весьма простой для работы с ардуинкой. Сейчас жду ADS1252 (АЦП близкий к тому, что был использован в В7-87, там ADS1251, немногим помедленнее, зато более линейный), но 7135 не бросаю, потихоньку полируя на ней "ядро" уффффф. Докинув чуть побольше денег можно купить ICL7104-16, которая представляет из себя то же самое, но с 16ти битным счётчиком и выходами под внешние буфер, интегратор и компаратор, что очень хорошо, т.к. можно поставить нормальные быстрые ОУ на полевиках и компарь типа LM311 хотяб.
    • угонял до 0,7 вольта, увы нет.... Транзисторы на плате КТ3102, цоколевка обратная по сравнению с 2N5551   Пересмотрел, реле не читается по фото. Стоит Omron G2RL-14E-12DC
  • Похожий контент

×
×
  • Создать...