Изменение кода для счетчика

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

Здравствуйте. Помогите, пожалуйста.

Нужно дополнить код:

Код: Выделить всё

#include <avr/io.h>

#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>
//unsigned int i;???

//---------------------------------------------
void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 1: PORTD = 0b11111001; break;
		case 2: PORTD = 0b10100100; break;
		case 3: PORTD = 0b10110000; break;
		case 4: PORTD = 0b10011001; break;
		case 5: PORTD = 0b10010010; break;
		case 6: PORTD = 0b10000010; break;
		case 7: PORTD = 0b11111000; break;
		case 8: PORTD = 0b10000000; break;
		case 9: PORTD = 0b10010000; break;
		case 0: PORTD = 0b11000000; break;
	}
}
//---------------------------------------------
int main(void)
{
	unsigned char i;
	unsigned butcount=0,butstate=0;
	DDRD = 0xFF;
	DDRB = 0x00;
	PORTD = 0b00000000;
	PORTB = 0b00000001; // Нулевой порт на вход, подано питание.
	while(1)
	{
		for (i=0;i<10;i++) // Начальное и конечное значения, шаг.
		{
			while(butstate==0)
			{
				if (!(PINB&0b00000001)){
					if (butcount < 5)
					{
						butcount++;
					}
					else
					{
						i=0;
						butstate=1;
					}
				}
				else
				{
					if (butcount > 0)
					{
						butcount--;
					}
					else
					{
						butstate=1;
					}
				}
			}
			segchar(i);
			_delay_ms(1500); // Задержка 1,5 секунды
			butstate = 0;
		}

	}
}
В исходном виде он считает без нажатия кнопки и возвращается к нулю при ее нажатии. А нужно, чтобы отсчет начинался при нажатии кнопки и после остановки продолжался с той цифры, на которой отсчет был прерван, при этом не заменяя цикл for на таймер. Если правильно понимаю строка

butstate = 0; после строки со значением задержки отвечает за сбрасывание в ноль при остановке. На что ее заменить, чтобы отсчет продолжался не с нуля?

Как начать отсчет по нажатию кнопки при входе в программу (кнопка на нулевой ножке, при нажатии получается логический ноль)? В какую часть кода добавить эту новую строку? И нужно ли использовать переменную unsigned int i?
Последний раз редактировалось Аlex Чт июн 08, 2017 11:55:09, всего редактировалось 1 раз.
Причина: Тег CODE
Реклама
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт фев 09, 2010 17:52:26

Сообщение codenamehawk »

А кто вам запретил пробовать?
Реклама
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

А кто вам запретил пробовать?
Так в том-то и дело, что выполняю упражнение, код во втором случае нужно изменить без привлечения таймера.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Программа написана коряво, каким то школьником. Чтобы что-либо в ней переделать, нужно её всю переписать заново.
По этому, берёте своё ТЗ и шаг за шагом, потихоньку, реализовываете его. Появятся вопросы - милости просим.

PS: mnirti, когда выкладываете код, обрамляйте его соответствующим тегом (пример - первый пост этой темы, я поправил как нужно). Уже было сказано это Вам в другой теме, но Вы, по всей видимости, не любите читать...
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

Аlex, исправлюсь, буду предоставлять код с тегами.

Кажется, что код написан все-таки не школьником. Вот адрес самого упражнения:
Спойлерhttp://narodstream.ru/avr-urok-9-oformlenie-koda-funkcii/
Мне необходимо именно из этого исходного материала с циклом for сделать немного другой счетчик. Т. к. только учусь, огромная просьба помочь.
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Кнопки так не опрашивают. Даже если в коде и есть 5 опросов подряд со счётчиком - это не избавит от дребезга, т.к. они пролетят как пуля.
Нет события по кнопке (нажата, отжата, ...). Если она будет постоянно нажата, будет всегда обнуление переменной "i", что приведёт к зависанию нуля на индикаторе.
Кнопка просто тупо обнуляет счёт и больше не делает ничего. Она не останавливает счёт, ни запускает его, ... Так задано алгоритмом этой программы, который находится в тупике, и его немного не изменишь, только всё переписывать, согласно новому алгоритму.

Помочь очень хочется, но пока нечем - конкретных вопросов нет. Вопрос, типа "Как мне переделать это, чтобы работало как я хочу ?" не катит. На него ответов много.
Могу помочь только советом - начните писать программу заново и по-нормальному. Сделайте, для начала, перебор циферок на индикаторе. Затем добавьте нормальный обработчик кнопки. Когда он будет, у Вас появятся события от неё, в которых Вы уже будете добавлять код, связанный с этими событиями.
Контактная информация:
Реклама
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

Обработчик кнопки с избавлением от дребезга контактов такой:

Код: Выделить всё

if (PINB.0==0){ per=1;         
delay_ms(200);}                   
while(per==1)                     
{
if (PINB.1==0) {per=2;         
delay_ms(200);}                             
}
Или обработка нажатия:

Код: Выделить всё

private void button1_Click(object sender, System.EventArgs e)
{
   MessageBox.Show("button1 was clicked");
}
И если все заново, то можно хотя бы оставить основу:

Код: Выделить всё

#include <avr/io.h>

#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>

unsigned int i;

int main(void)
{
	unsigned char butcount=0;
	
	
	DDRD = 0xFF;
	DDRB = 0x00;
	PORTD = 0b00000000;    
	PORTB = 0b00000001; 
	
while (1)

{ 
	
	for (i=0; i<10; i+1) //i++ = i+1
	
	{
		//условие
		
	
	}
		
}
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Ничего не понял из Вашего поста :)
В обработчике кнопки что-то много всего лишнего. Достаточно :

Код: Выделить всё

if (PINB.0==0){        
delay_ms(10);
while(PINB.0==0);
delay_ms(10);
}                   
Но такой код повесит программу при удержании кнопки. Ну для начала достаточно.
Да, и почему PINB.0 ? В предыдущем коде у Вас опрос состояния входа было (PINB&0b00000001). Вы в CVAVR'е чтоли программу пишите ?
mnirti писал(а):Или обработка нажатия:
Тут вообще кусок из программы под винду :))
mnirti писал(а):И если все заново, то можно хотя бы оставить основу:
Это вопрос ? Если да, то - конечно можно :))
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

Программу пишу в атмель студио, тренируюсь на ATmega8A, там на нулевую лапку подается 1, если кнопку нажимаю, то сразу ноль (синий значок на соединении, проверяю в протеусе).

Тогда, наверное, так:

Код: Выделить всё

if ((PINB&0b00000001)==0))
{        
delay_ms(10);
while(1);
delay_ms(10);
}
В цикл помещаю 1, чтобы был беспрерывным. Подскажите, пожалуйста, какой нужен код, или цикл, или обработчик, который останавливает счет и возобновляет его с того значения, на котором прервали. Как такой оператор называется? Можно ли его в for поместить, или он будет в свитче в качестве default? В таймере библиотека прерываний interrupt, но в for какие-то другие нужны?
Получается: сначала кнопка не нажата (логическая единица,красный значок), нажали один раз, начинается отсчет от 0 до 9 по кругу, нажали другой раз - отсчет застывает на той цифре, до которой успел дойти (0 логический), кнопка отпущена - продолжается со следующей цифры (логическая 1). По идее, при нажатии на ножке будет ноль, но нужно то, чтобы первое нажатие кнопки воспринималось программой как запуск отсчета, а не как остановка. Остановка - после второго. Иначе получается, что не успела программа начаться, как уже остановится. А может с помощью break выполнить прерывание или он годится только для перехода на следующую цифру при отсчете?
Последний раз редактировалось mnirti Чт июн 08, 2017 15:25:20, всего редактировалось 1 раз.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Уууух, не думал, что всё так запущено ... :)
mnirti писал(а):В цикл помещаю 1, чтобы был беспрерывным.
Он бесконечный. А это значит, что он просто повесит программу навсегда.
mnirti писал(а):который останавливает счет и возобновляет его с того значения, на котором прервали. Как такой оператор называется?
Вы и вправду считаете, что есть такой оператор ? :)
Это - целый алгоритм, который нужно реализовывать и встраивать в существующий код. Причём он будет зависеть от существующего алгоритма программы.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

Уууух, не думал, что всё так запущено
Не запущено, запускать нечего, еще учиться, и учиться...

Если правильно понимаю:

Код: Выделить всё

while ((PINB&0b00000001)==0))
цикл будет сравнивать с 0, если приходит ноль, значит счет остановится.
Вы и вправду считаете, что есть такой оператор?
Нет, не считаю, просто не знаю как и из каких операторов (или циклов) собрать конструкцию, которая осуществит остановку и возобновление отсчета. Ищу на форумах, в других упражнениях, но нет там такого, что могу утащить и приделать на свое задание.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

mnirti писал(а):цикл будет сравнивать с 0, если приходит ноль, значит счет остановится.
Будут выполняться действия после этого оператора, пока условие в операторе (в скобках) будет равно истине.
Не стесняйтесь читать - https://yandex.ru/search/?lr=213&msid=1 ... 1%81%D0%B8
Конкретно в

Код: Выделить всё

while ((PINB&0b00000001)==0))
код будет выполняться, пока на ноге PB0 будет висеть лог. ноль.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

сначала напиши подробно по пунктам работу тогото, что ты хочешь получить: вот например непонятно как отанавливается счетчик повторным нажатием или при отпускании или другой кнопкой;
как счетчик должен себя вести если его остановили на середине интервала смежду цифрами (досчитывать потом остаток интервала или считать весь заново), и хоть это не так важно как управление, но тоже заслуживает внимания т.к. МК штука быстрая и часто в работе счетчиков применяются подсчетчики или задержки.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

непонятно как отанавливается счетчик повторным нажатием или при отпускании или другой кнопкой
В предыдущих постах было: там одна кнопка на нулевую ножку.

1. При нажатии начинается отсчет.
2. Повторное нажатие - останавливается.
3. Кнопку отпускаю, отсчет продолжается с той цифры, на которой был прерван.

Алгоритм работы понимаю, что должно быть, но вот как сделать - без малейшего понятия. :dont_know:

Код: Выделить всё

#include <avr/io.h>
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>
unsigned int i;

int main(void)
{
	unsigned char butcount=0;
	
	DDRD = 0xFF;
	DDRB = 0x00;
	PORTD = 0b00000000; // Весь регистр на выход 
	PORTB = 0b00000001; // Младший бит, нулевая нога на вход
	
	while ((PINB&0b00000001)==0)) // Цикл выполняется до тех пор, пока на нулевой ноге есть логический ноль
{
 {
	for (i=0; i<10; i+1) //i++ = i+1
	if ((PINB&0b00000001)==0))
_delay_ms(10);
	 PORTD = ~0b00000110;
	 _delay_ms(500);
	 PORTD = ~0b01011011;
	 _delay_ms(500);
	 PORTD = ~0b01001111;
	 _delay_ms(500);
	 PORTD = ~0b01100110;
	 _delay_ms(500);
	 PORTD = ~0b01101101;
	 _delay_ms(500);
	 PORTD = ~0b01111101;
	 _delay_ms(500);
	 PORTD = ~0b00000111;
	 _delay_ms(500);
	 PORTD = ~0b01111111;
	 _delay_ms(500);
	 PORTD = ~0b01101111;
	 _delay_ms(500);
	 PORTD = ~0b00111111;
	 _delay_ms(500);
       }
}

}
Может быть, добавить второй while, внутрь первого, сделать цикл в цикле, или дополнительную задержку?
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

[uquote="mnirti",url="/forum/viewtopic.php?p=3123019#p3123019"][quote]1. При нажатии начинается отсчет.
2. Повторное нажатие - останавливается.
3. Кнопку отпускаю, отсчет продолжается с той цифры, на которой был прерван.
...[/uquote]
т.е.
1) запуск МК - счетчик стоит, показание=0 (или выкл.)
2) кнопка нажата (первый раз) - счетчик пошел
3) кнопка отпущена - ???
4) кнопка нажата (2й раз и последующие) - счетчик останавливается
5) кнопка отпущена (после 2го и последующих) - счетчик запускается.
так?
тогда сначала пункты 1 и 2
1 - описываешь начальные условия
2 - ставишь пустой цикл на удержание, пока кнопка не нажата
3 -
4 и 5 прячешь в цикл FOR(i от 0 до 9), а его в бесконечный цикл - это тело счетчика
тут удобно сделать массив знаков для индикатора DIG[10]=...сдесь описаны выводимые в порт сигналы для каждой цифры от 0 до 9. (посмотри где и как описать массив)
в цикле просто пишешь задержку,
потом пустой цикл для удержания счетчика до отпускания кнопки,
потом вывод i в порт- PORTD=DIG;
всё.... (цикл FOR будет сам подставлять нужную цифру)
Последний раз редактировалось Ivanoff-iv Пт июн 09, 2017 12:46:11, всего редактировалось 1 раз.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

mnirti писал(а):Алгоритм работы понимаю, что должно быть, но вот как сделать - без малейшего понятия.
Значит взялись за сложную задачу.
Начните изучение с самых азов. Скачайте какой-нибудь учебник по Си и потихонечку начинайте изучать, создавая сначала простые программки.
Язык проще всего учить на компе. Результат виден сразу и режимы отладки имеются, что очень поможет при изучении.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

Да, в пункте 3 кнопка не нажата, то есть при запуске счетчика нажимается один раз, для остановки еще раз.

Подскажите, пожалуйста, какие ошибки в структуре:

Код: Выделить всё

#include <avr/io.h>
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>
unsigned int i;

int main(void)
{
	unsigned char butcount=0;
	
	DDRD = 0xFF;
	DDRB = 0x00;
	PORTD = 0b00000000; // Весь регистр на выход 
	PORTB = 0b00000001; // Младший бит, нулевая нога на вход
	
	while ((PINB&0b00000001)==1)) // Пустой цикл: кнопка не нажата
	if ((PINB&0b00000001)==1))
	{
		
	}
	while ((PINB&0b00000001)==0)) // Цикл выполняется до тех пор, пока на нулевой ноге есть логический ноль
{
 {
	for (i=0; i<10; i+1) //i++ = i+1
	if ((PINB&0b00000001)==0))
_delay_ms(10);

char dig [10]=  // Массив чисел 
 {
	 PORTD = ~0b00000110;
	 _delay_ms(500);
	 PORTD = ~0b01011011;
	 _delay_ms(500);
	 PORTD = ~0b01001111;
	 _delay_ms(500);
	 PORTD = ~0b01100110;
	 _delay_ms(500);
	 PORTD = ~0b01101101;
	 _delay_ms(500);
	 PORTD = ~0b01111101;
	 _delay_ms(500);
	 PORTD = ~0b00000111;
	 _delay_ms(500);
	 PORTD = ~0b01111111;
	 _delay_ms(500);
	 PORTD = ~0b01101111;
	 _delay_ms(500);
	 PORTD = ~0b00111111;
	 _delay_ms(500);
       }


while ((PINB&0b00000001)==0)) // Пустой цикл: кнопка нажата
if ((PINB&0b00000001)==0))
{
	
}
}
PORTD=char dig[i]; // Вывод значений в порт D

}
Добавлено after 5 minutes 18 seconds:
Значит взялись за сложную задачу.
Задача действительно очень сложная для меня. Но, к сожалению, приходится начинать не с простого. И изучать язык на компьютере также нет возможности, так как предстоит работать только в программе атмель и только с определенными типами микросхем.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

mnirti писал(а):Подскажите, пожалуйста, какие ошибки в структуре:
А компилятор ошибку что-ли какую выдаёт ?

Добавлено after 14 minutes 56 seconds:
mnirti писал(а):так как предстоит работать только в программе атмель и только с определенными типами микросхем
То, что потом предстоит - это дело десятое. Я сказал как проще его изучить.
Никто потом не запрещает эти знания применять в области программирования под микроконтроллеры.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт май 23, 2017 15:41:09

Сообщение mnirti »

Отладчик ошибки нашел в плане того, что не хватает скобок и точек с запятой. А при загрузке кода в МК и тестировании в протеусе получается, что питание на нулевую лапку изначально не подано, при нажатии кнопки часть сегментов не видна и счет останавливается сам по себе. Поэтому подозреваю, что циклы у меня неправильно записаны и/или строки не в том порядке. Программа не принимает запись массива DIG, только char dig.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Только что обратил внимание вот на это :

Код: Выделить всё

char dig [10]=  // Массив чисел 
 {
    PORTD = ~0b00000110;
    _delay_ms(500);
    PORTD = ~0b01011011;
    _delay_ms(500);
    PORTD = ~0b01001111;
    _delay_ms(500);
    PORTD = ~0b01100110;
    _delay_ms(500);
    PORTD = ~0b01101101;
    _delay_ms(500);
    PORTD = ~0b01111101;
    _delay_ms(500);
    PORTD = ~0b00000111;
    _delay_ms(500);
    PORTD = ~0b01111111;
    _delay_ms(500);
    PORTD = ~0b01101111;
    _delay_ms(500);
    PORTD = ~0b00111111;
    _delay_ms(500);
       }
Улыбнуло :)
Ну почитайте Вы, наконец, книги по Си. Не получится у Вас ничего методом тыка...
Контактная информация:
Ответить

Вернуться в «AVR»