|
2 байта в AVR, как сранить и обработать 16 разрядов в ATmega? |
|
|
|
Dec 23 2007, 23:37
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
Вопрос собственно в следующем: разработана плата (и что плохо изготовлена), где есть связка Atmega128 и термодатчик MAX6630 http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2577/t/alВыход термодатчика - 13 бит (12+знак) и еще мусор до 2 байт (по spi). как сравнить и обработать данные в восьмибитном микроконтроллере?
|
|
|
|
|
Dec 24 2007, 02:49
|

Профессионал
    
Группа: Свой
Сообщений: 1 432
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 371

|
Организовать хранение 2 Б + Цитата мусор до 2 байт Устроняйте пробел в своих знаниях иначе дальше будет хуже ( у AVR АЦП 10 бит, а разрядность таки 8).
--------------------
OrCAD, Altium,IAR, AVR....
|
|
|
|
|
Dec 25 2007, 11:07
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
первоначально планировал сравнение значения температуры с пороговым значением. немного поразмыслив, понял,что для этого необходимо сравнить сначала старший байт со старшим байтом опорного значения. если старшие байты равны, то надо сравнивать младшие. но потом пришло следующее требование - вывод температуры на знакосегментный индикатор. т.е. для этого надо преобразовать значения в двоично-десятичный код а как? работаю avrstudio+winavr на с
|
|
|
|
|
Dec 29 2007, 09:08
|
Частый гость
 
Группа: Участник
Сообщений: 147
Регистрация: 7-12-07
Пользователь №: 33 057

|
Ниже приведена ассемблерная реализация алгоритма для 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
Сообщение отредактировал MMos - Dec 29 2007, 09:11
|
|
|
|
|
Jan 2 2008, 23:35
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
Всех с наступившим Новым Годом! написал прогу к вышесказанному
#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 по авр и по с....
Сообщение отредактировал pimen - Jan 2 2008, 23:52
|
|
|
|
|
Jan 3 2008, 11:41
|

Участник

Группа: Свой
Сообщений: 72
Регистрация: 27-06-06
Из: Msk
Пользователь №: 18 401

|
прочитать например так: (старший байт первый) Код /** * Отправить \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) { ... } ... }
|
|
|
|
|
Jan 3 2008, 11:51
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 2-01-08
Пользователь №: 33 768

|
Цитата(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).
|
|
|
|
|
Jan 3 2008, 14:57
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
Цитата(slanted @ Jan 3 2008, 14:51)  Для этого придуман флаг переноса и соответствующие инструкции, учитывающие его (sub/sbc, cp/cpc). а как это реализуется/используется на С в AVRstudio?
|
|
|
|
|
Jan 3 2008, 16:36
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 2-01-08
Пользователь №: 33 768

|
Цитата(pimen @ Jan 3 2008, 18:57)  а как это реализуется/используется на С в AVRstudio? Теоретически, оно должно само уметь обсчитывать стандартные сишные типы с помощью этих инструкций. WinAVR, к примеру, точно умеет. А вопрос-то был про восьмибитки вообще, я на него и ответил. ps. Собственно, подобные инструкции есть везде, в x86 тоже.
|
|
|
|
|
Jan 6 2008, 01:02
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
ЛЮДИ!!!! Объясните! есть программа:
#include <avr/io.h>
int T=0x0;
main () { T=(0b10001100<<8)>>3; }
это нечто выдает значение Т=0b1111000110000000, хотя должен 0b0001111000110000. если заменить сдвиг право на 3 на деление на 0b1000, то результат все равно 0b1111000110000000. деление и сдвиг просто числа 0b1000110000000000 дает правильные результаты. что я не учел??????????
|
|
|
|
|
Jan 6 2008, 01:47
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(pimen @ Jan 6 2008, 03:02)  это нечто... Главная ошибка - Вы начали использовать "нечто" пытающееся эмулировать дебильную бинарную запись при наличии в языках много более удобных средств, например, возможности поименовать биты. Разбираться (только зачем - правильнее не пользоваться) можете начинать с реализации этой самой 0b.... Потенциальная ошибка - препроцессор особым умом обычно особо не отличается, посему не не искушайте его и пользуйтесь не менее выразительным " <<( 8-3 )" а не "(<<8)>>3" Примечание - разрядность констант не резиновая и по умолчанию чаще всего 16bit, посему нежели в будующем потребуется большая, то не забудте указать сие явно через 'L'. C некоторой долей вероятности основываясь на типичных ошибках в реализации макросов на основе которых построено "нечто" можете попробовать: T=(0b10001100) << (8-3);
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 6 2008, 12:12
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 2-01-08
Пользователь №: 33 768

|
Цитата(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, и генерирует для них логический сдвиг.
|
|
|
|
|
Jan 10 2008, 20:22
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
Еще вопрос по С: использовал оператор goto. Сам оператор находится в подпрограмме, метка находится в main(). Компилятор пишет ошибку. Если переношу оператор goto в main(), то все нормально. что за ерунда?
|
|
|
|
|
Jan 10 2008, 22:28
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 2-01-08
Пользователь №: 33 768

|
Цитата(pimen @ Jan 11 2008, 00:22)  Еще вопрос по С: использовал оператор goto. Сам оператор находится в подпрограмме, метка находится в main(). Компилятор пишет ошибку. Если переношу оператор goto в main(), то все нормально. что за ерунда? Так задумано. Если хотите прострелить себе ногу -- прочитайте про setjmp/longjmp, которым такое поведение эмулируется.
|
|
|
|
|
Jan 11 2008, 08:34
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(pimen @ Jan 10 2008, 23:22)  Еще вопрос по С: использовал оператор goto. Сам оператор находится в подпрограмме, метка находится в main(). Это что за издевательство ? Подумайте, что будет со стеком ? PS. Мой Вам совет - забудьте про goto и никогда не вспоминайте .
|
|
|
|
|
Jan 11 2008, 09:35
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
по поводу оператора goto, пользуясь вашими советами, забуду. Подскажите, как корректно переместиться из подпрограммы в main() структура программы приведена ниже:
void hot(void) { //отсюда надо попасть в main() }
void compare(void) if (....) { hot() }
SIGNAL(SIG_OVERFLOW1) { ... compare() ... }
main() { // сюда надо перескочить из hot() }
|
|
|
|
|
Jan 11 2008, 10:34
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(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*#
|
|
|
|
|
Jan 11 2008, 11:42
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 30-11-07
Пользователь №: 32 846

|
Цитата(alexander55 @ Jan 11 2008, 13:34)  Давайте уточним задачу. По некоторому прерыванию SIGNAL(SIG_OVERFLOW1) при выполнении каких-то условий (скажем аварийных), Вы быстро должны произвести какие-то действия в hot() и завершить выполнение прерывания. Так или что-то еще осталось за кадром ? PS. Вспомнил про обсуждения на эту тему http://electronix.ru/forum/index.php?showt...&hl=*goto*#Вы совершенно правильно поняли в hot() происходит выключение источников, потом в main(), пока есть авария (в данном случае перегрев), ждем устранение аварийного фактора, и поехали дальше спасибо за ссылку
|
|
|
|
|
Jan 11 2008, 12:12
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(pimen @ Jan 11 2008, 14:42)  Вы совершенно правильно поняли в hot() происходит выключение источников, потом в main(), пока есть авария (в данном случае перегрев), ждем устранение аварийного фактора, и поехали дальше В main Вы попадете по окончании прерывания без всяких фокусов (причем с корректным стеком). Если Вам надо заблокировать какие-то действия в прерывании, установите флаг аварии при выходе за допустимые пределы и анализируя этот флаг не выполняйте, что не требуется. После устранения аварии этот флаг сбросьте (подозреваю, что он уже существует). Вот и все.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|