Нескольно простых вопросов о программировании AVR на Си.
- Сообщения: 1759
- Зарегистрирован: Пт июн 01, 2018 07:28:45
- Реклама
Я же дал ссылки на соответствующие строчки в Makefile.
В любом случае, оптимизации одинаковые для разных версий gcc.
В любом случае, оптимизации одинаковые для разных версий gcc.
примерно та же песня и с avr-gcc, в другой теме, кажется, я приводил сравнения...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 228
- Зарегистрирован: Пн окт 04, 2010 11:55:41
Всем привет котаны и котики! Пытаюсь с CodevisionAVR 3.12 пересесть на Atmel Studio7. вот мой небеольшой проектик переписываю в студии, и пришел вопрос как по USART дробные числа вывести в терминал. К примеру CodevisionAVR я бы делал так:
Для Студии нет подобных библиотек по выводу дробных чисел? было удобно(( Пошарив по stdlib.h, нашел пару функции dtostrf() и dtostre() не особо устроили... к примеру есть пять символов (12.38), а потом стало 9.88, то перед 9 появляется пробел(((
Код: Выделить всё
ftoa(adc,2,buffer); //Вывод напряжения с двумя знаками после точки
puts(buffer);
puts("\n\r"); //переход на новую строку
Код: Выделить всё
dtostrf(adc, 5, 2, buffer); // 2 - кол-во цифр после запятой
puts(buffer);
USART_sendLine(buffer);
имхо, самое логичное - подключить библиотеку поддержки float для printf и пользоваться возможностями этой функции. printf, кстати, сразу и будет в USART выводить.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Реклама
- Сообщения: 228
- Зарегистрирован: Пн окт 04, 2010 11:55:41
[uquote="ARV",url="/forum/viewtopic.php?p=4093296#p4093296"]подключить библиотеку поддержки float для printf и пользоваться возможностями этой функции. printf, кстати, сразу и будет в USART выводить.[/uquote]
ага и потерять минимум 1,5-2К памяти программ как вы говорили тут же на форуме
ага и потерять минимум 1,5-2К памяти программ как вы говорили тут же на форуме
потерять... использовать с пользой. начиная с 16К флеша память уже не является препятствием. 1,5-2К вы же на float пожертвовали...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
да, код становится жирнее.WiseLord писал(а):Вывод такой - вплоть до 8 версии качество оптимизации улучшалось, а потом начало становиться хуже.
видимо писателям компилятора действительно:
ARV писал(а):начиная с 16К флеша память уже не является препятствием
ohmycode!
primuss3.com
primuss3.com
- Сообщения: 228
- Зарегистрирован: Пн окт 04, 2010 11:55:41
slav0n, ARV, Котаны, как вы заметили я не гуру - а новичок, и больше головой об стену Си бьюсь, потихоньку выбиваю по кирпичику)))
Данный вопрос решил тем что взял функцию ftoa(float n,unsigned char decimals,char *str) из библиотеки stdlib.lib CVAVR и тупо в*ерачил её в AtmelStudio 7 .c и .h. Но у меня компилятор начал ругаться на такие строки strcpyf(str,"-NAN"); как я понял это обрабатываем ±inf, nan, поэтому тупо //, и заработало, вывод дробных есть.
Поизучав, что это такое strcpyf(char *dest,char flash *src) нашел инфу что должно содержаться в библиотеке #include <string.h> CVAVR, возможно ли её заменить стандартными функциями из библиотеке #include <string.h> в Студии. Ну и проект по сравнению с использованием функции dtostrf() стал весить на 12% меньше.
Данный вопрос решил тем что взял функцию ftoa(float n,unsigned char decimals,char *str) из библиотеки stdlib.lib CVAVR и тупо в*ерачил её в AtmelStudio 7 .c и .h. Но у меня компилятор начал ругаться на такие строки strcpyf(str,"-NAN"); как я понял это обрабатываем ±inf, nan, поэтому тупо //, и заработало, вывод дробных есть.
Код: Выделить всё
void ftoa(float n,unsigned char decimals,char *str)
{
float scale=0.5;
unsigned char i,d;
switch (((unsigned int *) &n)[1])
{
case 0xFFFF:
//strcpyf(str,"-NAN");
return;
case 0x7FFF:
//strcpyf(str,"NAN");
return;
};
if (n<0.0) {n=-n; *str++='-';};
if (decimals>6) decimals=6;
i=decimals;
while (i--) scale=scale*0.1;
n=n+scale;
i=0;
scale=1.0;
while (n>=scale)
{
scale=scale*10.0;
// 08032010_1
if (++i>38)
{
//strcpyf(str,"INF");
return;
}
};
if (i==0) *str++='0';
else
while (i--)
{
scale=floor(0.5+scale*0.1);
d=(unsigned char) (n/scale);
*str++=d+'0';
n=n-scale*d;
};
if (decimals==0) {*str=0; return;};
*str++='.';
while (decimals--)
{
n=n*10.0;
d=(unsigned char) n;
*str++=d+'0';
n=n-d;
};
*str=0;
}Поизучав, что это такое strcpyf(char *dest,char flash *src) нашел инфу что должно содержаться в библиотеке #include <string.h> CVAVR, возможно ли её заменить стандартными функциями из библиотеке #include <string.h> в Студии. Ну и проект по сравнению с использованием функции dtostrf() стал весить на 12% меньше.
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
[uquote="neid",url="/forum/viewtopic.php?p=4094070#p4094070"]Данный вопрос решил тем что взял функцию ftoa(float n,unsigned char decimals,char *str) из библиотеки stdlib.lib CVAVR и тупо в*ерачил её в AtmelStudio[/uquote]
Лишние пробелы в начале строки не проще было пропустить?
Лишние пробелы в начале строки не проще было пропустить?
- Сообщения: 228
- Зарегистрирован: Пн окт 04, 2010 11:55:41
[uquote="Reflector",url="/forum/viewtopic.php?p=4094081#p4094081"]Лишние пробелы в начале строки не проще было пропустить?[/uquote]
а как? покажите пример, я только учусь, да и вся эта возня с ftoa принципе в первые... но код то меньше весит, значит не проще! но пример хочу увидеть, вам же не сложно!
а как? покажите пример, я только учусь, да и вся эта возня с ftoa принципе в первые... но код то меньше весит, значит не проще! но пример хочу увидеть, вам же не сложно!
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
[uquote="neid",url="/forum/viewtopic.php?p=4094091#p4094091"]а как?[/uquote]
Что-то типа такого:
Что-то типа такого:
Код: Выделить всё
char* s = dtostrf(adc, 5, 2, buffer);
while(*s == ' ') s++;
puts(s); - Сообщения: 121
- Зарегистрирован: Пт мар 19, 2021 08:58:45
Научите считать микросекунды(us)?
Делаю так, выходит ерунда:
нужно как можно точнее считать 1us, 500ms это просто тренировка
Делаю так, выходит ерунда:
Код: Выделить всё
// bool timer_status; //Статус для отображения на экране
...........
Timer1 overflow interrupt service routine
ISR (TIMER0_OVF_vect)
{
unsigned int timer_us;
unsigned int timer_ms;
TCNT0=0xF0;
timer_us++;
if(timer_us>999){ //1мс
timer_ms++;
timer_us=0;}
if(timer_ms>499){//500мс
timer_status=1; //сменили статус
timer_ms=0;}
}
...................
void Timer0_Init(void)
{
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Normal top=0xFF
// Timer Period: 1 us
TCCR0B=(0<<CS01) | (1<<CS00);
TCNT0=0xF0;
TIMSK0=(1<<TOIE0);
}
................
int main(void)
{Timer0_Init();
sei();
while (1)
{
if(timer_status!=0){ //каждые 500мс обновим
timer_status=0; //сбросили флаг таймера
}
}
Касательно TCNT0=0xF0...
Не уверен, что за оставшиеся 15 тактов до переполнения в прерывании успеет выполнится всё, что там написано (включая собственно вход-выход из прерывания), чтобы выйти в основную программу и успеть что-то сделать до нового прерывания.
На 16МГц отмерять интервалы с 1мкс (1МГц) таким методом вряд ли получится.
Не уверен, что за оставшиеся 15 тактов до переполнения в прерывании успеет выполнится всё, что там написано (включая собственно вход-выход из прерывания), чтобы выйти в основную программу и успеть что-то сделать до нового прерывания.
На 16МГц отмерять интервалы с 1мкс (1МГц) таким методом вряд ли получится.
- Сообщения: 121
- Зарегистрирован: Пт мар 19, 2021 08:58:45
[uquote="WiseLord",url="/forum/viewtopic.php?p=4103892#p4103892"]Касательно TCNT0=0xF0...
Не уверен, что за оставшиеся 15 тактов до переполнения в прерывании успеет выполнится всё, что там написано (включая собственно вход-выход из прерывания), чтобы выйти в основную программу и успеть что-то сделать до нового прерывания.
На 16МГц отмерять интервалы с 1мкс (1МГц) таким методом вряд ли получится.[/uquote]
к примеру 4us получается отмерить у ардуинщиков функцией micros() в ArduinoIDE, я так понимаю лучшего тоже не выжму?
Не уверен, что за оставшиеся 15 тактов до переполнения в прерывании успеет выполнится всё, что там написано (включая собственно вход-выход из прерывания), чтобы выйти в основную программу и успеть что-то сделать до нового прерывания.
На 16МГц отмерять интервалы с 1мкс (1МГц) таким методом вряд ли получится.[/uquote]
к примеру 4us получается отмерить у ардуинщиков функцией micros() в ArduinoIDE, я так понимаю лучшего тоже не выжму?
Наверное, такие задержки стоит доверить компилятору
Если внешние ловите, то capture event на Capture pin (ICP1) использовать.
Код: Выделить всё
#include <util/delay.h>
_delay_us(1);- Сообщения: 121
- Зарегистрирован: Пт мар 19, 2021 08:58:45
[uquote="Карбофос",url="/forum/viewtopic.php?p=4104006#p4104006"]Если внешние ловите, то capture event на Capture pin (ICP1) использовать.[/uquote]
да внешний импульс, подсчет примерной его длительности в us, но таймер1 уже занят, не использовать, вот пытаюсь как то вывернуться...
да внешний импульс, подсчет примерной его длительности в us, но таймер1 уже занят, не использовать, вот пытаюсь как то вывернуться...
Код: Выделить всё
uint8_t ovf_count = 0;
uint16_t ticks;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
TCCR0A = 0;
TCCR0B = 0; // No clock source (Timer/Counter stopped)
TCNT0 = 0; // Timer/Counter Register
TIFR0 |= _BV(TOV0);
// Wait for rising edge of C-clock
loop_until_bit_is_set(FREQ_PIN, FREQ_BIT);
// Wait for falling edge of C-clock
loop_until_bit_is_clear(FREQ_PIN, FREQ_BIT);
TCCR0B = _BV(CS00); // Start Timer/Counter, No prescaling
do {
do {
// Check for overflow
if (bit_is_set(TIFR0, _BV(TOV0))) {
TIFR0 |= _BV(TOV0);
++ovf_count;
}
} while (bit_is_clear(FREQ_PIN, FREQ_BIT));
do {
// Check for overflow
if (bit_is_set(TIFR0, _BV(TOV0))) {
TIFR0 |= _BV(TOV0);
++ovf_count;
}
} while (bit_is_set(FREQ_PIN, FREQ_BIT));
} while (--pulses); // pulses - сколько внешних периодов считать
TCCR0B = 0; // Stop Timer/Counter
// Check for overflow
if (bit_is_set(TIFR0, _BV(TOV0))) {
TIFR0 |= _BV(TOV0);
++ovf_count;
}
// тиков таймера насчитали, -2 тика на } while(--pulses);
// 1 тик таймера - 1 такт частоты контроллера
ticks = (((uint16_t)ovf_count << 8) | TCNT0) - 2;
}
Котаны! Подскажите, пожалуйста. Есть код для мигания светодиодов с помощью тактовой кнопки:
Он рабочий, светодиоды загораются, все хорошо. Но, мне необходимо посадить кнопку на, к примеру, PB4
Тогда, я меняю код следующим образом:
... и получаю мигающие светодиоды. Реакции на кнопку нет никакой.
Как корректно пересадить кнопку на другую ножку?
Код: Выделить всё
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRD = 0b00000000; // Порт D вход
PORTD = 0b11111111; // Подключаем подтягивающие резисторы
DDRB = 0b11111111; // Порт B выход
PORTB = 0b00000000; // Лог. 0 на выходе
while(1)
{
while ((PIND&(1 << PD0)) == 1){} // Ждем пока на выводе PDO лог. 1
_delay_ms(50); // Задержка
if ((PINB&(1 << PB0)) == 0) // Если на выводе PB0 лог. 0
{
PORTB |= (1 << PB0); // Лог. 1 на выводе PB0
PORTB &= ~(1 << PB1); // Лог. 0 на выводе PB1
}
else
{
PORTB &= ~(1 << PB0); // Лог. 0 на выводе PB0
PORTB |= (1 << PB1); // Лог. 1 на выводе PB1
}
while ((PIND&(1 << PD0)) == 0){} // Ждем пока на выводе PDO лог. 0
_delay_ms(50); // Задержка
}
}Тогда, я меняю код следующим образом:
Код: Выделить всё
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB = 0b11101111; // Порт B4 на вход
PORTB = 0b00010000; // Лог. 1 на входе PB4
while(1)
{
while ((PINB&(1 << PB4)) == 1){} // Ждем пока на выводе PB4 лог. 1
_delay_ms(50); // Задержка
if ((PINB&(1 << PB0)) == 0) // Если на выводе PB0 лог. 0
{
PORTB |= (1 << PB0); // Лог. 1 на выводе PB0
PORTB &= ~(1 << PB1); // Лог. 0 на выводе PB1
}
else
{
PORTB &= ~(1 << PB0); // Лог. 0 на выводе PB0
PORTB |= (1 << PB1); // Лог. 1 на выводе PB1
}
while ((PINB&(1 << PB4)) == 0){} // Ждем пока на выводе PDO лог. 0
_delay_ms(50); // Задержка
}
}
Как корректно пересадить кнопку на другую ножку?
Код: Выделить всё
while ((PINB&(1 << PB4)) == 1){}


