Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: 2 байта в AVR
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
pimen
Вопрос собственно в следующем:
разработана плата (и что плохо изготовлена), где есть связка Atmega128 и термодатчик MAX6630
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2577/t/al
Выход термодатчика - 13 бит (12+знак) и еще мусор до 2 байт (по spi).
как сравнить и обработать данные в восьмибитном микроконтроллере?
DASM
C чем именно сравнить и как обработать ? На каком языке надо ?
arttab
Организовать хранение 2 Б +
Цитата
мусор до 2 байт


Устроняйте пробел в своих знаниях иначе дальше будет хуже ( у AVR АЦП 10 бит, а разрядность таки 8).
MMos
Расскажи поподробнее, что бы ты делал с данными, если бы они были восьми- (или менее) разрядными.
Тогда можно дать конкретный совет, что делать при большей разрядности. Без этого вопрос очень неконкретный и ответа ждать придётся долго.
pimen
первоначально планировал сравнение значения температуры с пороговым значением.
немного поразмыслив, понял,что для этого необходимо сравнить сначала старший байт со старшим байтом опорного значения.
если старшие байты равны, то надо сравнивать младшие.
но потом пришло следующее требование - вывод температуры на знакосегментный индикатор. т.е. для этого надо преобразовать значения в двоично-десятичный код
а как?
работаю avrstudio+winavr на с
Algol
Попробуйте потестировать в отладчике мою функцию
unsigned int hex2bcd (unsigned char hex)
{
unsigned char i;
unsigned int bcd=0;
for(i=0;i<8;i++) {
if ((bcd & 0x0F) >= 0x05) bcd += 0x03;
if ((bcd & 0xFF) >= 0x50) bcd += 0x30;
bcd <<= 1;
if ((hex & 0x80)==0x80) bcd |= 0x01;
hex <<= 1;
}
return bcd;
}
Писано это около года назад, не помню где то в сети отрыл алгоритм быстрого преобразования hex to bcd, как раз с целью вывода на жки. Сюдя по тому что взято из рабочей проги, должно работать.
arttab
Довольно странные вопросы. Если пользуетесь Си компилятором, то надо Си знать. Если бы Вы знали Си, то вопрос как хранить более 8 бит не возникло.

Работа программиста не сводиться к поиску готовых решений и скачки их с инета. Требуется понимание предоставляемых Вам возможностей и умение ими пользоваться.

Советую перечитать курс по микропроцессорам, языку Си, доки по AVR, разобраться в выложенным Algol примеры и изучить компилятор.
DASM
Цитата(Algol @ Dec 25 2007, 14:22) *
отрыл алгоритм быстрого преобразования hex to bcd, как раз с целью вывода на жки.

Работает. Только вот как - нифига не понял crying.gif
alexander55
Цитата(pimen @ Dec 24 2007, 02:37) *

Если работаете с С используйте для 16 битных данных типы unsigned int и int.
Все Ваши проблемы решит компилятор.
MMos
Снимаю шляпу перед автором алгоритма. Красота-а-а-а!
На Си попробовать было негде - сваял процедурочку на VBA. Расширил до 16 разрядов. Алгоритм потенциально расширяем на любое количество разрядов. Вы будете смеяться, но я его понял! Правда только после того, как запустил под отладчиком.
В общем СУПЕР! Рекомендую программистам всех времён, народов и языков.
Побежал реализовывать на ассемблере.
MMos
Ниже приведена ассемблерная реализация алгоритма для MSC-51 (в AVR пока не силён).
В примере преобразуется десятичное число 23456.
Удлинняет код та особенность, что "полезные" операции можно выполнять только с аккумулятором.
При попытке перевести реализацию на AVR столкнулся с проблемой - не могу найти операцию двоично-десятичной коррекции (в нижеприведеном коде это команда DA). Это мне так не повезло или такой операции у AVR вообще нет?

start:
mov r3,#0 ; результат старший байт
mov r4,#0 ; результат средний байт
mov r5,#0 ; результат младший байт
mov r6,#05bh ; исходные данные старший байт
mov r7,#0a0h ; исходные данные младший байт
mov r0,#16 ; счётчик циклов
cycle:
mov a,r7
rlc a
mov r7,a
mov a,r6
rlc a
mov r6,a
mov a,r5
addc a,r5
da a
mov r5,a
mov a,r4
addc a,r4
da a
mov r4,a
mov a,r3
addc a,r3
da a
mov r3,a
djnz r0,cycle
pimen
Всех с наступившим Новым Годом!
написал прогу к вышесказанному

#include <avr/io.h>//mega128

char U,L;

void SPI_read(void)
{
SPCR=0x50;
SPDR=0xaa;
while(SPSR==0x00)
{ }
U=SPDR;

SPDR=0xaa;
while(SPSR==0x00)
{ }
L=SPDR;
SPCR=0x00;
}

void main(void)
{ PORTB&=0xDF;//spi fpga
SPI_read();
PORTB|=0x20;

//...сравнение значений температур с пороговым

PORTB&=0xEF;//spi rf
SPI_read();
PORTB|=0x10;
}

здесь сначала читается первый байт, потом второй байт из цифровых термометров
если я пишу это в переменную типа int, то все равно могу записать только 1 байт:
т.к. регистр spi расчитан на байт информации, то требуется новый запуск модуля spi для чтения информации с датчиков
при последующем чтении из регистра и записи информации в переменную предидущии данные естественно удаляются
как дописать данные в туже переменную?
или может подскажите идею или другую программную реализацию
жду ответов
--------------------------------------------------
щас читаю 3 книги: 2 по авр и по с....
vooon
прочитать например так:
(старший байт первый)

Код
/**
* Отправить \a send по SPI
* \return принятое по SPI значение
*/
unsigned char spi(unsigned char send);

....
{
  int temp;
  int porog;
...
  temp = spi(0);
...
...
  temp = (temp<<8)|spi(0);
...
  if (temp == porog)
  {
...
  }
...
}
slanted
Цитата(pimen @ Dec 24 2007, 03:37) *
Вопрос собственно в следующем:
разработана плата (и что плохо изготовлена), где есть связка Atmega128 и термодатчик MAX6630
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2577/t/al
Выход термодатчика - 13 бит (12+знак) и еще мусор до 2 байт (по spi).
как сравнить и обработать данные в восьмибитном микроконтроллере?

Для этого придуман флаг переноса и соответствующие инструкции, учитывающие его (sub/sbc, cp/cpc).
pimen
Цитата(slanted @ Jan 3 2008, 14:51) *
Для этого придуман флаг переноса и соответствующие инструкции, учитывающие его (sub/sbc, cp/cpc).

а как это реализуется/используется на С в AVRstudio?
slanted
Цитата(pimen @ Jan 3 2008, 18:57) *
а как это реализуется/используется на С в AVRstudio?

Теоретически, оно должно само уметь обсчитывать стандартные сишные типы с помощью этих инструкций. WinAVR, к примеру, точно умеет. А вопрос-то был про восьмибитки вообще, я на него и ответил.

ps. Собственно, подобные инструкции есть везде, в x86 тоже.
pimen
ЛЮДИ!!!!
Объясните!
есть программа:

#include <avr/io.h>

int T=0x0;

main ()
{
T=(0b10001100<<8)>>3;
}

это нечто выдает значение Т=0b1111000110000000, хотя должен 0b0001111000110000.
если заменить сдвиг право на 3 на деление на 0b1000, то результат все равно 0b1111000110000000.
деление и сдвиг просто числа 0b1000110000000000 дает правильные результаты.
что я не учел??????????
zltigo
Цитата(pimen @ Jan 6 2008, 03:02) *
это нечто...

Главная ошибка - Вы начали использовать "нечто" пытающееся эмулировать дебильную бинарную запись при наличии в языках много более удобных средств, например, возможности поименовать биты. Разбираться (только зачем - правильнее не пользоваться) можете начинать с реализации этой самой 0b....
Потенциальная ошибка - препроцессор особым умом обычно особо не отличается, посему не не искушайте его и пользуйтесь не менее выразительным " <<( 8-3 )" а не "(<<8)>>3"
Примечание - разрядность констант не резиновая и по умолчанию чаще всего 16bit, посему нежели в будующем потребуется большая, то не забудте указать сие явно через 'L'.

C некоторой долей вероятности основываясь на типичных ошибках в реализации макросов на основе которых построено "нечто" можете попробовать:
T=(0b10001100) << (8-3);
AHTOXA
Цитата
T=(0b10001100<<8)>>3;
...
выдает значение Т=0b1111000110000000, хотя должен 0b0001111000110000.


И что тут не правильного? Было 2 нуля справа, стало 7. Как раз сдвиг влево на 5.

А с единичками в старших разрядах что-то напутано:-)
slanted
Цитата(zltigo @ Jan 6 2008, 05:47) *
Главная ошибка - Вы начали использовать "нечто" пытающееся эмулировать дебильную бинарную запись при наличии в языках много более удобных средств, например, возможности поименовать биты. Разбираться (только зачем - правильнее не пользоваться) можете начинать с реализации этой самой 0b....
Потенциальная ошибка - препроцессор особым умом обычно особо не отличается, посему не не искушайте его и пользуйтесь не менее выразительным " <<( 8-3 )" а не "(<<8)>>3"
Примечание - разрядность констант не резиновая и по умолчанию чаще всего 16bit, посему нежели в будующем потребуется большая, то не забудте указать сие явно через 'L'.

C некоторой долей вероятности основываясь на типичных ошибках в реализации макросов на основе которых построено "нечто" можете попробовать:
T=(0b10001100) << (8-3);

И где тут хоть один макрос?
Кстати, >>(8-3) сработает, но по совсем другой причине.

Цитата(pimen @ Jan 6 2008, 05:02) *
int T=0x0;

main ()
{
T=(0b10001100<<8)>>3;
}

это нечто выдает значение Т=0b1111000110000000, хотя должен 0b0001111000110000.
если заменить сдвиг право на 3 на деление на 0b1000, то результат все равно 0b1111000110000000.
деление и сдвиг просто числа 0b1000110000000000 дает правильные результаты.
что я не учел??????????


Проблема в том, что: а) стандарт Си не специфицирует, будет ли ">>" арифметическим сдвигом, или логическим; б) не специфицируется размер int'а, который в данном случае составляет 16 бит. В результате сдвига на 8 влево, 0b10001100 превращается в 0x8C00, которое содержит единицу в знаковом бите (типа это отрицательное число). Сдвиг вправо, который как оказалось, в данном случае арифметический, размазывает эту единицу по старшим битам числа чтобы сохранить отрицательность. В результате имеем то, что имеем.

При сдвиге "просто числа" 0b1000110000000000 такого не происходит, потому что данная реализация компилятора считает константы данного вида unsigned, и генерирует для них логический сдвиг.
zltigo
Цитата(slanted @ Jan 6 2008, 14:03) *
И где тут хоть один макрос?

Прибамбасы (0b.... ) штатными средствами компиляторов не поддерживаются и в этом случае реализуются твердыми последователями ассемблеров не имеющих поддержки макросов на на макросах smile.gif - вот такой парадокс.
pimen
Еще вопрос по С:
использовал оператор goto. Сам оператор находится в подпрограмме, метка находится в main(). Компилятор пишет ошибку.
Если переношу оператор goto в main(), то все нормально.
что за ерунда?
mdmitry
Цитата(pimen @ Jan 10 2008, 23:22) *
Еще вопрос по С:
использовал оператор goto. Сам оператор находится в подпрограмме, метка находится в main(). Компилятор пишет ошибку.
Если переношу оператор goto в main(), то все нормально.
что за ерунда?

Прочитать книгу по языку С и понять назначение оператора goto в языке. В ассемблере переход не запрещен из функции, программирование на С структурное и выход из функции должен быть корректно оформлен (очистка стека и другое).
slanted
Цитата(pimen @ Jan 11 2008, 00:22) *
Еще вопрос по С:
использовал оператор goto. Сам оператор находится в подпрограмме, метка находится в main(). Компилятор пишет ошибку.
Если переношу оператор goto в main(), то все нормально.
что за ерунда?

Так задумано. Если хотите прострелить себе ногу -- прочитайте про setjmp/longjmp, которым такое поведение эмулируется.
alexander55
Цитата(pimen @ Jan 10 2008, 23:22) *
Еще вопрос по С:
использовал оператор goto. Сам оператор находится в подпрограмме, метка находится в main().

Это что за издевательство ?
Подумайте, что будет со стеком ?
PS. Мой Вам совет - забудьте про goto и никогда не вспоминайте .
pimen
по поводу оператора goto, пользуясь вашими советами, забуду.
Подскажите, как корректно переместиться из подпрограммы в main()
структура программы приведена ниже:

void hot(void)
{
//отсюда надо попасть в main()
}

void compare(void)
if (....)
{
hot()
}

SIGNAL(SIG_OVERFLOW1)
{
...
compare()
...
}

main()
{
// сюда надо перескочить из hot()
}
alexander55
Цитата(pimen @ Jan 11 2008, 12:35) *
по поводу оператора goto, пользуясь вашими советами, забуду.
Подскажите, как корректно переместиться из подпрограммы в main()
структура программы приведена ниже:

void hot(void)
{
//отсюда надо попасть в main()
}

void compare(void)
if (....)
{
hot()
}

SIGNAL(SIG_OVERFLOW1)
{
...
compare()
...
}

main()
{
// сюда надо перескочить из hot()
}

Давайте уточним задачу.
По некоторому прерыванию SIGNAL(SIG_OVERFLOW1)
при выполнении каких-то условий (скажем аварийных), Вы быстро должны произвести какие-то действия в hot() и завершить выполнение прерывания.
Так или что-то еще осталось за кадром ?
PS. Вспомнил про обсуждения на эту тему
http://electronix.ru/forum/index.php?showt...&hl=*goto*#
pimen
Цитата(alexander55 @ Jan 11 2008, 13:34) *
Давайте уточним задачу.
По некоторому прерыванию SIGNAL(SIG_OVERFLOW1)
при выполнении каких-то условий (скажем аварийных), Вы быстро должны произвести какие-то действия в hot() и завершить выполнение прерывания.
Так или что-то еще осталось за кадром ?
PS. Вспомнил про обсуждения на эту тему
http://electronix.ru/forum/index.php?showt...&hl=*goto*#


Вы совершенно правильно поняли
в hot() происходит выключение источников, потом в main(), пока есть авария (в данном случае перегрев), ждем устранение аварийного фактора, и поехали дальше

спасибо за ссылку
alexander55
Цитата(pimen @ Jan 11 2008, 14:42) *
Вы совершенно правильно поняли
в hot() происходит выключение источников, потом в main(), пока есть авария (в данном случае перегрев), ждем устранение аварийного фактора, и поехали дальше


В main Вы попадете по окончании прерывания без всяких фокусов (причем с корректным стеком).
Если Вам надо заблокировать какие-то действия в прерывании, установите флаг аварии при выходе за допустимые пределы и анализируя этот флаг не выполняйте, что не требуется.
После устранения аварии этот флаг сбросьте (подозреваю, что он уже существует).
Вот и все.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.