Мелкие вопросы по МК и ПЛИС.
- Gudd-Head
- Друг Кота
- Сообщения: 20091
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Сделал светодиодную моргалку на Tiny2313. С завода она поставляется с запущенным встроенным генератором на 4 МГц и делителем на 8. Фьюзы не трогал. Для эффекта мигания циклом for( ; ; ) сделал задержку из 65536 nop'ов (понимаю, не лучший вариант). Расчетное время составило 65536·8/4·10^6 = 0,13 с. На самом деле мигает почти в30 раз медленнее (около 3 с). Где я ошибся?
- Gudd-Head
- Друг Кота
- Сообщения: 20091
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Я по даташиту вычитал, что 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; //переход к началу
}
Вот исходник:
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; //переход к началу
}
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 писал(а):Спасибо.
Для одного кристалла компилятор с Си на ассемблер переводит однозначно (напр., тот же оператор for( ; ; ) в 30 машинных циклов) или по-разному? И можно где-нить посмотреть как будут переведены те или иные функции (кроме скомпилированного .asm файла)?
Я не спец в Си, но наверняка код на ассемблере сгенерированный компилятором зависит от оптимизации типа переменных и т. п., т. е. не всегда один и тот же. Посмотреть кроме как в асм листинге вряд-ли возможно (точнее наверное все-же возможно, но сложно довольно и нудно), в общем, пусть меня знатоки поправят.
По-поводу 30 тактов - данное высказывание основано только на вашем эксперименте, я не знаю во сколько тактов выполняется for.
- Gudd-Head
- Друг Кота
- Сообщения: 20091
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
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 выглядит, по-крайней мере, смешной
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
ну, допустим, я делал. и что? встроенный ШИМ не обязателен для этого.Gudd-Head писал(а):Кто-нибудь делал самопальный АЦП на МК у которого нет встроенного АЦП, но есть компаратор и ШИМ? Или есть компаратор, таймер и внешний генератор пилообразного напряжения?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Inspiron
- Встал на лапы
- Сообщения: 144
- Зарегистрирован: Сб мар 17, 2007 19:38:52
- Откуда: Североонежск\Питер
- Контактная информация:
Доброго всем времени суток. Может кто подскажет такой вопрос: нужен синтаксис функции rand(), но той. которая работает на AVR. Ну тоесть для стандартного С++ я могу написать:
#include <stdlib>
...........
...........
X=rand(10);
...........
end;
и переменная X будет содержать случайное число в диапазоне от 0 до 10. А как такое же на AVR сделать? Заранее спасибо.
#include <stdlib>
...........
...........
X=rand(10);
...........
end;
и переменная X будет содержать случайное число в диапазоне от 0 до 10. А как такое же на AVR сделать? Заранее спасибо.
Уважаемые модераторы, сделайте пожалуйста раздел дискотечных примочек и цветомузыки. Уже много тем пылятся в бездне ветки "Умные мысли"
-
BerZerK-ku
- Мучитель микросхем
- Сообщения: 492
- Зарегистрирован: Вт июл 22, 2008 08:10:54
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
- Контактная информация:
Различные мелкие вопросы
Подскажите пожалуйста, как на языке С запрограммировать последовательное чтение элементов массива из X целых чисел и вывод их в один из выводов порта. МК - ATMega16.
- mr.Kirill
- Мучитель микросхем
- Сообщения: 438
- Зарегистрирован: Вт сен 25, 2007 19:40:26
- Откуда: Челябинск
Re: Различные мелкие вопросы
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
- Контактная информация:
Различные мелкие вопросы
Да, пожалуйста, откомментируйте. Не понял как свой массив прикрутить к этому коду.
Строка 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;
}
Строка 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: Различные мелкие вопросы
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: Различные мелкие вопросы
// 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: Различные мелкие вопросы
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 имеется одна неприятная особенность - после того, как эта функция отработает, ваш массив окажется обнуленным. так что будьте осторожнее, следуя советам, которые вам дают добрые люди
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!