Нескольно простых вопросов о программировании AVR на Си.

Обсуждаем контроллеры компании Atmel.
Ответить
Мудрый кот
Сообщения: 1759
Зарегистрирован: Пт июн 01, 2018 07:28:45

Сообщение parovoZZ »

Какие оптимизации были включены?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Я же дал ссылки на соответствующие строчки в Makefile.

В любом случае, оптимизации одинаковые для разных версий gcc.
Контактная информация:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18776
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

примерно та же песня и с avr-gcc, в другой теме, кажется, я приводил сравнения...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Прорезались зубы
Сообщения: 228
Зарегистрирован: Пн окт 04, 2010 11:55:41

Сообщение neid »

Всем привет котаны и котики! Пытаюсь с CodevisionAVR 3.12 пересесть на Atmel Studio7. вот мой небеольшой проектик переписываю в студии, и пришел вопрос как по USART дробные числа вывести в терминал. К примеру CodevisionAVR я бы делал так:

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

ftoa(adc,2,buffer); //Вывод напряжения с двумя знаками после точки
puts(buffer); 
puts("\n\r");  //переход на новую строку
Для Студии нет подобных библиотек по выводу дробных чисел? было удобно(( Пошарив по stdlib.h, нашел пару функции dtostrf() и dtostre() не особо устроили... к примеру есть пять символов (12.38), а потом стало 9.88, то перед 9 появляется пробел(((

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

dtostrf(adc, 5, 2, buffer); // 2 - кол-во цифр после запятой
puts(buffer);
USART_sendLine(buffer);
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18776
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

имхо, самое логичное - подключить библиотеку поддержки float для printf и пользоваться возможностями этой функции. printf, кстати, сразу и будет в USART выводить.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Прорезались зубы
Сообщения: 228
Зарегистрирован: Пн окт 04, 2010 11:55:41

Сообщение neid »

[uquote="ARV",url="/forum/viewtopic.php?p=4093296#p4093296"]подключить библиотеку поддержки float для printf и пользоваться возможностями этой функции. printf, кстати, сразу и будет в USART выводить.[/uquote]
ага и потерять минимум 1,5-2К памяти программ как вы говорили тут же на форуме
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18776
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

потерять... использовать с пользой. начиная с 16К флеша память уже не является препятствием. 1,5-2К вы же на float пожертвовали...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков

Сообщение slav0n »

WiseLord писал(а):Вывод такой - вплоть до 8 версии качество оптимизации улучшалось, а потом начало становиться хуже.
да, код становится жирнее.
видимо писателям компилятора действительно:
ARV писал(а):начиная с 16К флеша память уже не является препятствием
ohmycode!
primuss3.com
Контактная информация:
Прорезались зубы
Сообщения: 228
Зарегистрирован: Пн окт 04, 2010 11:55:41

Сообщение neid »

slav0n, ARV, Котаны, как вы заметили я не гуру - а новичок, и больше головой об стену Си бьюсь, потихоньку выбиваю по кирпичику)))
Данный вопрос решил тем что взял функцию 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

Сообщение Reflector »

[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

Сообщение neid »

[uquote="Reflector",url="/forum/viewtopic.php?p=4094081#p4094081"]Лишние пробелы в начале строки не проще было пропустить?[/uquote]
а как? покажите пример, я только учусь, да и вся эта возня с ftoa принципе в первые... но код то меньше весит, значит не проще! но пример хочу увидеть, вам же не сложно!
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[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

Сообщение kote52 »

Научите считать микросекунды(us)?
Делаю так, выходит ерунда:

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

// 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;	 //сбросили флаг таймера
    }
}
нужно как можно точнее считать 1us, 500ms это просто тренировка
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Касательно TCNT0=0xF0...

Не уверен, что за оставшиеся 15 тактов до переполнения в прерывании успеет выполнится всё, что там написано (включая собственно вход-выход из прерывания), чтобы выйти в основную программу и успеть что-то сделать до нового прерывания.

На 16МГц отмерять интервалы с 1мкс (1МГц) таким методом вряд ли получится.
Контактная информация:
Встал на лапы
Сообщения: 121
Зарегистрирован: Пт мар 19, 2021 08:58:45

Сообщение kote52 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=4103892#p4103892"]Касательно TCNT0=0xF0...

Не уверен, что за оставшиеся 15 тактов до переполнения в прерывании успеет выполнится всё, что там написано (включая собственно вход-выход из прерывания), чтобы выйти в основную программу и успеть что-то сделать до нового прерывания.

На 16МГц отмерять интервалы с 1мкс (1МГц) таким методом вряд ли получится.[/uquote]

к примеру 4us получается отмерить у ардуинщиков функцией micros() в ArduinoIDE, я так понимаю лучшего тоже не выжму?
Опытный кот
Аватара пользователя
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Сообщение Карбофос »

Наверное, такие задержки стоит доверить компилятору

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

#include <util/delay.h>
_delay_us(1);
Если внешние ловите, то capture event на Capture pin (ICP1) использовать.
Встал на лапы
Сообщения: 121
Зарегистрирован: Пт мар 19, 2021 08:58:45

Сообщение kote52 »

[uquote="Карбофос",url="/forum/viewtopic.php?p=4104006#p4104006"]Если внешние ловите, то capture event на Capture pin (ICP1) использовать.[/uquote]
да внешний импульс, подсчет примерной его длительности в us, но таймер1 уже занят, не использовать, вот пытаюсь как то вывернуться...
Опытный кот
Аватара пользователя
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Сообщение Карбофос »

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

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;
}
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

Котаны! Подскажите, пожалуйста. Есть код для мигания светодиодов с помощью тактовой кнопки:

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

#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); // Задержка 
}
}
Он рабочий, светодиоды загораются, все хорошо. Но, мне необходимо посадить кнопку на, к примеру, PB4
Тогда, я меняю код следующим образом:

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

#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); // Задержка 
}
}
... и получаю мигающие светодиоды. Реакции на кнопку нет никакой.
Как корректно пересадить кнопку на другую ножку?
Опытный кот
Аватара пользователя
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Сообщение Карбофос »

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

while ((PINB&(1 << PB4)) == 1){}
У вас здесь используется битовая операция, ее результат - не логическая константа.
Ответить

Вернуться в «AVR»