Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 129
Зарегистрирован: Вт сен 23, 2008 14:29:06
Откуда: Ukraine

Сообщение roma1984 »

Спасибо! Это все мелочи, больше все интересует цикл измерения АЦП, правильно ли он присваивает значения на входах переменным Upin, может и от этого сипят ошибки в протеусе. Не пойму просто логики этого выражения ADMUX=adc_input | (ADMUX & 0x00); Как он понимает с какого порта проводить измерения кроме нулевого PA0 который указан.

Добавлено after 4 minutes 22 seconds:
Так и есть, ставлю значения от 0 до 1023 в формулу и ошибок нет. Значит значения adc_input(0) содержат всякий бред.
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

roma1984 писал(а):Не пойму просто логики этого выражения ADMUX=adc_input | (ADMUX & 0x00);
А откуда оно вообще взято ?
По сути, выражение "ADMUX & 0x00" - бесполезно, ибо всегда будет равно нулю.
В итоге, вся конструкция сведётся к

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

ADMUX=adc_input;
:dont_know:

Но ошибок тут нет. Значение ADMUX будет зависимо от значения adc_input.
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 129
Зарегистрирован: Вт сен 23, 2008 14:29:06
Откуда: Ukraine

Сообщение roma1984 »

С уроков по АЦП с инета , хотя єсть готовий проект по меге8 и там такого типа ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); где переменой присваивают #define ADC_VREF_TYPE 0x40 для тини44 в опорним VCC вроде надо #define ADC_VREF_TYPE 0x00
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

roma1984 писал(а):типа ADMUX=adc_input | (ADC_VREF_TYPE & 0xff)
Дак тут 0xff. Разницу чуете ? :)
Кстати, и тут тоже операция "& 0xff" бесполезна :) При разрядности выражения в 8 бит, конечно же.
Тут всё сведётся к

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

ADMUX=adc_input | ADC_VREF_TYPE;
Для чего лишнюю операцию делать ... :dont_know:
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 129
Зарегистрирован: Вт сен 23, 2008 14:29:06
Откуда: Ukraine

Сообщение roma1984 »

Вроде проясняєтса :)) Когда в коде появляєтся например для PA0 порта ADC_result(0) то строка unsigned int ADC_result(unsigned char adc_input) переводит значения 0 из одной системи вычислений в другую и функция ADMUX=adc_input присваиваєт ето число ADMUX. Осталось понять как конвертируются числа и что делаєт | (ADMUX & 0x__) .
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Что за "конвертирование систем вычислений" ? Это что за "чудо зверушка" такая ? :)
roma1984 писал(а):что делаєт | (ADMUX & 0x__)
Да ничего оно не делает. Отбрасывает в маске лишние биты, да и всё.
Я в АВРах не бум-бум, но судя по названию регистра, ADMUX - это мультиплексор входов АЦП. И, судя по коду, по всей видимости, выбор идёт через младшие биты.
Ничего тут таинственного нет, КМК :dont_know:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

roma1984 писал(а):єсть готовий проект по меге8 и там такого типа ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
все дело в "такого типа" - это расплывчатое выражение говорит о том, что вы нифига не знаете, как оно там на самом деле. ну или вам на это фиолетово, что недопустимо.

на самом деле там наверняка "что-то типа этого": ADMUX=adc_input | ADC_VREF_TYPE; либо (вероятнее всего) ADMUX= ADC_VREF_TYPE | (adc_input & 0x07);
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 129
Зарегистрирован: Вт сен 23, 2008 14:29:06
Откуда: Ukraine

Сообщение roma1984 »

Аlex C "конвертирование систем вычислений" я немного перегнул , спал уже наверно на ходу, там просто беззнаковое целое число .
ADMUX это мультиплексор входов 2 первые бита выбор опорного (00 Vсс), остальные 6 - выбор входа:
ADC0 (PA0) - 000000
ADC1 (PA1) - 000001
ADC2 (PA2) - 000010
ADC3 (PA3) - 000011
ADC4 (PA4) - 000100
ADC5 (PA5) - 000101
ADC6 (PA6) - 000110
ADC7 (PA7) - 000111
Реально меняются 3 последние биты , если маска отбрасывает лишние биты, то надо не трогать просто 5 первых бит.
И тогда получится ADMUX=adc_input | (ADMUX & 0x07) .
Вроде так?
ARV Да, я в этом плане новичок, так и написал, в тех уроках, что я смотрел нет описание этой строки
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Если первые 2 бита - опорное, значит их, при выборе входа, трогать не нужно.
Получается, что переменную adc_input нужно ещё сдвинуть влево на 2 бита. Что-то в этом роде :

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

ADMUX &= 0x03;    // Очищаем все биты, кроме 2-ух младших, в кторых лежит настройка опорного.
ADMUX |= adc_input<<2;  // Устанавливаем биты мультиплексора из переменной adc_input
:dont_know:

Или я что-то не так понял :roll:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

roma1984 писал(а):И тогда получится ADMUX=adc_input | (ADMUX & 0x07) .
Вроде так?
нет, не так. так вы гасите в ADMUX все биты, кроме младших трех, а потом к этим трем добавляете еще и те, которые в adc_input

правильно так, как я вам писал:
ARV писал(а):ADMUX= ADC_VREF_TYPE | (adc_input & 0x07);
или так, ближе к вашему варианту

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

ADMUX = (ADMUX & 0xF8) | (adc_input & 0x07);
но согласитесь, первый вариант проще
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 129
Зарегистрирован: Вт сен 23, 2008 14:29:06
Откуда: Ukraine

Сообщение roma1984 »

Опять сипит ошибки в протеусе, уже голова болит.
Спойлер#include <avr/io.h>
# define ADC_VREF_TYPE 0x00
# define F_CPU 1000000UL
#include <util/delay.h>

void ADC_init()
{
ADMUX=0x00; // Настройки канала PА0 опорноє Vcc 0b00000000
ADCSRA=0x83; // 0b10000011 ADEN=1, ADSC=0, ADATE=0, ADIF=0, ADIE=0, предделитель на 8 частота АЦП 125 кГц ADPS2=0 ADPS1=1 ADPS0=1
}

//функция получает в качестве аргумента номер канала и возвращает значение на входе
unsigned int ADC_result(unsigned char adc_input)
{
ADMUX= ADC_VREF_TYPE | (adc_input & 0x07);
_delay_us(10); //задержка для стабилизации входного напряжения
ADCSRA |= 0x40; //ADSC = 1. Запуск преобразования (в режиме однократного преобразования)
while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
ADCSRA|=0x10; //ADIF= 1 преобразование закончено
return ADCW; //ADCW - содержит ADCH и ADCL как нам нужно
}

float Upin1, Upin2, Upin3, Upin4, Ipin, U1, U2, U3, U4;
int main(void)
{
Upin1=0; Upin2=0; Upin3=0; Upin4=0; Ipin=0; U1=0; U2=0; U3=0; U4=0;

DDRA=0x00;
DDRB=0x7;

while(1)
{
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;
}
}
Добавлено after 13 minutes 26 seconds:
CV AVRавтоматом такоє генерит
Спойлер#include <tiny44.h>

#include <delay.h>

#define ADC_VREF_TYPE 0x00

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=(adc_input & 0x3f) | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Bipolar Input Mode: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
// ADC4: On, ADC5: On, ADC6: On, ADC7: On
DIDR0=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x83;
ADCSRB&=0x6F;
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 129
Зарегистрирован: Вт сен 23, 2008 14:29:06
Откуда: Ukraine

Сообщение roma1984 »

Скопировал код с CodeVisionAVR опять не работает, думаю что за фигня пишу в AVR Studio 5.0 моргание пином протеус матерится, пишу в CodeVisionAVR все работает. Походу AVR Studio 5.0 баганя какая то.
Контактная информация:
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Объявляю функцию как inline void в прототипе пишу extern inline void
в одном проекте все работает перенес библиотеку в другой проект
компилятор IAR выдает ошибку.

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

Error[Li005]: no definition for "Login_enter" 
убираю модификатор inline все находит (делаю вывод что файл header подключается нормально)

Даже не знаю в какую сторону копать.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Странно то что в одном месте компилятор это переживал, а в другом не захотел.
Но да ладно, тогда как по феншую выдать переменную из одного модуля в другой, желательно что бы было без входа в функцию?

Глобальными переменными что-то надоело пользоваться, решил по пробовать выдать и изменить через функцию.
Но даже при максимально оптимизации по скорости он все равно производит вход в функцию,где происходит только присваивание 1 или 0 переменной и все.

Ps: прогнал на самой высокой оптимизации не в одном варианте функцию не вывернул.
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

И что Вас в этом смущает ? С чего такая уверенность, что компилятор обязан эти функции проинлайнить ? Не посчитал нужным - не заинлайнил, посчитает - заинлайнит.

Как вариант - extern, а вместо функций - макросы в хидере.
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

ARV писал(а):inline - это квалификатор для компилятора, который строит код модуля путем встраивания (т.е. повтора) в нужных местах кода функции, а extern - это квалификатор для линкера, который просто расставляет ссылки на единожды имеющийся где-то код. то есть это взаимоисключающие квалификаторы - нельзя быть одновременно повторяемым куском кода и единственным куском.
Близко к истине, но не так. В оригинале значится: "By declaring a function inline, you can direct GCC to make calls to that function faster."
На всякий случай перевод: "Объявляя функцию inline, вы указываете GCC сделать вызовы этой функции быстрее".
В некоторых случаях, данная функция действительно может оказаться в коде, а не в виде отдельной подпрограммы. Например, если она вызывается с одинаковым набором параметров или всего один раз.
extern - это указание компилятору, что данный идентификатор внешний, доступный для обработки LD. Так как любая не статическая функция, с кодом в текущем файле, является внешней то, запись
int func(int i) { return i++;}
и запись
extern int func(int i) { return i++;}
имеют один и тот же смысл, так как если функция не статическая, то значит она внешняя.

А вот сочетание этих extern и inline в одном месте может действительно привести к неожиданным последствиям.
Подробности: https://gcc.gnu.org/onlinedocs/gcc/Inline.html
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

pokk писал(а):Даже не знаю в какую сторону копать.
В сторону понимания сущности inline. И немного в сторону понимания того, как работает трио препроцессор-компилятор-линкер. Первый лепит из *.h и *.c большие простынки *.(ну скажем pp) и скармливает их компилятору. На выходе компилятора появляется *.o - файл со скомпилированными объектами. Линкер собирает согласно списка все объектные файлы в программу - устанавливает связи (linker- ведь!) между объектами, попутно проверяя все ли ссылки из модулей находят объекты в других модулях и однозначны ли эти связи. Если компилятор изыскивает возможность реально заинлайнить функцию - то как объект в модуле она существовать не будет - и попытка заставить линкер связать вызов из других модулей на такую функцию закономерно обломится.
Таким образом реконструкция катастрофы выглядит следующим образом - предыдуший компилятор толи не решился функцию инлайнить, то ли решил, что раз она объявлена в заголовке [???] то программист по ходу "не сечёть фишку" и добро-бы перестраховаться - создал её "в теле". IAR же или по упёртости или по жестоковыйности своей натуры возжелав наказать "неряху" - заинлайнил функцию, спихнув на линкера ответственность разгребаться в связях [подобно пьяному дьячку на колокольне].
Что делать - учиться програменному делу настояшим образом ©, знать и любить свой инструмент как солдат лопату. :) static, inline - это не ускоряющие заклинания, а конкретные требования к компилятору - который в общем-то тупой исполнитель нашей воли. Т.е. если inline функция, грубо говоря, слегка подобна макросу - и пользоваться сей "макрос" будет в нескольких единицах компиляции (т.е. препроцессорных простынях собранных из С-файлов) то помещать его хорошо туда где его все увидят - т.е. в файл заголовка. НО! Как уже замечалось выше - компилятор порою избирательно туп и если он откажется инлайнить функцию, определённую в заголовке, - то у линкера появятся претензии иного рода - к наличию множественных копий её тела в разных объектных файлах. Т.е. мы плавненько возвращаемся к первому предложению этого абзаца - понимание того как работают инструменты позволит расшивать ситуации на лету вне зависимости от причуд конкретного компилятора.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

добавлю еще об inline: эта директива не принуждает компилятор обязательно инлайнить тело функции, это лишь рекомендация сделать это, если подвернется возможность (или необходимость). а вот какие там возможности или необходимости будут - это отдано на откуп компилятору, ему и решать. для гарантированного инлайна применяются всякие костыли (вероятно, разные для разных компиляторов). например, AVR-GCC должен всегда инлайнить функцию, для которой задан атрибут always_inline.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение FreshMan »

Кто какую использует форму записи макроса, дабы в проге было видно четкое различие между оным, переменной и функцией ?
Tell Me The Truth
Ответить

Вернуться в «Разные вопросы по МК»