Перейти к содержанию
    

alexeyv

Участник
  • Постов

    298
  • Зарегистрирован

  • Посещение

Весь контент alexeyv


  1. Где-то примерно так: #include <avr/io.h> #include <stdio.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/signal.h> volatile unsigned int ADCCompare_new =0; volatile unsigned int ADCCompare_old =0; #define SETBIT(x,y) (x|=(1<<y)) #define CLRBIT(x,y) (x&=~(1<<y)) #define INVBIT(x,y) (x^=(1<<y)) #define CHKBIT(x,y) (x&(1<<y)) #define BITON(x,y) (x&(1<<y)) #define BITOFF(x,y) (!(x&(1<<y))) ISR(TIMER1_COMPA_vect) { INVBIT(PORTB,PB1);// INVBIT(PORTB,PB0);// if(ADCCompare_new != ADCCompare_old) { OCR1A = ADCCompare_old = ADCCompare_new; } } int main(void) { cli(); // Init TC1 - CTC Mode TCCR1A = 0; TCCR1B = (1<<WGM12) | (1<<CS10); OCR1A = 510; TCNT1 = 0; TIMSK = (1<<OCIE1A); // Init ADC SFIOR=0; ADCSRA = (1<<ADEN)|(0<<ADSC)|(0<<ADATE)|(0<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); ADMUX=1; //vibor vhoda // Init Port's DDRA=0x00; //in DDRB=0xff; //out DDRC=0xff; //out DDRD=0x00; //in PORTA=0x00; PORTB=0x01; PORTC=0x00; PORTD=0x00; TIFR = 0xFF; sei(); while(1) { _delay_ms(1000); ADCSRA |= (1<<ADSC); // Start ADC Conversion while((ADCSRA & (1<<ADIF)) != 0x10);// Wait till conversion is complete ADCCompare_new = 510 - (ADC/3); // Read the ADC Result ADCSRA |= (1 << ADIF); // Clear ADC Conversion Interrupt Flag } }
  2. Делаю также как и defunct. Тут на форуме недавно была ветка. Поизучай
  3. Формула должна управлять выходной частотой для динамика, а не рабочей частотой от которой работает АЦП - не путайте понятия!! Не верю. Жаль мне сейчас не на чем проверить. Это всего лишь эквивалентные преобразования. Это надо сделать ДЛЯ того что бы программа заработала, причем правильно!! По поводу ролика: Какой режим оптимизации включен? При включенной оптимизации компилятор как раз выкинет все ваши присваивания и приведет все к виду: TCNT1 = 65035 + _function_divide(ADC,3); переменная ADCCompare также выкинется как лишняя. Замечания по поводу алгоритма 1. Зачем вообще так часто сканировать номинал резистора или он быстро меняется. Достаточно это делать раз в секунду. Причем в Single-mode. Делать это в главном цикле в задержкой в 1 сек и ожиданием окончания конверсии после старта 2. Согласен с Палыч'ем - необходимо использовать тайммер в СТС режиме. В прерывании от него необходимо проверять не изменилось ли значение резистора и только после этого менять период работа таймера. Не изменилось - пусть себе дальше пашет. Использование ОС1х - не обязательно, надо смотреть как у Вас все подлючено и можно ли перебросить выводы.
  4. Если нужна только целая часть квадратного корня, то можно воспользоваться другим алгоритмом: Для квадратов чисел верны следующие равенства: 1 = 1^2 1+3 = 2^2 1+3+5 = 3^2 и так далее. То есть, узнать целую часть квадратного корня числа можно, вычитая из него все нечётные числа по порядку, пока остаток не станет меньше следующего вычитаемого числа или равен нулю, и посчитав количество выполненных действий. Например, так: Выполнено 3 действия, квадратный корень числа 9 равен 3. Недостатком такого способа является то, что если извлекаемый корень не является целым числом, то можно узнать только его целую часть, но не точнее. В то же время такой способ вполне доступен детям, решающим простейшие математические задачи, требующие извлечения квадратного корня. Циклов конечно будет больше, зато время их выполнения гораздо меньше
  5. 1. Если FCPU =16МГц, то необходимо поставить делитель АЦП равным 128 (тактовая на АЦП будет 125КГц) 2. Странно!! А у меня получилось FF58. Объясните мне разницу между TCNT1 = 65535 - 500 + ADC/3; и ADCCompare=ADC; ADCCompare=ADCCompare/3; ADCCompare=500-ADCCompare; TCNT1=65535-ADCCompare; 3. Где опрос флага ADIF и его сброс? Ваша проблема понятна - Вы считываете данные с АЦП тогда, когда еще нет точного результата конверсии 4. Для проверки алгоритма поставьте несколько констант вместо считывания с АЦП и проверьте зависимость выхода(частоты) от констант. Если на выходе будет нужная частота, то проблема в считывании показаний с АЦП. Также, если есть к-либо отладочный порт (USART), можете вывести значения АЦП на ПК и посмотреть как они считываются/изменяются. 5. Если у вас задержки порядка секунды, зачем запускать АЦП во Free Runing? По окончании задержки запустите в одиночном измерении и дождитесь окончании конверсии
  6. 1. Какой чип? 2. Какая тактовая частота? В даташите написано тактовая на АЦП д.б. 50...200кГц, а у Вас делитель на 2. 3. Зачем постоянно выбираете 1-й канал? Одного раза разве не достаточно? 4. Так наверное будет и понятнее и проще: ADMUX=1; while(1) { if(a) continue; a=1; TCNT1 = 65535 - 500 + ADC/3; _delay_ms(1000); } 5. А разве не надо опрашивать флаг ADIF что бы узнать об окончании конверсии?
  7. To develsnik: Если по нажатию кнопок, Вы хотите не только зажигать светодиодики, но и выполнять какие-либо другие действия, то подумайте об устранении дребезга с кнопок
  8. А в проекте есть sd_driver.c ?? Если нет, то надо добавить однако!
  9. Порядок_байтов Аналогов среды CCS не знаю.
  10. Как так?

    1. Какова разрядность переменных x и k ? И вообще их определение 2. Как часто вызывается код? 3. Где flag устанавливается и как часто?
  11. У меня такое было раньше. Попробуй отказаться от использования "я" в комментариях. Полазь по форуму и найди прогу FuckYa.exe. Поставь ее запуск перед компиляциеей проекта и она будет заменять "я" на "Я". PS. Или попытайся отключить "ToolTip variable watching" в Editor Properties. Или "Parser Selection" = "None" в "Language/Code Sense" точно не помню.
  12. 1. Определитесь с терминологией: массив указателей на метки или массив указателей на функции ?! 2. В случае массива с указателями на функции: // количество обработчиков #define N_FUNC 16 // тип функции-обработчика typedef void(TypFunc)(void); // прототипы обработчиков для массива TypFunc f1; TypFunc f2; ... TypFunc f16; // сам массив указателей TypFunc * mas_func[N_FUNC] = {f1,f2,.....,f16}; unsigned int nfunc; // индекс функции-обработчика void main (void) { ... // необходимым вам образом вычисляете nfunc ... if(nfunc < N_FUNC) mas_func[nfunc](); // вызов необходимого обработчика ... } TypFunc f1 {...} ... TypFunc f16 {...} Код ДОЛЖЕН работать на любом Си, в том числе и стандартном, т.к. здесь нет никагого противоречия со стандартом. Проверял на нескольких разных компиляторах/платформах 3. Реализацию с метками описал maksimp. Хотя с я все же не совсем согласен 4. На чем и как написаны эти низкоуровневые обработчики? На асме или на Си? Если на Си или асме в виде отдельных функций, то "goto" использовать нельзя, т.к. будет использоваться пролог одной функции, а эпилог другой, и они скорее всего будут не симетричные. Если обработчики - это куски кода, то проще использовать "switch-case". Некоторые компиляторы сами оптимизируют такой программый код под вызод функций (при этом создается секция .switch, хранящая переходы оператора).
  13. Ага,клавиша "+" располагается удобнее на клавиатуре, или клавишу "|" заело.
  14. То биш, работаю я нормально в операционке и вдруг мне (или не мне, но с помощью меня) понадобилось поработать с устройством с неподписаным драйвером. Для этого я должен закончить всю свою работу, сохраниться, закрыть порядка десятка приложений, записать текущее состояние работы, ПЕРЕГРУЗИТЬСЯ, нажать Ф8, поработать с этим устройством, потом опять перегрузиться, восстановить прежнее состояние. И так, возможно, несколько раз за рабочий день!! Не слишком накладно ?!? Лучше один раз сделать нормально и не знать хлопот.
  15. Я вчера устанавливал драйвера AS-4 под Win7-64. Там в программаторе как раз установлена микруха CP2102 Silicon Labs, но только с измененным Device_PID (c 0xEA60 на 0x8066). По приведенной ими инструкции мне пришлось поменять Device_PID обратно на 0xEA60, а потом (после перезагрузки) установить оригинальные драйвера от Silicon Labs с цифровой подписью. Эти дрова Винда сразу приняла. Ссылки: http://as-kit.ru/AS-tools.soft/asisp/Silabs_win_XP_win7.zip http://as-kit.ru/AS-tools.soft/asisp_soft.html Посмотрите, может поможет...... З.Ы. Win7-64 не устанавливает (а если и установит, то не включает) драйвера без цифровой подписи. Мне раньше приходилось такие устройства подключать не в Win7-64, а в режиме XP, который есть там.
  16. Я это и имел ввиду. Забыл уточнить тип памяти
  17. Создай свои - не так уж и сложно. Использование printf() - слишком уж тормозной и memory-потребляющий способ.
  18. Прототип функции - это объявление функции перед ее вызовом, для того чтобы компилятор мог правильно проверить типы параметров и возвращаемого значения функции. Обычно записывается в *.h и подключается include'ом в начале *.c-файла в котором используется, но можно указать и явно в начале файла: #include <stdio.h> int power(int m, int n); /* тестирование power - функции возведения в степень */ main() { int i; for (i = 0; i < 10; ++i) printf("%d %d %d\n", i, power(2,i), power(-3,i)); return 0; } /* power: возводит base в п-ю степень; n >= 0 */ int power(int base, int n) { int i, p; P = 1; for (i = 1; i <= n; ++i) p = p * base; return p; } Перед функцией main можно заметить такую строку: int power(int m, int n); Она сообщает, что power является функцией с двумя аргументами типа int, возвращающей также значение типа int. Эта декларация называется прототипом функции и обязана согласовываться по форме как с определением (заголовком) функции power, так и с любыми ее вызовами. Если определение функции отличается от ее прототипа или формы вызова, возникает ошибка. Имена параметров согласовывать не обязательно. Вообще-то не обязательно даже указывать имена параметров в прототипе функции, поэтому предыдущий прототип можно было бы записать так: int power(int, int); Однако хорошо выбранные имена являются своеобразной документацией к программе, так что они будут часто использоваться. Опция компилятора --require_prototypes, заставляет в обязательном порядке всем функциям иметь прототипы, иначе он выдаст ошибку Прототип функции прерывания - как и у всех остальных функций interrupt void dmaXmtIsr(void); /// <--- прототип функции ....... void main (void) { ...... } ...... interrupt void dmaXmtIsr(void) { ...... ............. } Подробнее - в книге Керигана/Ричи, откуда и были взяты примеры.
  19. Различных бутлоадеров для АВР в сети дофига и даже на сайте Атмела есть. Реализация WAKE Для АВР на асме и на Си-ИАР есть, например, на http://caxapa.ru/lib/wake/ Объединить два проекта в один (загрузчик + транспортный уровень для него) - дело максимум двух дней.
  20. 1. RAMPX, RAMPY - тоже самое, что и RAMPZ, с инструкциями LD/LDD/ST/STD - для доступа к SRAM памяти >64К при косвенной адресации ldi r29,$05 ldi r28,$00 ld r2,Y+ Т.е. если RAMPY=0, то будет прочитана ячейка $500, если RAMPY=1, то будет прочитана ячейка $10500 При ресете RAMPZ=RAMPY=RAMPX=0 - то есть указывают на нижние 64К 2. Отличие RAMPZ, от RAMPX и RAMPY - в том что RAMPZ:Z используется в инструкциях ELPM/SPM для доступа к Flash-памяти ldi ZL, byte3(Table_1<<1); Initialize Z-pointer out RAMPZ, ZL ldi ZH, byte2(Table_1<<1) ldi ZL, byte1(Table_1<<1) elpm r16, Z+; Load constant from Program ; memory pointed to by RAMPZ:Z (Z is r31:r30) Здесь можно использовать только RAMPZ:Z 3. RAMPD - аналогично, но с инструкциями LDS/STS для прямой адресации lds r2,$400 Т.е. если RAMPD=0, то будет прочитана ячейка $400, если RAMPD=2, то будет прочитана ячейка $20400 При ресете RAMPD=0 - то есть указывает на нижние 64К 4. есть еще EIND (Extended Indirect Register) - предлагаю с ним разобраться самому в качестве домашнего задания P.S. Если интерфейса внешней памяти у кристалла нет, то инструкции скорее всего не отработают. Хотя регистры скорее всего есть, т.к. ядро у семейств А1,А3 и А4 одно и тоже
  21. 1. pm не используется для вызова подпрограм. Для вызова подпрограмм используются команды CALL/ICALL/EICALL/RCALL. pm() - program memory, макрос просто умножает параметр на 2. Дело в том, что ОЗУ у AVR адресуется байтово, а flash-память словарно, и адреса всех объектов, лежащих во flash-памяти являются словарными. Поэтому что бы из словарного адреса получить байтовый (для доступа к любому байту flash-памяти), необходимо умножить на 2, или сдвинуть на 1 влево. Доступ к flash-памяти: ldi ZH, high(Table_1<<1) ; Initialize Z pointer ldi ZL, low(Table_1<<1) lpm r16, Z+ ; Load constant from program Low-adress + increment Z lpm r16, Z ; Load constant from program High-adress 2. call Z - нет такой команды, есть icall. И насколько я помню при загрузке ZH:ZL для команды icall, сдвигать адрес не надо. Косвенный вызов функции: ldi ZH, high(func) ; Initialize Z pointer ldi ZL, low(func) icall ; Load constant from program
  22. В стандартной библиотеке Си есть файл setjmp.h, объявляющий макросы и тип данных для нелокальных переходов. Посмотри, может тебе это подойдет.
  23. 1. Поверьте мне - GCC НЕ ВСЕ ЭТО сделает сам, в нем заложены только типичные алгоритмы, которые впрочем постоянно расширяются и периодически обновляются. 2. Мои высказывания относятся ко всем компиляторам, а не только к GCC. И если писать сразу отпимизировано, то не надо будет думать, что "я это делать не буду - это компилятор САМ прооптимизирует", а потом локти себе кусать. Это путь к деградации, если думать что за тебя все сделает компилятор/оптимизатор. 3. -О3 конечно хорошо, но когда идет отладка, то -О3 отключаешь, и как раз в этот момент не хватает - то оперативки, то флеша, то быстродействия......... (если конечно при проектировании не заложили запас, а все сделали в притык, как часто бывает)
×
×
  • Создать...