Свежие обсуждения
Микроконтроллеры

Начинаю изучать AVR. К кому из участников форума можно обратиться с "глупыми вопросами"?

1 4 5

>осталось в асемблер перевести и протестить

-- Это мазохизм :- ) Тестить надо на ПЭВМ, а уж потом, если результат удовлетворительный, переводить на ассемблер МК. Впрочем, какой смысл переводить на ассемблер тоже не понятно. Хорошие компиляторы Си под AVR есть.

 

Остальная (основная) часть программы написана на ассемблере для повышения скорости (напряжение и ток не основная задача). Если писать на Си, то получится сплошная ассемблеровская вставка

 

Если нет возражений, я вернусь к теме раздела ( о глупых вопросах). Методику программирования на Си для МК я так и не нашел. Сейчас застрял с одной маленькой проблемой, может кто подскажет, как ее решить. В исходном состоянии на PINA0 '1', При появлении на ней '0' переменной A1 присвоить случайное значение от 0 до 9, переменной A2 - от 0 до 3 и выдать их значения поочередно в порт С. МК MEGA8535. Вроде задача простая.Но у меня в эмуляторе получается на выходе порта генерация, независимо от состояния порта A.

 

- Вы задачу нечетко сформулировали. Сразу возникают вопросы:

1) После выдачи пары чисел программа возвращается в исходное состояние (ожидание появления 0 на PINA0) или нет?
2) Если да, то что должно происходить при удержании 0 на PINA0 -- непрерывная генерация чисел или ожидание появления 1 на PINA0?
Еще непонятно, зачем нужны переменные A1 и A2..
Если бы Вы показали свой исходный код (неработающий), было бы совсем хорошо

Если предположить, что ответы на вопросы:
1) Программа возвращается в исходное состояние.
2) Ожидание появления 1 на PINA0.

Кусок кода будет выглядять примерно так (предполагается, что порты уже настроены и требуемый заголовочный файл stdlib.h подключен):

/* Бесконечный цикл */
for (;;)
{
/* Дожидаемся 1 на PINA0 */
while ((PINA & 1) == 0);
/* Дожидаемся 0 на PINA0 */
while (PINA & 1);
/* Отправляем в PORTC случайное число в диапазоне [0..9] */
PORTC = rand() % 10;
/* Отправляем в PORTC случайное число в диапазоне [0..3] */
PORTC = rand() % 4;
}

PS. Интересно, что Вы подразумеваете под "методикой программирования на Си для МК". Особенности конечно есть, а вот никакой специальной методики нет.

 

В упрощенном варианте на вход PINA0 поступает 1 (DDRA = 0x00 PORTA = 0xFF)
При кратковременном нажатии на кнопку без фиксации на PORTA0 поступает 0, кнопка отпускается- на входе опять 1.
При этом переменным A1 и A2 присваиваются случайные значения, фиксируются и поступают на выход до следующего нажатия на кнопку.
При следующем нажатии все повторяется(значения A1, A2 меняются). Когда это получится, задача усложнится. С переменными A1, A2 до выдачи на выход будут производиться операции. Поэтому я их ввел, думаю тк будет легче. Вход PORTA0 это такт синхронизации, по которому будут производиться эти шаги. Т.к. я только учусь программировать МК, я задачи разбиваю на маленькие блоки, постепенно приходя к цельной программе.

/PS. Интересно, что Вы подразумеваете под "методикой программирования на Си для МК".

Прежде чем взяться за МК я освоил основы Си, Си++ в среде Windows. Нашел довольно хорошую методику. вроде все получалось. Кстати, если кого интересует, великолепная методика изучения СИ++ Уолтер Савич "Программирование на Си++". Но этих знний не достаточно для программирования МК. Здес добавляется нечто общее между кодами и Си, отличается синтаксис. Просматривая примеры и источники, указанные мной выше, пытаюсь что-то изобразить, но увы. Например, случауное число от 0 до 9 в Си++ будет выглядеть randomize(10), этож надо знать, что здесь нужно это описать как rand() % 10

 

Набрал этот листинг в ICC, смотрел в эмуляторе VMLAB.

#include <io8535.h>
#include <stdlib.h>
void delay(void);
void main(void)
{
int A1, A2;
DDRA = 0x00;
PORTA = 0xFF;
DDRC = 0xFF;
PORTC = 0xFF;
while(1)
{
while (PINA & 1) // Ожидание '0'
{
PORTA = 0xFF; // Восстановление '1' на входе
A1 = rand()%10;
A2 = rand()%4;
PORTC = A1;
delay();
PORTC = A2;
}
}
}

void delay(void)
{
unsigned char a, b;
for (a =1; a; a++)
for(b = 1; b; b++);
}
В эмуляторе в окне состояния регистров портов меняю значения входного порта. На выходе (PORTC) постоянная генирация, независимо от состояния входа (PORTA).

 

Решение задачи я уже написал, в эмуляторе AVRStuio оно работает именно так как надо (не поленился проверить).

В Вашем коде логические ошибки. Вместо ожидания 0 все команды будут повторятся до тех пор, пока на PINA0 присутствует 1. Вдобавок делается попытка ПРОГРАММНОГО восстановления 1 на входе, когда оно ФИЗИЧЕСКИ определяется уровнем напряжения на соотв. ножке

Ожидание 0 следует делать так:
while (PINA & 1);
или, что то же самое:
while (PINA & 1) {}
Т.е. пустой цикл, повторяющийся пока на PINA0 присутвует 1.

Следует учесть, что в реальном устройстве проблемы может создать дребезг контактов. И еще: задачу можно было бы решить иначе, используя внешнее прерывание.

---

Про методику и пр:

Си и Си++ это разные языки (хотя Си является подмножеством Си++). С++ сложней на порядок, если изучать его в полном объеме. Для программирования микроконтроллеров почти не применяется. Название книжки "Программирование на С++" настораживает. Хорошо если Си там рассмотрен отдельно. Или хотя бы указано, чем Си++ отличается от Си.

Про якобы отличающийся синтаксис Си для ПЭВМ и микроконтроллеров -- приведите примеры, в каком месте он отличается. Если есть желание, конечно.

>Например, случауное число от 0 до 9 в Си++ будет выглядеть randomize(10), этож надо знать, что здесь нужно это описать как rand() % 10

Ерунду пишите. Стандартная (т.е. прописанная в утвержденный комитетом стандарт языка) функция rand() в С++ есть, также как и в Си. Работает под любой платформой. А вот упомянутой Вами randomize() нет. rand() % 10 это не какая-то специфическая для микроконтроллеров магия. Такой прием работает везде (Windows, DOS, UNIX и пр). Напомню, что оператор % -- это взятие остатка от деления. Функция rand() возвращает случайное число в диапазоне от 0 до 32767 (обычно). Остаток от деления на 10 -- тоже случайное число, но уже в диапазоне [0..9].

PS. С мой точки зрения, беда в том что Вы делаете далеко идущие выводы без достаточной базы для этого. То есть сами себя запутываете.

 

PS. С мой точки зрения, беда в том что Вы делаете далеко идущие выводы без достаточной базы для этого. То есть сами себя запутываете.

В том то и дело, что у меня нет никакой базы в программировании микроконтроллеров. Потому и спрашиваю тех кто знает. Пытаюсь освоить по обрывкам информации, которые удается достать. Книги заказываю с Москвы в несколько месяцев один раз ( и привозят не все). В среде Windows. основы освоил, писал програмки, они работают. Сейчас приступил к микроконтроллерам, пока кроме коммутации свеодиодов (написал в Algorithm builder несколько переключающихся режимов) ничего не получается. В среде Windows эта задача была решена давольно быстро.
То, что для этих задач нужно См, а не Си++, я понял. Просто мне вместо литературы по Си привезли эту. До следующего заказа было месяца три. Начал изучать и не жалею. Книга великолепная. Обещаю, что любой по ней научится программировать на Си++. Когда освою МК буду дальше изучать Си++.

 

>В среде Windows. основы освоил, писал програмки, они работают. Сейчас приступил к микроконтроллерам, пока кроме коммутации свеодиодов <...> ничего не получается.

...и обвиняте в этом микроконтроллерную специфику. А зря. Вот смотрите: берем Ваш код и заменяем строку
#include <#include <io8535.h> на
unsigned char DDRA, DDRC, PORTA, PORTC, PINA;
После этого программу можно откомпилировать под любую платформу, в т.ч. Windows. Более того, ее можно даже отлаживать и симулировать (с определенными условностями). Поэтому ссылаться на различный синтаксис и методики, скажем так, не совсем верно.

Проблема в несколько другой плоскости лежит. Например, Вы хотите подождать появления на PINA0 лог. нуля, затем выполнить ряд команд. Но почему-то пишите код, который делает прямо противоположное -- циклическое выполнение ряда команд пока PINA0 == 1. Объяснить подобную ошибку чем-то специфическим для МК нельзя. PINA -- обычная глобальная переменная, с одной лишь особенностью -- ее значения задается только извне (аппаратно).

Следовательно, имеет место быть логическая ( алгоритмическая ) ошибка. Которую таким же успехом можно повторить и под Windows, в похожей ситуации.

В среде Windows эта задача была решена давольно быстро.

Интересно, как?

 

Мне непонятна Ваша позиция. В среде Windows эта задача решена, и я не думаю, что это предмет доказательства своих знаний. я говорю, что решил ее только потому, что дйствительно этот факт имеет место, а не для того, чтобы показать свои способности программирования перед программистом, которому вряд-ли есть до этого дело. Я электронщик и тягаться с программистом в программировании не собираюсь. А что касается ошибки, про которую Вы говорите, я перепробывал. и while (PINA0 & 1); , и while (PINA0 & 1) , и с PORTA = 0xFF; , и без.и в VMLAB и в AVRSTUDIO. Не получается. Я всевго лишь спрашиваю информацию о литературе. Как я уже указывал, достать мне ее не легко, а Интернет мне обходится 1МБ - 0,5$. Насколько я понял из сообщений в Интернете, я не единственный, кто встретился с этими проблемами. и ответы были бы интересны не только мне. Практака решения задач, стоявших передо мной, дает уверенность, что я рано или поздно ее решу, но я думаю, что это форум полезен и для многих других русскоязычных специалистов.