|
|
| ||||||||
|
|
|
|
221665
119
0
0
|
|
Опции темы | Поиск в этой теме |
|
|
41
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
А функция часом не inline определена?
|
|
|
|
|
|
42
|
|
Завсегдатай Фонарёвки
|
Код:
void spi_init(){
/* Set MOSI and SCK output */
PORTB = PORTB | (1<<3)|(1<<5);
/* Enable SPI, Master, set clock rate fck/4 */
SPCR = (1<<SPE)|(1<<MSTR);
}
void spi_send(char cData){
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF))){}
}
|
|
|
|
|
|
43
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Странно. Такое поведение, характерно для функций, определенных как
inline void spi_send(char cData) { } А определение ранее есть? т.е. такая строчка void spi_send(char cData); Я правда с winavr не работал, всех его заморочек не знаю. Возможно функции без определения он вставляет как inline |
|
|
|
|
|
44
|
|
|
Завсегдатай Фонарёвки
|
C оптимизациями -O0 и -O1 он генерирует правильно, и функции вызывает через rcall.
С -O1 прошивка получается меньше, чем с -O2 ![]() С -O2, -O3 и -Os он начинает разбрасываться так, как я написал... Цитата:
Код:
spi_send(255); spi_send(255); spi_send(255); spi_send(255); Код:
void spi_send(char cData){
/* Start transmission */
SPDR = cData;
78: 9f ef ldi r25, 0xFF ; 255
7a: 9e bd out 0x2e, r25 ; 46
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF))){}
7c: 0d b4 in r0, 0x2d ; 45
7e: 07 fe sbrs r0, 7
80: fd cf rjmp .-6 ; 0x7c <lcd_clear+0x6>
SPCR = (1<<SPE)|(1<<MSTR);
}
void spi_send(char cData){
/* Start transmission */
SPDR = cData;
82: 9e bd out 0x2e, r25 ; 46
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF))){}
84: 0d b4 in r0, 0x2d ; 45
86: 07 fe sbrs r0, 7
88: fd cf rjmp .-6 ; 0x84 <lcd_clear+0xe>
SPCR = (1<<SPE)|(1<<MSTR);
}
void spi_send(char cData){
/* Start transmission */
SPDR = cData;
8a: 9e bd out 0x2e, r25 ; 46
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF))){}
8c: 0d b4 in r0, 0x2d ; 45
8e: 07 fe sbrs r0, 7
90: fd cf rjmp .-6 ; 0x8c <lcd_clear+0x16>
SPCR = (1<<SPE)|(1<<MSTR);
}
void spi_send(char cData){
/* Start transmission */
SPDR = cData;
92: 9e bd out 0x2e, r25 ; 46
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF))){}
94: 0d b4 in r0, 0x2d ; 45
96: 07 fe sbrs r0, 7
98: fd cf rjmp .-6 ; 0x94 <lcd_clear+0x1e>
spi_send(0b1000000); // Y (0...5)
PORTB=PORTB | (1<<2); //LCD_D=1
}
|
|
|
|
|
|
|
45
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Он не разбрасывается, а оптимизирует по скорости
|
|
|
|
|
|
46
|
|
|
Завсегдатай Фонарёвки
|
А как ему обьяснить, что память у мк дорогая, это вам не комп с метрами и гектарами?
![]() По идее, -Os должен оптимизировать для рамера. А он тоже "для скорости"... Дождаться бы Gall... Любителя -O2 и пророчащего, что Цитата:
|
|
|
|
|
|
|
47
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Так у тебя свободной памяти небось вагон, вот он скорость и выжимает
|
|
|
|
|
|
48
|
|
Завсегдатай Фонарёвки
|
Ну да, я только начал писать... Но я хочу с самого начала контролировать, что получается
Потому как в итоге программа будет сложной - может даже и не влезть.Или gcc так и будет выжимать скорость, пока петух не клюнет в обьём памяти?
|
|
|
|
|
|
49
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Какой смысл тогда в выборе оптимизации, если компилятор всё равно делает по-своему?..
|
|
|
|
|
|
50
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
да хто-ж его знает, у меня ICCAVR - асбсолютно тупой послушный компилятор
|
|
|
|
|
51
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Оптимизация -O2 - это оптимизация по скорости. Компилятор замечает, что вписать код функции прямо вместо ее вызова экономит пару тактов по сравнению с инструкцией CALL - и делает это.
Для микроконтроллеров лучше использовать опцию -Os, можно вместе с опцией -fcall-prologues. |
|
|
|
|
|
52
|
||
|
Завсегдатай Фонарёвки
|
Цитата:
Цитата:
Наверное -mcall-prologues Нет, всё равно не помогает! -Os -mcall-prologues всё равно вписывает функции прямо в место вызова Я так понимаю, надо более конкретно смотреть, какие оптимизации включают -Os и -O2, но не включает -O1... |
||
|
|
|
|
53
|
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
Опция -Os НЕ дает "самый маленький" размер. Дело в том, что в большой программе вписывание функций инлайном в конечном итоге УМЕНЬШАЕТ общий размер кода. Это происходит потому, что при этом удается применить межпроцедурную оптимизацию - удалить лишние ldi, например. Написанный отдельно дубликат функции на этапе линковки будет вырезан из прошивки, если в программе не найдется ни одного call на него. Подавить его создание полностью можно, объявив функцию как static inline. Если очень хочется, чтобы функции не инлайнились, есть опция -fno-inline. |
|
|
|
|
|
|
54
|
|
|
Завсегдатай Фонарёвки
|
Помогло! Добавил -fno-inline, получилась прошивка 176 байт вместо 230
![]() Цитата:
|
|
|
|
|
|
|
55
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Переписываю и я сейчас программу на Си (RGB индикатор). Что-то меня эта оптимизация совсем не устраивает. Мало того что я не могу нормально выйти из прерывания (ему хочется сначала попрыгать туда-сюда), так ещё и обработчик меня серьёзно напугал. Вот что нужно было сделать:
Код:
ISR (TIM0_COMPA_vect)
{
PORTA &= 0b11001111;
}
Код:
compA0: in R16, PORTA ;Потушить все каналы andi R16, 0b11001111 out PORTA, R16 reti Код:
ISR (TIM0_COMPA_vect)
{
d2: 1f 92 push r1
d4: 0f 92 push r0
d6: 0f b6 in r0, 0x3f ; 63
d8: 0f 92 push r0
da: 11 24 eor r1, r1
dc: 8f 93 push r24
PORTA &= 0b11001111;
de: 8b b3 in r24, 0x1b ; 27
e0: 8f 7c andi r24, 0xCF ; 207
e2: 8b bb out 0x1b, r24 ; 27
}
e4: 8f 91 pop r24
e6: 0f 90 pop r0
e8: 0f be out 0x3f, r0 ; 63
ea: 0f 90 pop r0
ec: 1f 90 pop r1
ee: 18 95 reti
Ещё я объявил глобальные переменные, свободных регистров ещё вагон, а он полез в ОЗУ. Зачем?.. И это на фоне довольно неплохой оптимизации более сложных вещей. Слип он нормально мне написал. Правда я конфигурирую всё равно ковыряясь в регистрах, не доверяю этим библиотекам. Он они что творят... Добавлено... Код:
ISR (TIM0_COMPA_vect, ISR_NAKED)
{
PORTA &= 0b11001111;
d2: 8b b3 in r24, 0x1b ; 27
d4: 8f 7c andi r24, 0xCF ; 207
d6: 8b bb out 0x1b, r24 ; 27
reti ();
d8: 18 95 reti
Добавлено... Забросил затею. Мозги мои не заточены под логику этого языка. Программа разрастается в жуткие запутывающие условия. К ассемблеру уже привык. Очень послушный и понятный язык. Писать больше, но мозг кипит меньше. Может вернусь к затее когда понадобится написать большую программу, но пока что 2 килобайта ассемблерного кода меня пугают меньше Си... |
|
|
|
|
|
56
|
|
Ветеран Фонарёвки
|
Осилил кучу флуда и расборок по поводу "чья кочка зеленее" и возник вопрос...
А где продолжение обучения? К примеру я хотел бы увидеть как генерировать шым (на микроконтроллерах в которых он есть и так понятно а если нету, свою то функцию я напишу, но так как начинающий то не думаю что она будет оптимальной) И еще хотелось бы научиться шаговым движком рулить... в интернете примеры есть, но не всегда то что нужно или не всегда понятно. К тому же разные люди по разному объясняют. |
|
|
|
|
57
|
|
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 179
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Генерирование ШИМ программно
Идея очень проста, поэтому достаточно написать пример кода. Код:
while (1) {
PORTB = 0xFF;
delay(x);
PORTB = 0x00;
delay(k - x);
}
Функция delay может быть описана, например, так: Код:
void delay(unsigned n) {
for (unsigned i = 0; i < n; ++i) { asm volatile ("nop"); }
}
|
|
|
|
|
|
58
|
|
Завсегдатай Фонарёвки
|
Gall Расскажи, как вообще в Си принято работать со строками. Для меня, после пхп, работать с "массивом букв" - это кошмар
(если знаешь пхп - поймёшь всю суть моих страданий ).Например, как можно короче записать этот код? Условия: 1. не занимать больше флеша, чем этот пример 2. не занимать больше озу, чем этот пример 3. записать компактнее ![]() char lcd[84] - промежуточный буффер, где находится полный текст, который должен выводиться на дисплей. В разных местах кода требуется менять лишь отдельные его фрагменты, например: Код:
switch(input){
case(INPUT_DISABLE):
lcd[10]='[';
lcd[11]='F';
lcd[12]='M';
lcd[13]='T';
lcd[14]='R';
lcd[15]=' ';
lcd[16]='o';
lcd[17]='f';
lcd[18]='f';
lcd[19]=']';
return;
case(INPUT_DIRECT):
lcd[10]='[';
lcd[11]='8';
lcd[12]='M';
lcd[13]='H';
lcd[14]='z';
lcd[15]=']';
lcd[16]=' ';
lcd[17]=' ';
lcd[18]=' ';
lcd[19]=' ';
return;
case(INPUT_LOGIC):
lcd[10]='[';
lcd[11]='8';
lcd[12]='M';
lcd[13]='H';
lcd[14]='z';
lcd[15]=' ';
lcd[16]='L';
lcd[17]='O';
lcd[18]='G';
lcd[19]=']';
return;
case(INPUT_DIV16):
lcd[10]='[';
lcd[11]='1';
lcd[12]='2';
lcd[13]='8';
lcd[14]='M';
lcd[15]='H';
lcd[16]='z';
lcd[17]=']';
lcd[18]=' ';
lcd[19]=' ';
return;
case(INPUT_DIV128):
lcd[10]='[';
lcd[11]='1';
lcd[12]='.';
lcd[13]='1';
lcd[14]='G';
lcd[15]='H';
lcd[16]='z';
lcd[17]=']';
lcd[18]=' ';
lcd[19]=' ';
return;
}
|
|
|
|
|
|
59
|
|
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
например так:
_flash char str[][11]={"строка 1", "вторая","и тд." }; . case INPUT_DISABLE: memcpy(lcd+10, str[0], 10); .... case ... на строки при таком описании уйдет на 1 байт больше, из-за нуля в конце, но удобнее писать. А код сократиться. |
|
|
|
|
|
60
|
|
Ветеран Фонарёвки
|
Ну допустим аппаратный шим есть, но на 2х каналах а надо 4 разных на 4 при этом на всех 4х каналах должен шим быть разным, к примеру есть у меня 4 светодиодных линейки и яркость каждой мне нжно регулировать отдельно при этом в реальном времени в зависимости от определенных параметров, управление с компа или изменение входного сигнала - не суть важно.
Аппаратный это конечно хорошо, но наприпмер Mega8 должна регулировать 12 тью разными каналами (4 RGB линейки), как тут в реальном времени создавать и менять? Аппаратный не рассматриваем. Вижу 2 варианта - либо внутренний таймер либо через коэффициент как было сказано выше считая такты, вот и подходим к тому что я только начинаю осваивать и неумею нормально работать с прерываниями, а опыт программирования - самоучка на дельфях, хотя примеры для образования в интернете были - их решал сегодня закупил детали для программатора и пару тинек, одну на индикатор RGB вторая для экспериментов, там вав плеер или USB клавиатурное западло (хобби оно на самом деле так называется - в поиске посмотри, незнаю как переименовать эту фразу по другому). Пока мучаю програмный эмулятор.
|
|
|
|