Страница 38 из 628

Добавлено: Пн ноя 24, 2008 09:45:41
Gudd-Head
Сделал светодиодную моргалку на Tiny2313. С завода она поставляется с запущенным встроенным генератором на 4 МГц и делителем на 8. Фьюзы не трогал. Для эффекта мигания циклом for( ; ; ) сделал задержку из 65536 nop'ов (понимаю, не лучший вариант). Расчетное время составило 65536·8/4·10^6 = 0,13 с. На самом деле мигает почти в30 раз медленнее (около 3 с). Где я ошибся?

Добавлено: Пн ноя 24, 2008 14:40:34
biDE
1. По даташиту частота генератора 8МГц
2. Как вы думаете в цикле кроме nop еще какието операторы есть?

Добавлено: Пн ноя 24, 2008 16:31:20
smac
biDE писал(а):1. По даташиту частота генератора 8МГц
Только в состоянии поставки еще и деление на 8 включено, т. е. по идее частота 1 МГц должна быть.
Действительно в цикле наверняка еще куча операторов есть.

Добавлено: Пн ноя 24, 2008 16:45:19
Gudd-Head
Я по даташиту вычитал, что 4 МГц (+делитель на 8 ). Но все равно - отличие было бы в 2 раза, да и то в быструю сторону.
Вот исходник:
main()
{
#include <iot2313v>
long i;
DDRB = 0x1C; //установили 14...16 ноги на вывод
begin: //начало программы
PORTB = 0x10; //зажгли красный светодиод
for (i=0;i<65535;i++) #asm("nop"); //задержка
PORTB = 0x08; //зажгли желтый светодиод
for (i=0;i<65535;i++) #asm("nop");
PORTB = 0x04; //зажгли зеленый светодиод
for (i=0;i<65535;i++) #asm("nop");
goto begin; //переход к началу
}

Добавлено: Пн ноя 24, 2008 17:28:54
smac
Gudd-Head писал(а):Я по даташиту вычитал, что 4 МГц (+делитель на 8 ). Но все равно - отличие было бы в 2 раза, да и то в быструю сторону.
Вот исходник:
main()
{
#include <iot2313v>
long i;
DDRB = 0x1C; //установили 14...16 ноги на вывод
begin: //начало программы
PORTB = 0x10; //зажгли красный светодиод
for (i=0;i<65535;i++) #asm("nop"); //задержка
PORTB = 0x08; //зажгли желтый светодиод
for (i=0;i<65535;i++) #asm("nop");
PORTB = 0x04; //зажгли зеленый светодиод
for (i=0;i<65535;i++) #asm("nop");
goto begin; //переход к началу
}
а оператор for по вашему сколько тактов занимает, да еще и с long i? (сам отвечу приблизительно тактов 30 и занимает). Подсказка: чтобы получить точные временные интервалы используйте таймер и прерывания (ну или на худой конец полинг флагов таймера).

Добавлено: Пн ноя 24, 2008 18:26:26
Gudd-Head
Спасибо.
Для одного кристалла компилятор с Си на ассемблер переводит однозначно (напр., тот же оператор for( ; ; ) в 30 машинных циклов) или по-разному? И можно где-нить посмотреть как будут переведены те или иные функции (кроме скомпилированного .asm файла)?

Добавлено: Пн ноя 24, 2008 18:50:19
smac
Gudd-Head писал(а):Спасибо.
Для одного кристалла компилятор с Си на ассемблер переводит однозначно (напр., тот же оператор for( ; ; ) в 30 машинных циклов) или по-разному? И можно где-нить посмотреть как будут переведены те или иные функции (кроме скомпилированного .asm файла)?
Я не спец в Си, но наверняка код на ассемблере сгенерированный компилятором зависит от оптимизации типа переменных и т. п., т. е. не всегда один и тот же. Посмотреть кроме как в асм листинге вряд-ли возможно (точнее наверное все-же возможно, но сложно довольно и нудно), в общем, пусть меня знатоки поправят.
По-поводу 30 тактов - данное высказывание основано только на вашем эксперименте, я не знаю во сколько тактов выполняется for.

Добавлено: Пн ноя 24, 2008 19:06:00
Gudd-Head
smac писал(а):По-поводу 30 тактов - данное высказывание основано только на вашем эксперименте, я не знаю во сколько тактов выполняется for.
Кусок из сгенерированного .asm файла:
; 6 begin:
_0x3:
; 7 PORTB = 0x10; //зажгли красный светодиод
LDI R30,LOW(16)
RCALL SUBOPT_0x0
; 8 for (i=0;i<65535;i++) #asm("nop");
_0x5:
RCALL SUBOPT_0x1
BRGE _0x6
nop
RCALL SUBOPT_0x2
RJMP _0x5
_0x6:
; 9 PORTB = 0x08; //зажгли желтый светодиод
/* Если я все правильно понимаю, здесь закомменчены строки Си и приведен их ассемблерный эквивалент с вызовом оптимизированных функций (компилятор работает в режиме оптимизации места), которые находятся в конце файла: */
;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES, CODE SIZE REDUCTION:10 WORDS
SUBOPT_0x0:
STS 56,R30
__CLRD1S 0
RET
;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES, CODE SIZE REDUCTION:18 WORDS
SUBOPT_0x1:
__GETD2S 0
__CPD2N 0xFFFF
RET
;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES, CODE SIZE REDUCTION:20 WORDS
SUBOPT_0x2:
__GETD1S 0
__SUBD1N -1
__PUTD1S 0
RET
Таким образом, на фоне всех этих операций задержка nop выглядит, по-крайней мере, смешной :))

Добавлено: Пн ноя 24, 2008 21:38:42
smac
Gudd-Head писал(а): Таким образом, на фоне всех этих операций задержка nop выглядит, по-крайней мере, смешной :))
Ну собсно, что и требовалось доказать :). Так что не мучайтесь, берите даташит, настраивайте таймер и в путь.

Добавлено: Чт ноя 27, 2008 09:53:20
Gudd-Head
Кто-нибудь делал самопальный АЦП на МК у которого нет встроенного АЦП, но есть компаратор и ШИМ? Или есть компаратор, таймер и внешний генератор пилообразного напряжения?

Добавлено: Сб ноя 29, 2008 02:03:50
gri
Можно ли в Шаер-порграммере программировать Атмел. Если до, то на какие ноги какие сигналы подавать?

Добавлено: Вт дек 02, 2008 20:34:31
ARV
Gudd-Head писал(а):Кто-нибудь делал самопальный АЦП на МК у которого нет встроенного АЦП, но есть компаратор и ШИМ? Или есть компаратор, таймер и внешний генератор пилообразного напряжения?
ну, допустим, я делал. и что? встроенный ШИМ не обязателен для этого.

Добавлено: Ср дек 03, 2008 03:40:28
Inspiron
Доброго всем времени суток. Может кто подскажет такой вопрос: нужен синтаксис функции rand(), но той. которая работает на AVR. Ну тоесть для стандартного С++ я могу написать:
#include <stdlib>
...........
...........
X=rand(10);
...........
end;
и переменная X будет содержать случайное число в диапазоне от 0 до 10. А как такое же на AVR сделать? Заранее спасибо.

Добавлено: Ср дек 03, 2008 07:52:04
BerZerK-ku
Inspiron писал(а):Доброго всем времени суток. Может кто подскажет такой вопрос: нужен синтаксис функции rand(), но той. которая работает на AVR. Ну тоесть для стандартного С++ я могу написать:
#include <stdlib>
...........
...........
X=rand(10);
...........
end;
и переменная X будет содержать случайное число в диапазоне от 0 до 10. А как такое же на AVR сделать? Заранее спасибо.
В библиотеке stdlib.h идущей с IAR находится функция int rand(void) и #define RAND_MAX 0x7FFF (тоже самое и в WinAVR). Судя по логике, изменив rand_max можно было бы задать максимальное значение, но наделе этого не произошло. В таком случае можно просто воспользоваться подобными преобразованиями: rand()&0x07 (число от 0 до 7), rand()%11 (число от 0 до 10).

Различные мелкие вопросы

Добавлено: Пт дек 05, 2008 08:32:19
Digital
Подскажите пожалуйста, как на языке С запрограммировать последовательное чтение элементов массива из X целых чисел и вывод их в один из выводов порта. МК - ATMega16.

Re: Различные мелкие вопросы

Добавлено: Пт дек 05, 2008 09:07:03
mr.Kirill
Digital писал(а):Подскажите пожалуйста, как на языке С запрограммировать последовательное чтение элементов массива из X целых чисел и вывод их в один из выводов порта. МК - ATMega16.
Например вот так

Код: Выделить всё


void send_data(unsigned char *data, unsigned char n)
{
char i;
char j;

for (j=0;j<n;j++)
        {
        for(i=0;i<8;i++)
                {	  
                if ((data[j] & 0x80) == 0x80)
                        {
                          PORTD.0=1;
                        }
                else
                        {
                          PORTD.0=0;
                        }
                data[j]=data[j]<<1;
                }
        }
}

Код для CodeVisionAVR
Вроде все понятно, комментарии нужны?

Различные мелкие вопросы

Добавлено: Пт дек 05, 2008 12:35:14
Digital
Да, пожалуйста, откомментируйте. Не понял как свой массив прикрутить к этому коду.
Строка if ((data[j] & 0x80) == 0x80), к примеру, что делает непонятно и почему переменная i ограничивается значением <8?

Мне надо к примеру выдавать в порт данные из массива (по прерыванию - переполнение таймера), т.е. первое прерывание - начальный элемент массива, второе - следующий и т.д.:

flash unsigned char array[16]={
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00
};

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTB.4=элемент_из_массива_array;
}

Re: Различные мелкие вопросы

Добавлено: Пт дек 05, 2008 14:48:06
mr.Kirill
Digital писал(а):Да, пожалуйста, откомментируйте. Не понял как свой массив прикрутить к этому коду.
Строка if ((data[j] & 0x80) == 0x80), к примеру, что делает непонятно и почему переменная i ограничивается значением <8?
Эта строка "смотрит" на старший бит (0x80 = 0b10000000) элемента массива и смотря что на нем та часть кода и выполняется, т.е. выставляется на порту либо 1, либо 0. Так пробежав 8 раз (число бит в байте, потому i ограничено 8мью) на выходном пине получится последовательность нулей и единиц, которая соответствует числу этого элемента массива.
Мне надо к примеру выдавать в порт данные из массива (по прерыванию - переполнение таймера), т.е. первое прерывание - начальный элемент массива, второе - следующий и т.д.:

flash unsigned char array[16]={
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00
};
чтобы вывести все элементы массива сразу то будет вот так запись
void send_data(array, 16);
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTB.4=элемент_из_массива_array;
}
Для такого случая нужно немного код подкорректировать. Сейчас уже убегаю, занят, если не получится самому сделать, то вечером постараюсь отписаться.

Re: Различные мелкие вопросы

Добавлено: Пт дек 05, 2008 15:18:10
Digital
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTB.4=элемент_из_массива_array;

Для такого случая нужно немного код подкорректировать. Сейчас уже убегаю, занят, если не получится самому сделать, то вечером постараюсь отписаться.
}
Отпишитесь пожалуйста в любом случае. У моего домашнего компьютера с сетью проблемы и получится ли починить на выходных не знаю :(

Re: Различные мелкие вопросы

Добавлено: Пт дек 05, 2008 15:23:14
ARV
Digital писал(а):Да, пожалуйста, откомментируйте. Не понял как свой массив прикрутить к этому коду.
Строка if ((data[j] & 0x80) == 0x80), к примеру, что делает непонятно и почему переменная i ограничивается значением <8?
вполне можно заменить на строку

Код: Выделить всё

if (data[j] & 0x80)
эффект тот же
Мне надо к примеру выдавать в порт данные из массива (по прерыванию - переполнение таймера), т.е. первое прерывание - начальный элемент массива, второе - следующий и т.д.:

flash unsigned char array[16]={
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00
};
чтобы по прерыванию вывести ваш массив последовательно, можно сделать такой обработчик прерывания таймера:

Код: Выделить всё

// Timer 0 overflow interrupt service routine 
interrupt [TIM0_OVF] void timer0_ovf_isr(void) { 
// в подпрограмме-обработчике выводится 1 байт за прерывание 
// из глобального массива data[16]. байты выводятся от МЛАДШЕГО бита к СТАРШЕМУ
char i, ch = 0x01; 
static char j=0; 

   if(j++ < 16)
         for(i=0; i<8; i++) {     
                if (data[j] & ch) 
                          PORTD.0=1; 
                else 
                          PORTD.0=0; 
                ch <<= 1;
        } 
} 
вопрос лишь в том, поможет ли использование готового кода вам чему-то научиться, или нет...

P.S. в приведенном ранее примере функции send_data имеется одна неприятная особенность - после того, как эта функция отработает, ваш массив окажется обнуленным. так что будьте осторожнее, следуя советам, которые вам дают добрые люди