во-вторых, если функция объявлена static и используется только в одном месте, она почти со 100% гарантией будет компилятором (оптимизатором) проинлайнена в коде. т.к. в этом случае нет накладных расходов на передачу параметров и возврат результата, это сокращает объем кода.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
ARV писал(а):во-первых, у вас 2 разных выражения, отсюда и разный объем при использовании одного и другого:
В другом компиляторе (для STM32) эти выражения дают одинаковый по размеру код, вот я и подумал что оптимизатор их должен привести к одному и тому же. Если она static ведь оптимизатор дает одинаковый размер.
Таки да. У меня, например, что деление на 16, что сдвиг на 4 генерирует абсолютно одинаковый ассемблерный код. Причём сдвиг там даже не используется - вместо сдвига на 4 там просто swap байта:
Спойлер
Apparatchik писал(а):При таком коде занимает 88 байт флеша, если же раскоментировать строку со здвигом и закоментировать с делениями - 104 байта.
А вы сохрание asm выхлоп компилятора для обеих вариантов и сравните в каком-нибудь двухпанельном diff-e - сразу покажет, что там оптимизатор не так понял. Попробуйте сравнить варианты с частями выражения - до '+' и после него.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR!
int aaa[6][7][8];
int z0 = sizeof(aaa);
int z1 = sizeof(aaa[0]);
int z2 = sizeof(aaa[0][0]);
int z3 = sizeof(aaa[0][0][0]);
printf("%d %d %d \n", z0/z1, z1/z2, z2/z3);
#define __IO volatile /*!< Defines 'read / write' permissions
__INLINE void FlashWord16Prog(uint32_t flash_addr, uint16_t data)
{
...
/* (2) Perform the data write (half-word) at the desired address */
*(__IO uint16_t*)(flash_addr) = data; /* (2) */
...
}
Значение flash_adr приводится к указателю на тип (volatile uint16_t*), затем происходит доступ записи по этому адресу.
Я хочу понять как распутывается эта запись.
Допустим имеем
Что здесь происходит?
а) работа(инкремент) с указателем-переменной как с volatile
б) копирование данных по адресу ptr с отключенной оптимизацией компилятора.
Ничего сложного. Значение data копируется в 16-битную ячейку памяти, на которую указывает ptr. Затем, инкремент смещает указатель так чтобы он указывал на следующую 16-битную ячейку. Ключевое слово volatile гарантирует, что запись в ячейку произойдет именно в этом месте (это так, по простому).
ОК, тогда ещё вопрос.
Указатели поддерживают работу с адресной арифметикой.
Для асинхронной модификации(подпрограмма прерывания) обычных типов данных и передачи этих данных в основную программу их объявляют с квалификатором volatile.
Если я в таком случае декларирую volatile указатель, то будет ли это означать что адресная арифметика также не будет подвергаться оптимизации?
то компилятор на свое усмотрение может и применить некие оптимизации инкремента. Например, решить, что это можно и попозже посчитать, а не в данном месте. При этом доступ к ячейке будет volatile. Но если сделать вот так
то тогда он уже будет обязан инкрементировать здесь и сейчас. При этом доступ к ячейке будет не volatile. Ну а чтобы совсем связать его руки, то можно сделать вот так:
Здраствуйте! Подскажите новичку в сфере программирования про АЦП, точней как измерить значения на 4 входах. Сижу, курю примеры и уроки, но так и не понял что к чему.
В протеусе код написанный в АВР студии сипит ошибками.
Надо перевести этот рабочий код с среди ардуино в нормальный код на си для АВР студии Спойлерfloat Upin1=0.0;
float Upin2=0.0;
float Upin3=0.0;
float Upin4=0.0;
float Ipin=0.0;
float U1=0.0;
float U2=0.0;
float U3=0.0;
float U4=0.0;
void setup() {
pinMode(0,INPUT);
pinMode(1,INPUT);
pinMode(2,INPUT);
pinMode(3,INPUT);
pinMode(4,INPUT);
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
digitalWrite(9,HIGH);//пин заряда
digitalWrite(10,HIGH);// соответствие пину 8 в протеусе - пин разряда (8 пин =пину 10)
}
void loop() {
//делаем замер напряжения падения на транзисторах пин PA4
Ipin=analogRead(4);
Ipin=(Ipin*5)/1023.0;
//делаем замер напряжения на входах
Upin1=analogRead(0);
Upin1=(Upin1*5)/1023;//вход PA0
Upin2=analogRead(1);
Upin2=(Upin2*5)/1023;//вход PА1
Upin3=analogRead(2);
Upin3=(Upin3*5)/1023.0;//вход PA2
Upin4=analogRead(3);
Upin4=(Upin4*5)/1023.0;//вход PA3
//вычисляем напряжение на аккумуляторах
U1=Upin1/(51/78.00);
U2=Upin2/(51/171.00);
U3=Upin3/(51/251.00);
U4=Upin4/(51/351.00);
if (U4>U3)
{
U4=U4-U3;
}
if (U3>U2)
{
U3=U3-U2;
}
if (U2>U1)
{
U2=U2-U1;
}
//защита от переразряда
if ((U1<3)||(U2<3)||(U3<3)||(U4<3))
{
digitalWrite(10, LOW);
}
else
{
digitalWrite(10, HIGH);
}
//защита от перезаряда
if ((U1>4.2)||(U2>4.2)||(U3>4.2)||(U4>4.2))
{
digitalWrite(9, LOW);
}
//защита от КЗ
// if (Ipin>4)
// {
// digitalWrite(9, LOW);
// digitalWrite(10, LOW);
// }
}
Мой код, или бред
Первий Вариант
Спойлер#include <avr/io.h>
#include <avr/delay.h>
float Upin1, Upin2, Upin3, Upin4, Ipin, U1, U2, U3, U4;
int main(void)
{
Upin1, Upin2, Upin3, Upin4, Ipin, U1, U2, U3, U4=0;
//функция получает в качестве аргумента номер канала и возвращает значение на входе
unsigned int ADC_result(unsigned char adc_input)
{
ADMUX=adc_input | (ADMUX & 0x00);
_delay_us(10); //задержка для стабилизации входного напряжения
ADCSRA |= 0x40; //ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
return ADCW; //ADCW - содержит ADCH и ADCL как нам нужно
}
while(1)
{
ADMUX |= 0x00; //выставляем канал PA0
_delay_us(30); //задержка для стабилизации
ADCSRA |= 0x40; //ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //Ждём флаг окончания измерения
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
Upin1=ADCH;
ADMUX |= 0x01; //выставляем канал PA1
_delay_us(30); //задержка для стабилизации
ADCSRA |= 0x40;//ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //Ждём флаг окончания измерения
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
Upin2=ADCH;
ADMUX |= 0x02; //выставляем канал PA2
_delay_us(30); //задержка для стабилизации
ADCSRA |= 0x40;//ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //Ждём флаг окончания измерения
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
Upin3=ADCH;
ADMUX |= 0x03; //выставляем канал PA3
_delay_us(30); //задержка для стабилизации
ADCSRA |= 0x40;//ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //Ждём флаг окончания измерения
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
Upin4=ADCH;
ADMUX |= 0x04; //выставляем канал PA4
_delay_us(30); //задержка для стабилизации
ADCSRA |= 0x40; //ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //Ждём флаг окончания измерения
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
Ipin=ADCH;
}
}
//функция получает в качестве аргумента номер канала и возвращает значение на входе
unsigned int ADC_result(unsigned char adc_input)
{
ADMUX=adc_input | (ADMUX & 0x00);
_delay_us(10); //задержка для стабилизации входного напряжения
ADCSRA |= 0x40; //ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
return ADCW; //ADCW - содержит ADCH и ADCL как нам нужно
}
while(1)
{
//Upin1=ADC_result(0)*0.0048875855327468;
//Upin2=ADC_result(1)*0.0048875855327468;
//Upin3=ADC_result(2)*0.0048875855327468;
//Upin4=ADC_result(3)*0.0048875855327468;
//Ipin=ADC_result(4)*0.0048875855327468;
}
}
Все нормально, ошибок в протеусе нет, но когда раскоментирую
//Upin1=ADC_result(0)*0.0048876;
//Upin2=ADC_result(1)*0.0048876;
//Upin3=ADC_result(2)*0.0048876;
//Upin4=ADC_result(3)*0.0048876;
//Ipin=ADC_result(4)*0.0048876;
в протеусе появляются ошибки (PC=0x00CA. [AVR MEMORY] Writing to memory location 0x0171 outside of memory size 0x0160. [U2]
), ругается на память,
и когда компилиш
Warning
"Compiler optimizations disabled; functions from <util/delay.h>
"F_CPU not defined for <util/delay.h>"
Понял. Оптимизацию включил а строку # define F_CPU 1000000UL надо било поставить перед #include <util/delay.h>
Последний раз редактировалось roma1984 Вс ноя 06, 2016 18:41:04, всего редактировалось 1 раз.