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