Например TDA7294

РадиоКот > Статьи

Математический винегрет на МК Atmel

Автор: Сергей
Опубликовано 21.05.2013.
Создано при помощи КотоРед.

Здравствуйте, уважаемые коты и гости нашего сайта!
    Как-то ранее я уже писал статью аналогичного направления, правда для микроконтроллеров серии PIC. В данной статье я попытаюсь сделать некое подобие "обучалки" для людей, умеющих моргать светодиодом, настраивать некую периферию, т.е. статья - для людей, имеющих некий опыт программирования. 
    В свое время мне очень помог сайт Корабельникова, и, чтобы пресечь всякую ругань и споры в отношении последнего, скажу: это мое, сугубо личное мнение. На мой взгляд, самоучитель последнего для меня в начале пути по освоению МК серии PIC был верхом совершенства. Но, оглядываясь на зад, вижу, что в самоучителе слишком много "воды". Ну да ладно. Как говориться - пора и честь знать. Так вот, о чем это собственно я? Рассматривая проекты других авторов (мы все критики) я неоднократно сталкивался с такой бедой: идея хороша, программа написана красиво, и т.п., но в ней совершенно нет математики! А на мой взгляд (МК я занимаюсь чуть более года) не использовать это замечательное свойство - возможность проведения рассчетов - просто кощунство! В качестве примера приведу следующее: данную программу (ассемблерный файл) я писал для устройства, (выложу позже) имеющего задачу заменить штатный узел в устройстве. Так вот, управление производится изменением напряжения на выводе, причем в одних устройствах логика прямая, а во вторых - инверсная, да и диапазон изменения напряжения разный. Поэтому было решено использовать МК ATtiny13A. Для подстройки диапазона (его растяжения) используются 2 резистора - один максимум задания, второй - соответственно минимум. Таким простым способом удается использовать одну прошивку для серии устройств (перекрутили их так, что "максимум" по абсолютному значению меньше "минимума").
Ну, теперь приступим: Операции сложения и вычитания при помощи МК часто встречаются в литературе и мануалах, поэтому здесь подробно рассматриваться не будут. Умножение. В МК младшего семейства отсутствуют аппаратные делитель и умножитель, позволяющие при помощи одной команды выполнять такие операции. Поэтому приходится изгаляться. В двоичной матиматике умножение выполняется... в столбик. Вы, наверное, встречали сведения о том, что простая операция сдвига влево эквивалентна умножению на 2, а вправо - делению? Так вот, возьмем для наглядности число 0b00000011 (3d) и 0b00011000 (24d), а затем перемножим их. В десятичном представлении ответ равен 72, в хексе 0x48.        Что же можно сделать в МК? Например сдвиг. Рассмотрим, что нам это дает. Используем промежуточный регистр - счетчик проходов выполнения операций сложения и сдвига. Как можно заметить из картинки, мы произвели 8 сдвигов и столько же сложений. Чтобы не задаваться вопросом что куда сдвигать и с чем складывать, поясню: сдвигать мы будем ответ, причем вправо! Почему, спросите вы, да потому, что это не операция деления, а такой хитрый ход! Посмотрите на картинку выше. Поверните ее на 180 градусов по горизонтали и всмотритесь в участок сложения. Что мы видим: первое слагаемое (все в повернутой картинке) - одни нули. Сдвинем их вправо и прибавим следующие нули. И так до тех пор, пока мы не встретили 1 во втором множителе. Так вот. Прибавляя к пустому ответу нули, мы получаем то же самое, но затем мы сдвигаем ответ вправо и опять выполняем сложение. Таких операций мы выполняем столько, сколько бит в наименьшем из множителей. 
    Ну, посчитали, посдвигали, а что же мы имеем? А вот что: (0*1)*3+(0*2)*3+(0*4)*3+(1*8)*3+(1*16)*3... = 24+48 = 72. Т.е. то, что хотели. Уффф, какой же это труд - писать статьи.
    Теперь (но уже чуть короче) о делении. 
    Возьмем для примера числа из картинки - 0x274C и 0x09. На картинке показана последовательность действий при делении. В некий вспомогательный регистр, равный по размерности делителю, вдвигаем влево (в младший бит) делимое. Далее выполняем вычитание - из вспомогательного регистра вычитаем делитель. Проверим, было ли замещение? Если оно было, значит мы вычли из меньшего большее. А делать этого нельзя! Поэтому пишем в ответ 0, производим обратную операцию - складываем вспомогательный регистр с делителем для восстановления исходного числа и производим сдвиг далее. Так поступаем до тех пор, пока не будет снят флаг carry - замещения. В этом случае пишем в младший бит ответа 1 и работаем дальше, до тех пор, пока не обнулится счетчик проходов, в который нужно записать число бит делимого (размер его регистра).
     В добавление к написанному выше прилагаю ассемблерный файл с написанными математическими программами. Правда там в делении есть лишний регистр - temporary+2, но, я полагаю, что если будет интересно, его можно просто удалить из операций (это я заметил чуть позже). Если что будет не совсем ясно - вопросы в форум.

Файлы:
Ассемблерный файл примера


Все вопросы в Форум.


ID: 1550