Страница 5 из 75

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Ср мар 04, 2015 12:32:33
Compressor
Вот это немного не ясно, получается во всех разрядах в скобках стоят нули, затем в номер бита пишем 1, все инвертируем. Там где наш нужный номер бита стал нулем логическое И даст ноль в регистре, а ост. разряды не изменит? Где-то так?

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Ср мар 04, 2015 12:37:58
Compressor
LED_PORT = LED_PORT & (0<<LED2);
Получается тут обн. Весь порт?

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Ср мар 04, 2015 12:43:53
FreshMan
Compressor писал(а):LED_PORT = LED_PORT & (0<<LED2);
Получается тут обн. Весь порт?
эта операция, ее можно записать проще PORT & = (0<<bit) выполняет не что иное как логическое И над портом
а эта PORT & =~ (0<<bit) делает сброс нужного вам бита в порте, в данном случае нулевого

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Ср мар 04, 2015 12:48:32
Compressor
Я понял, спасибо.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 09:17:08
kk042fjv
Добрый день!
Заинтересовал меня один вопрос, на ЖК я хочу вывести символ 0xA5

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

lcd_putchar(0xA5);
появляется буква И, как и положено. Дальше хочу вывести ±, мне нужно написать 0x90? (так ничего не получается).

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 09:48:16
ARV
получаться или не получаться у вас будет в зависимости от того, какой знакогенератор прошит в вашем ЖКИ: если там нет символа плюс-минус, то ваши попытки тщетны. в этом случае единственный для вас выход - использовать пользовательский знакогенератор, т.е. создать собственное изображение нужного символа, записать его в ЖКИ и затем уже выводить соответствующий код символа.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 09:53:40
akl
Думаю, Вам придется самостоятельно генерировать символ ± в CGRAM.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 10:00:06
kk042fjv
Это я в протеусе все пробовал.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 10:02:06
akl
Попробуйте загрузить 0xB1. Может повезёт.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 10:37:29
kk042fjv
akl писал(а):Попробуйте загрузить 0xB1. Может повезёт.
Выводит букву Я.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 14:38:06
WiseLord
FreshMan писал(а):эта операция, ее можно записать проще PORT & = (0<<bit) выполняет не что иное как логическое И над портом
а эта PORT & =~ (0<<bit) делает сброс нужного вам бита в порте, в данном случае нулевого
В корне неверно. Первая операция обнуляет весь порт, а вторая операция не делает ничего вообще. Не учите неправильным и неработающим вещам.

Правильное использование (допустим, bit = 3):

Установка бита:
PORT |= (1<<bit) равносильно PORT = PORT | (1<<bit) равносильно PORT = PORT | 00001000

Сброс бита:
PORT &= ~(1<<bit) равносильно PORT = PORT & ~(1<<bit) равносильно PORT = PORT & 11110111

Всё остальное - от лукавого. (0<<bit) вообще не имеет смысла, так как всегда равно нулю и не зависит от bit.
Compressor писал(а):LED_PORT = LED_PORT & (0<<LED2);
Получается тут обн. Весь порт?
Именно так. Порт логически умножается на ноль.
kk042fjv писал(а):Это я в протеусе все пробовал.
Насколько я понял, Вы русские буквы в протеусе видите. Значит, вероятнее всего, подменили библиотеку тамошнюю на русифицированную.

А у этой русифицированной библиотеки глюки с работой знакогенератора. По крайней мере, у меня знакогенератор в ней не работает, в отличие от оригинальной (которая, увы, без кириллицы).

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 19:46:31
DrRain
Здравствуйте, дабы не плодить темы, тем более тут разговор довольно близкий к моим вопросам.
Я только только знакомлюсь и с AVR и с Си. Прочитал пару тройку статей на тему программирования МК, и даже собрал небольшой тестовый стендик на ATmega8.

В качестве практики появилась идея написать программу для упревления доп освещением в машине.
Итак:
есть 4 группы лампочек и 3 кнопки
1 кнопка управляет по определенному алгоритму первой группой. (нажал кнопку горит отпустил потухла, нажал и держишь 2 секунды включается на постоянку, и отключается только при следующем нажатии)
2 кнопка точно по такому же алгоритму управляет второй группой.
3 кнопка попеременно а затем вместе включает оставшиеся группы.

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

В общем у меня ничего не получается, поможите советом пожалуйста.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 20:36:43
ARV
DrRain писал(а):как рулить отдельно каждым пином если все пины находятся на одном порту?
самым тривиальным способом: http://arv.radioliga.com/content/category/6/33/49/ - первые два пункта FAQ

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт мар 05, 2015 21:31:31
FreshMan
WiseLord писал(а):вторая операция не делает ничего вообще.
извиняюсь, нолик не заметил :)

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Пт мар 06, 2015 18:34:02
DrRain
Благодарю, вроде разобрался, может быть еще подскажете как реализовать функционал (поморгать лампочкой при помощи кнопки, а если кнопку подержать пару секунд, то лампочка включится на постоянку)?

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Пт мар 06, 2015 20:01:30
WiseLord
Завести счётчик, наращиваемый, например, раз в миллисекунду (по таймеру). Считать только при нажатой кнопке.

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

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

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб мар 07, 2015 09:13:05
DrRain
попробовал написать по Вашему алгоритму, вроде как так :)
пока не могу въехать в тонкости счетчиков. в общем ничего у меня не заработало ))))

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

#include <avr/io.h>
#include <avr/interrupt.h>
 
unsigned char cou1;  // назначаем переменную
char Flag1=0; // переменная флаг изначально сброшенный.

 
ISR (TIMER1_OVF_vect)
{
	if ((PIND&(1 << PD0)) == 0) // если кнопка PD0 нажата
	{
		if(Flag1==0)
		{
			PORTB=0b00000001; //включить ламочку
			cou1 = cou1+1; // пока кнопка нажата добавляем +1 в перем нную каждый цикл
		}
		else // если флаг не равен 0
		{
			cou1=0; //сбросим счетчик
			Flag1=0; // сбросим флаг
		}
		
	}
	if ((PIND&(1 << PD0)) == 1) // если кнопка отпущена
	{
		if(cou1<2000) // еслисчетчик не достиг значение
		{
			PORTB=0b00000000; //выключим лампочку
			cou1=0;				//сбросим счетчик
		}
		else // если достиг
		{
			PORTB=0b00000001; //включаем лампочку
			Flag1=1;		//устанавливаем флаг
		}
	}
}
	
 
int main(void)
{
 
DDRB= 0b11111111; //определяем PORTB на выход
PORTB= 0x00;	// изначально все лампочки на порту B выключены

DDRD = 0b11111000; //устанавливаем первые три ножки на вход остальные на выход
PORTD= 0b00000111; //подключаем к первым трем ножкам подт резисторы остальные уст в 0
 
TCCR1B = (1 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12); //предделитель clk/1024, режим таймера СТС
TCNT1 = 0;
TIMSK |= (1<<TOIE1); // разрешаем прерывание по переполнению таймера 
cou1 = 0; // Присвоение начального значения
 
sei(); // Разрешение прерываний
 
while (1) {}; // Бесконечный цикл
}
Есть ощущение что ошибки в настройке счетчика, но не хватает ни знаний ни смекалки понять где проблема. :)

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб мар 07, 2015 11:34:29
WiseLord
Ну, как минимум, unsigned char cou1; не может достигнуть значения 2000. Используйте unsigned int, или период счётчика в 10 раз больше и считать тогда до 200. Хорошо бы ещё следить и за тем, чтобы счётчик, досчитав до максимума, больше не инкрементировался.
Второй момент - coul и flag хорошо бы сделать volatile, так как они изменяются в прерывании.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб мар 07, 2015 14:51:51
ks0
И дребезг кнопки фильтровать, можно программно, можно формирователем на 555

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб мар 07, 2015 16:22:30
DrRain
переосмыслил, переписал код с нуля, теперь я хотя бы понимаю что и где происходит. :)
на данный момент работает моргание диодом с кнопки, а вот счетчик никак не хочет отрабатывать :( всю голову сломал, пересчитал предделитель.
не пойму где я не прав? ну не загорается лампочка на "постоянку".

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

#include <avr/io.h>
#include <avr/interrupt.h>
 
volatile int cou1;  // назначаем переменную
volatile char Flag1; // переменная флаг 

 
ISR (TIMER1_COMPA_vect)
{
if ((PINC&(1 << PC0)) == 0) // Проверка состояния переключателя
{
cou1 = cou1++; 
}
}	
 
int main(void)
{
// настройки портов ввода и вывода 
DDRB= 0b11111111; //определяем PORTB на выход
PORTB= 0b00000000;	// изначально все лампочки на порту B выключены

DDRD = 0b11111000; //устанавливаем первые три ножки на вход остальные на выход
PORTD= 0b00000111; //подключаем к первым трем ножкам подт резисторы остальные уст в 0
 
TCCR1A = 0x00;
TCCR1B = (1 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12); //предделитель clk/1024, режим таймера СТС
TCNT1 = 0x00;
OCR1A = 489; // максимальный предел счета (при 1 MHz это 500мс)
TIMSK |= (1 << OCIE1A); // разрешение прерывания по совпадению

cou1 = 0b00000000; // Присвоение начального значения
Flag1 = 0b00000000; //изначально сброшенный

sei(); // Разрешение прерываний
 
while (1) 
{
	if ((PIND&(1 << PD0)) == 0) // если кнопка PD0 нажата
	{
		
		if(Flag1==0)
		{
			PORTB=_BV(0); //включить ламочку
		}
		else // если флаг не равен 0
		{
			Flag1=1; // установим флаг в 1 (лампочка горит)
		}
		
	};
	
	if ((PIND&(1 << PD0)) == 1) // когда кнопку отпустили
	{
		if(cou1< 4) 		 // проверяем достиг ли счетчик указанного значения
		{
			PORTB &= ~_BV(0);  //выключим лампочку
			cou1=0;				//сбросим счетчик
			Flag1=0;			// снимим флаг (лампочка не горит)
		}
		else // если достиг
		{
			//PORTB=_BV(0); 		//включаем лампочку
			Flag1=1;			//устанавливаем флаг
			cou1=0;				//сбросим счетчик
		}
	}
	
	
}; // Бесконечный цикл
}