Мелкие вопросы по МК и ПЛИС.

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

Сделал светодиодную моргалку на Tiny2313. С завода она поставляется с запущенным встроенным генератором на 4 МГц и делителем на 8. Фьюзы не трогал. Для эффекта мигания циклом for( ; ; ) сделал задержку из 65536 nop'ов (понимаю, не лучший вариант). Расчетное время составило 65536·8/4·10^6 = 0,13 с. На самом деле мигает почти в30 раз медленнее (около 3 с). Где я ошибся?
Аватара пользователя
biDE
Встал на лапы
Сообщения: 84
Зарегистрирован: Пн ноя 12, 2007 20:53:05
Откуда: Одесса

Сообщение biDE »

1. По даташиту частота генератора 8МГц
2. Как вы думаете в цикле кроме nop еще какието операторы есть?
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение smac »

biDE писал(а):1. По даташиту частота генератора 8МГц

Только в состоянии поставки еще и деление на 8 включено, т. е. по идее частота 1 МГц должна быть.
Действительно в цикле наверняка еще куча операторов есть.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение 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; //переход к началу
}
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение 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 и занимает). Подсказка: чтобы получить точные временные интервалы используйте таймер и прерывания (ну или на худой конец полинг флагов таймера).
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

Спасибо.
Для одного кристалла компилятор с Си на ассемблер переводит однозначно (напр., тот же оператор for( ; ; ) в 30 машинных циклов) или по-разному? И можно где-нить посмотреть как будут переведены те или иные функции (кроме скомпилированного .asm файла)?
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение smac »

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

Я не спец в Си, но наверняка код на ассемблере сгенерированный компилятором зависит от оптимизации типа переменных и т. п., т. е. не всегда один и тот же. Посмотреть кроме как в асм листинге вряд-ли возможно (точнее наверное все-же возможно, но сложно довольно и нудно), в общем, пусть меня знатоки поправят.
По-поводу 30 тактов - данное высказывание основано только на вашем эксперименте, я не знаю во сколько тактов выполняется for.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение 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 выглядит, по-крайней мере, смешной :))
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение smac »

Gudd-Head писал(а):Таким образом, на фоне всех этих операций задержка nop выглядит, по-крайней мере, смешной :))

Ну собсно, что и требовалось доказать :). Так что не мучайтесь, берите даташит, настраивайте таймер и в путь.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

Кто-нибудь делал самопальный АЦП на МК у которого нет встроенного АЦП, но есть компаратор и ШИМ? Или есть компаратор, таймер и внешний генератор пилообразного напряжения?
Аватара пользователя
gri
Потрогал лапой паяльник
Сообщения: 336
Зарегистрирован: Чт июн 29, 2006 21:17:41
Откуда: Мариуполь
Контактная информация:

Сообщение gri »

Можно ли в Шаер-порграммере программировать Атмел. Если до, то на какие ноги какие сигналы подавать?
:]\/\/\/\/ххх\/\/\/\/\/\/ххх\/\/\/\/\/ххх\/\/\/\/\/\[:
В мае на гульках 2 баяна порвал...одной лапой.
Другая болела, после того, как потрогал паяльник.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
Inspiron
Встал на лапы
Сообщения: 144
Зарегистрирован: Сб мар 17, 2007 19:38:52
Откуда: Североонежск\Питер
Контактная информация:

Сообщение Inspiron »

Доброго всем времени суток. Может кто подскажет такой вопрос: нужен синтаксис функции rand(), но той. которая работает на AVR. Ну тоесть для стандартного С++ я могу написать:
#include <stdlib>
...........
...........
X=rand(10);
...........
end;
и переменная X будет содержать случайное число в диапазоне от 0 до 10. А как такое же на AVR сделать? Заранее спасибо.
Уважаемые модераторы, сделайте пожалуйста раздел дискотечных примочек и цветомузыки. Уже много тем пылятся в бездне ветки "Умные мысли"
BerZerK-ku
Мучитель микросхем
Сообщения: 492
Зарегистрирован: Вт июл 22, 2008 08:10:54

Сообщение 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).
Аватара пользователя
Digital
Открыл глаза
Сообщения: 78
Зарегистрирован: Сб сен 13, 2008 16:23:09
Откуда: Kaluga
Контактная информация:

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

Сообщение Digital »

Подскажите пожалуйста, как на языке С запрограммировать последовательное чтение элементов массива из X целых чисел и вывод их в один из выводов порта. МК - ATMega16.
Аватара пользователя
mr.Kirill
Мучитель микросхем
Сообщения: 438
Зарегистрирован: Вт сен 25, 2007 19:40:26
Откуда: Челябинск

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

Сообщение 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
Вроде все понятно, комментарии нужны?
Аватара пользователя
Digital
Открыл глаза
Сообщения: 78
Зарегистрирован: Сб сен 13, 2008 16:23:09
Откуда: Kaluga
Контактная информация:

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

Сообщение 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;
}
Аватара пользователя
mr.Kirill
Мучитель микросхем
Сообщения: 438
Зарегистрирован: Вт сен 25, 2007 19:40:26
Откуда: Челябинск

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

Сообщение 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;
}

Для такого случая нужно немного код подкорректировать. Сейчас уже убегаю, занят, если не получится самому сделать, то вечером постараюсь отписаться.
Аватара пользователя
Digital
Открыл глаза
Сообщения: 78
Зарегистрирован: Сб сен 13, 2008 16:23:09
Откуда: Kaluga
Контактная информация:

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

Сообщение Digital »

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

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


Отпишитесь пожалуйста в любом случае. У моего домашнего компьютера с сетью проблемы и получится ли починить на выходных не знаю :(
Последний раз редактировалось Digital Пт дек 05, 2008 15:23:20, всего редактировалось 1 раз.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение 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 имеется одна неприятная особенность - после того, как эта функция отработает, ваш массив окажется обнуленным. так что будьте осторожнее, следуя советам, которые вам дают добрые люди
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

Вернуться в «Разные вопросы по МК»