Нескольно простых вопросов о программировании AVR на Си.
- Сообщения: 41
- Зарегистрирован: Пт май 29, 2009 09:38:45
Вот это немного не ясно, получается во всех разрядах в скобках стоят нули, затем в номер бита пишем 1, все инвертируем. Там где наш нужный номер бита стал нулем логическое И даст ноль в регистре, а ост. разряды не изменит? Где-то так?
- Реклама
- Сообщения: 41
- Зарегистрирован: Пт май 29, 2009 09:38:45
LED_PORT = LED_PORT & (0<<LED2);
Получается тут обн. Весь порт?
Получается тут обн. Весь порт?
эта операция, ее можно записать проще PORT & = (0<<bit) выполняет не что иное как логическое И над портомCompressor писал(а):LED_PORT = LED_PORT & (0<<LED2);
Получается тут обн. Весь порт?
а эта PORT & =~ (0<<bit) делает сброс нужного вам бита в порте, в данном случае нулевого
Последний раз редактировалось FreshMan Ср мар 04, 2015 12:48:32, всего редактировалось 1 раз.
Tell Me The Truth
- Сообщения: 41
- Зарегистрирован: Пт май 29, 2009 09:38:45
- Сообщения: 261
- Зарегистрирован: Ср авг 01, 2012 10:45:42
Добрый день!
Заинтересовал меня один вопрос, на ЖК я хочу вывести символ 0xA5
появляется буква И, как и положено. Дальше хочу вывести ±, мне нужно написать 0x90? (так ничего не получается).
Заинтересовал меня один вопрос, на ЖК я хочу вывести символ 0xA5
Код: Выделить всё
lcd_putchar(0xA5);- Реклама
получаться или не получаться у вас будет в зависимости от того, какой знакогенератор прошит в вашем ЖКИ: если там нет символа плюс-минус, то ваши попытки тщетны. в этом случае единственный для вас выход - использовать пользовательский знакогенератор, т.е. создать собственное изображение нужного символа, записать его в ЖКИ и затем уже выводить соответствующий код символа.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Думаю, Вам придется самостоятельно генерировать символ ± в CGRAM.
- Сообщения: 261
- Зарегистрирован: Ср авг 01, 2012 10:45:42
Попробуйте загрузить 0xB1. Может повезёт.
- Сообщения: 261
- Зарегистрирован: Ср авг 01, 2012 10:45:42
Выводит букву Я.akl писал(а):Попробуйте загрузить 0xB1. Может повезёт.
В корне неверно. Первая операция обнуляет весь порт, а вторая операция не делает ничего вообще. Не учите неправильным и неработающим вещам.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 писал(а):Это я в протеусе все пробовал.
А у этой русифицированной библиотеки глюки с работой знакогенератора. По крайней мере, у меня знакогенератор в ней не работает, в отличие от оригинальной (которая, увы, без кириллицы).
- Сообщения: 30
- Зарегистрирован: Чт янв 01, 2015 18:52:59
Здравствуйте, дабы не плодить темы, тем более тут разговор довольно близкий к моим вопросам.
Я только только знакомлюсь и с AVR и с Си. Прочитал пару тройку статей на тему программирования МК, и даже собрал небольшой тестовый стендик на ATmega8.
В качестве практики появилась идея написать программу для упревления доп освещением в машине.
Итак:
есть 4 группы лампочек и 3 кнопки
1 кнопка управляет по определенному алгоритму первой группой. (нажал кнопку горит отпустил потухла, нажал и держишь 2 секунды включается на постоянку, и отключается только при следующем нажатии)
2 кнопка точно по такому же алгоритму управляет второй группой.
3 кнопка попеременно а затем вместе включает оставшиеся группы.
Первый и самый главный вопрос: как рулить отдельно каждым пином если все пины находятся на одном порту? а то как не думал, не получается
2 через какую функцию лучше всего реализовывать алгоритм? пробовал через delay не удобно, я так понял при команде delay останавливается вся программа. пробовал через прерывания, тоже ничего путного не получилось )))
В общем у меня ничего не получается, поможите советом пожалуйста.
Я только только знакомлюсь и с AVR и с Си. Прочитал пару тройку статей на тему программирования МК, и даже собрал небольшой тестовый стендик на ATmega8.
В качестве практики появилась идея написать программу для упревления доп освещением в машине.
Итак:
есть 4 группы лампочек и 3 кнопки
1 кнопка управляет по определенному алгоритму первой группой. (нажал кнопку горит отпустил потухла, нажал и держишь 2 секунды включается на постоянку, и отключается только при следующем нажатии)
2 кнопка точно по такому же алгоритму управляет второй группой.
3 кнопка попеременно а затем вместе включает оставшиеся группы.
Первый и самый главный вопрос: как рулить отдельно каждым пином если все пины находятся на одном порту? а то как не думал, не получается
2 через какую функцию лучше всего реализовывать алгоритм? пробовал через delay не удобно, я так понял при команде delay останавливается вся программа. пробовал через прерывания, тоже ничего путного не получилось )))
В общем у меня ничего не получается, поможите советом пожалуйста.
самым тривиальным способом: http://arv.radioliga.com/content/category/6/33/49/ - первые два пункта FAQDrRain писал(а):как рулить отдельно каждым пином если все пины находятся на одном порту?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
извиняюсь, нолик не заметилWiseLord писал(а):вторая операция не делает ничего вообще.
Tell Me The Truth
- Сообщения: 30
- Зарегистрирован: Чт янв 01, 2015 18:52:59
Благодарю, вроде разобрался, может быть еще подскажете как реализовать функционал (поморгать лампочкой при помощи кнопки, а если кнопку подержать пару секунд, то лампочка включится на постоянку)?
Завести счётчик, наращиваемый, например, раз в миллисекунду (по таймеру). Считать только при нажатой кнопке.
Завести переменную-флаг постоянного горения, изначально сброшенный.
При нажатии кнопки, если флаг сброшен, включить лампочку и начать счёт. Если же флаг установлен - выключить счёт, сбросить флаг и сбросить счётчик. При отпускании кнопки, если счёт не достиг 2000, погасить лампочку и сбросить счёт. Если же достиг - оставить зажжённой и установить флаг.
Завести переменную-флаг постоянного горения, изначально сброшенный.
При нажатии кнопки, если флаг сброшен, включить лампочку и начать счёт. Если же флаг установлен - выключить счёт, сбросить флаг и сбросить счётчик. При отпускании кнопки, если счёт не достиг 2000, погасить лампочку и сбросить счёт. Если же достиг - оставить зажжённой и установить флаг.
- Сообщения: 30
- Зарегистрирован: Чт янв 01, 2015 18:52:59
попробовал написать по Вашему алгоритму, вроде как так 
пока не могу въехать в тонкости счетчиков. в общем ничего у меня не заработало ))))
Есть ощущение что ошибки в настройке счетчика, но не хватает ни знаний ни смекалки понять где проблема. 
пока не могу въехать в тонкости счетчиков. в общем ничего у меня не заработало ))))
Код: Выделить всё
#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) {}; // Бесконечный цикл
}Ну, как минимум, unsigned char cou1; не может достигнуть значения 2000. Используйте unsigned int, или период счётчика в 10 раз больше и считать тогда до 200. Хорошо бы ещё следить и за тем, чтобы счётчик, досчитав до максимума, больше не инкрементировался.
Второй момент - coul и flag хорошо бы сделать volatile, так как они изменяются в прерывании.
Второй момент - coul и flag хорошо бы сделать volatile, так как они изменяются в прерывании.
- Сообщения: 238
- Зарегистрирован: Чт фев 28, 2013 14:16:10
И дребезг кнопки фильтровать, можно программно, можно формирователем на 555
- Сообщения: 30
- Зарегистрирован: Чт янв 01, 2015 18:52:59
переосмыслил, переписал код с нуля, теперь я хотя бы понимаю что и где происходит. 
на данный момент работает моргание диодом с кнопки, а вот счетчик никак не хочет отрабатывать
всю голову сломал, пересчитал предделитель.
не пойму где я не прав? ну не загорается лампочка на "постоянку".
на данный момент работает моргание диодом с кнопки, а вот счетчик никак не хочет отрабатывать
не пойму где я не прав? ну не загорается лампочка на "постоянку".
Код: Выделить всё
#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; //сбросим счетчик
}
}
}; // Бесконечный цикл
}


