Страница 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
появляется буква И, как и положено. Дальше хочу вывести ±, мне нужно написать 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; //сбросим счетчик
}
}
}; // Бесконечный цикл
}