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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

Это моя неопытность:) Никакого смысла или преимущества у XOR я не придумал :) И до кучи тогда еще вопрос: как будет правильнее сбрасывать бит? Так (~(1<<0)) или так (0<<1) или второй вариант вообще работать не будет?:)

VHEMaster, вы это мне или кому-то из предыдущих сообщений?:)
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Реклама
pcb
Опытный кот
Сообщения: 833
Зарегистрирован: Пт авг 12, 2011 09:14:27
Откуда: Млечный путь/Земля/РФ/Екатеринбург

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

Сообщение pcb »

Мikа писал(а):И до кучи тогда еще вопрос: как будет правильнее сбрасывать бит? Так (~(1<<0)) или так (0<<1) или второй вариант вообще работать не будет?:)
PORTB&=~(1<<pin); обнуляем бит
PORTB/=(1<<pin); ставим бит :tea:
Разработал:
-BLDC
-ФУОЗ/МПСЗ
-SMART BMS
-ECU/EDC на STM32F4(43%)+CPLD(57%)
-Моноинжектор на ATSAMD20G16
-контроллер эффектов для RGB LED ленты
-умные часы/обратный счет/секундомер
-устройство измерения емкости АКБ
Реклама
Аватара пользователя
VHEMaster
Потрогал лапой паяльник
Сообщения: 374
Зарегистрирован: Сб июл 14, 2012 09:20:09
Откуда: Украина, город Полтава

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

Сообщение VHEMaster »

Мikа писал(а):VHEMaster, вы это мне или кому-то из предыдущих сообщений?:)
Я это тому, кому нужна помощь
Всем канифоли :)
https://vk.com/maks_naumchuk
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

pcb писал(а): PORTB/=(1<<pin); ставим бит :tea:

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

PORTB|=(1<<pin); //ставим бит  
так правильно и вообще такие вопросы из азбуки по си можно вычитать. Стыдно должно быть товарищи.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

Спасибо, парни :) Да, вопрос из азбуки, но я предпочитаю узнать ответ у живых людей, а не у статьи, если это возможно :) Сорри за оффтоп :)
Ещё вопрос, относительно флагов прерываний. Суть такова, что после вызова прерывания и выполнения всего, что с ним связано, прерывание выполняется ещё раз. Как я понимаю - это дребезг кнопки. Но не понятно вот что: первое, что делает прерывание - запрещает прерывания. Потом идёт ожидание 250 мс. Потом выполняется всё, что оно за собой тянет. И, главное, в самом конце, перед разрешением прерываний, я сбрасываю все флаги INT прерываний.

Напомню, для понятности: обработчик прерывания "включает кусок выполняемого кода, делая его условие истинным".

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

ISR( INT1_vect )
{
	GICR=0b00000000; // Запрет прерываний
	_delay_ms(250);     // Ожидание
	LcdWriteData('P');   // Оповещение о том, что прерывание сработало
	w=1;                     // "Включение условия"
}


if (w==1)
	{
		
		//Выполняемый код
		
                [b]Было тут[/b]
		GIFR=0xb11100000; // Сбрасываем флаги прерываний по
		GICR=0b10000000; // Разрешаем прерывания
		_delay_ms(500);
		[b]w=0;[/b]
	}
После этого прерывание вызывается снова. О продолжающемся дребезге речи быть не может, тк всё это дело выполняется больше 5 секунд.
Саму проблему повторного ыполнения кода я решил тем, что переместил w=0; туда, где оно сейчас из Было тут.
Но мне хотелось бы понять, откуда берётся прерывание.
GIFR=0xb11100000; // Сбрасываем флаги прерываний по - в этот регистр я и 000 и 111 записывал, всё одно и то же.

Про обнуление флагов да и вообще про прерывания INT я читал тут
Конкретно о сбросе флагов прерываний:
СпойлерПоследний регистр, имеющий отношение к внешним прерываниям, - это статусный регистр GIFR (General Interrupt Flag Register). В нем содержатся флаги, устанавливаемые в случае формирования запроса на внешнее прерывание.
Флаги сбрасываются аппаратно, когда вызывается обработчики прерываний. Также их можно сбросить программно, записав в регистр единицы.
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Реклама
Аватара пользователя
eess9
Вымогатель припоя
Сообщения: 672
Зарегистрирован: Ср фев 29, 2012 01:58:32
Откуда: Харьков, Украина

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

Сообщение eess9 »

А что за странная запись?

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

 GIFR=0xb11100000; // Сбрасываем флаги прерываний 
Если вы хотите в 16-ричной системе, то 0xFF, если в двоичной - 0b11111111.
0xb -??? Странно что компилятор пропустил такое

Если флаг надо сбросить, то надо записать

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

GIFR=0xFF;
Вложения
1.jpg
(92.37 КБ) 322 скачивания
Реклама
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

eess9 писал(а):А что за странная запись?

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

 GIFR=0xb11100000; // Сбрасываем флаги прерываний 
Если вы хотите в 16-ричной системе, то 0xFF, если в двоичной - 0b11111111.
0xb -??? Странно что компилятор пропустил такое

Если флаг надо сбросить, то надо записать

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

GIFR=0xFF;
Это называется "Привет, я Миша и я днище" :oops: :oops: :oops: Остаток от экспериментов с 0b и 0x. В этом дело и было, сорри, такую телегу зря писал, спасибо! :beer:
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

0xb -??? Странно что компилятор пропустил такое
А чего бы ему не пропустить ? 0xb - это 11 в десятичной. Синтаксис для компилятора вполне адекватный. :)
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

А теперь озадачивает счётчик ATmega32 TC1, дающий прерывание по совпадению с числом :)
В обработчике он должен последовательно два раза вывести на дисплей число, которое он насчитал на момент вывода этого самого числа.

Вот обработчик:

ISR (TIMER1_COMPA_vect)
{
//timer++;
LcdWriteData('1'); //Пишем на дисплей
LcdWriteData('_'); //Пишем на дисплей
showMore(TCNT1|0x30); //Пишем на дисплей число из регистра, в котором лежит число, насчитанное таймером.

LcdWriteData(' '); //Пишем на дисплей

LcdWriteData('2'); //Пишем на дисплей
LcdWriteData('_'); //Пишем на дисплей
showMore(TCNT1|0x30); //Пишем на дисплей число из регистра, в котором лежит число, насчитанное таймером.

TIMSK&=(~(1<<OCIE1A)); //Запрещаем прерывание по таймеру

}

По-идее всё просто) Вот что пишет дисплей: 1_15676 2_15671. Но как второе число может быть меньше первого? Оо То, что таймер проходит по второму кругу исключено: частота 16МГц\1024. Таймер 16ти разрядный. В секунду считает до 15625. Так же для проверки прерывание по переполнению таймера выводит "F" на дисплей. Но в обработчике видно, что разница между выводами информации всего в паре команд.
Да, если добавить между выводами первого и второго значения какую-то задержку, больше 2 мс, то он показывает адекватный результат.
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

А чего бы ему не пропустить ? 0xb - это 11 в десятичной.
Ух ты! А я проглядел. Мikа, Вы очень изящно выстрелили себе в ногу. :)

Прерывания лучше не нагружать работой с дисплеем, ибо это долгое дело, а они должны быть как можно короче. Лучше в прерывании ставьте флаг, а в главном цикле по нему что-то делайте.

Кстати, Вы учли, что в момент прерывания таймер не обнуляется, и продолжает считать дальше?
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

YS, да, в рабочем варианте программы прерывания только флаги и выставляют. Ну или делают инкрименты. Всё описанное выше было просто тестом, разбираюсь подробнее, что к чему. то, что таймер не обнуляется, я помню :)
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

Кстати, в чем смысл этой операции:

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

TCNT1|0x30
?

В принципе, | 0x30 делает из цифры код ее символьного представления, если я все правильно помню. Но это верно только для цифр. Для чисел работать, естесственно, не будет. :)
то, что таймер не обнуляется, я помню
Тогда логично было бы добавить строчку типа

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

OCR1A+=TIMER_INT_PERIOD;
Где TIMER_INT_PERIOD - желаемый период прерываний. Иначе прерывание происходит ровно столько же раз в секунду, сколько и переполнение, только со сдвигом относительно него, при одном и том же числе в таймере...
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

Здравствуйте!
Написал в IAR AVR на Си операцию записи в EEPROM:
eep_OSCCAL=a;

Смотрю листинг после компиляции и вижу это:
Спойлер

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

 \                                 In  segment EEPROM_I, align 1, keep-with-next
     11          __eeprom uint8_t eep_OSCCAL=0x40;
   \                     eep_OSCCAL:
   \   00000000   40                 DC8 64
     12          
     13          

   \                                 In  segment CODE, align 2, keep-with-next
     14          int main(void)
   \                     main:
     15          {
     16            unsigned char a = 1;
   \   00000000   E001               LDI     R16, 1
     17            
     18           eep_OSCCAL=a;
   \   00000002   ....               LDI     R20, eep_OSCCAL
   \   00000004   ....               RCALL   __eeput8_8
     19             ;
     20          
     21            //Разрешение прерываний
     22            __enable_interrupt();
   \   00000006   9478               SEI
     23            
     24            while(1)
   \                     ??main_0:
   \   00000008   CFFF               RJMP    ??main_0
     25            {
     26              ;
     27            }
     28            
     29          
     30          }   

   Maximum stack usage in bytes:

     Function CSTACK RSTACK
     -------- ------ ------
     main         0      4


   Segment part sizes:

     Function/Label Bytes
     -------------- -----
     eep_OSCCAL        1
     main             10

 
 10 bytes in segment CODE
  1 byte  in segment EEPROM_I
 
 10 bytes of CODE  memory
  1 byte  of XDATA memory

Errors: none
Warnings: none

Вопрос: а где вообще код __eeput8_8 ?? :shock:
Меня интересует, как компилятор реализует запись в EEPROM если у меня записывается то же значение, что и было там? Т. е. подпрограмма тупо перезапишет ячейку, бессмысленно сократив ей жизнь если пишется то же что и было, или же она выполняет проверку различается ли то, что есть и что пишу и запишет только если различается?
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

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

Сообщение blackx »

__eeput8_8, видимо, в сторонней либе хранится. То есть, вы смотрите на листинг только своего кода, а не всего, что включается в конечный hex-файл.

Вообще, мало верится, что при записи происходит проверка значения :)
Изображение only pure true norwegian blackx Изображение
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

А как сделать так, чтобы генерился полный листинг, который в т. ч. можно отлаживать в Протеусе?
blackx писал(а):мало верится, что при записи происходит проверка значения
Неужели разработчики компилятора поленились реализовать такую простейшую функцию? Ведь это пишется в 2 строчки! В чем смысл такого упущения? :shock:

Кстати, на аппаратном уровне как все это происходит? Есть ли внутри кристалла аппаратная проверка "нужно ли спускать/накачивать заряд в затворе полевиков?" или перед записью весь байт стирается?
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

В чем смысл такого упущения?
В малом смысле реализации такой проверки. EEPROM обычно используется для хранения каких-то редко изменяемых данных, например, настроек. Причем зачастую эти данные изменяются человеком. В таком режиме ресурс EEPROM чрезвычайно велик, и делать дополнительную защиту от записи уже существующего значения нет смысла.

Кроме того, данные в EEPROM постепенно деградируют, и выполняя запись того же значения, мы продлеваем срок его хранения, обновляя утекшую часть заряда. Но тут, в общем, речь опять же идет о десятках лет.
Есть ли внутри кристалла аппаратная проверка
Нет. А во FLASH вообще стирается страница целиком, даже если меняем только один байт (остальные, естесственно, надо перписывать).
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

YS, подал идею по поводу переполнение таймера с разанее записанным в него числом, спс :) Я продолжа.ю кавыряться с таймером. Опытным путём у меня напрашивается такой вывод:

Даже если мы не разрешаем прерывания, счётчики всёравно считают.
Всёравно переполняются\сравниваются с каким-то числом и т.п.
Как следствие поднимают флаг прерывания. Но ничего не происходит, т.к. прерывание не разрешено.
Но ка ктолько мы его разрешаем, оно тут же срабатывает, т.к. флаг был заранее поднят.

Поэтому при работе с прерыванием по совпадению счётчика с каким-то числом надо:

Сбросить флаг прерывания
Сбросить счётчик в 0
Разрешить прерывание по совпадению

Правильно? Оо
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

YS писал(а):EEPROM обычно используется для хранения каких-то редко изменяемых данных, например, настроек.
А если кто-то безконца тыркает кнопки "погромче-потише", "поярче-потемнее" и т. п., а проц каждый раз пишет в ЭСППЗУ? Так и дотыркаться можно.
YS писал(а):выполняя запись того же значения, мы продлеваем срок его хранения, обновляя утекшую часть заряда
Так программу в ПЗУ проца никто не обновляет в это время и дело закончится тем, что заряд скорее утечет в памяти прогамм, зато данные в ЭСППЗУ целые будут. Правда кому они будут нужны после этого :))
YS писал(а):Нет. А во FLASH вообще стирается страница целиком, даже если меняем только один байт (остальные, естесственно, надо перписывать).
Ну это в памяти программ я так понял. А память данных ЭСППЗУ разве также шьется?
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

А если кто-то безконца тыркает кнопки
Давайте посчитаем. Ресурс EEPROM AVR - 100000 циклов перезаписи. Пускай человек тыкает кнопку раз в секунду по двенадцать часов в день, и при каждом тычке процессор сохраняет измененное значение в память.

Итак, 100000 тычков-секунд. 27 часов тыкания. Почти три дня тыкания кнопки раз в секунду, двенадцать часов в день, без перерыва. Это кто-нибудь осилит? :)
А память данных ЭСППЗУ разве также шьется?
Где как. У MSP430 так же, только размер сегмента меньше. У AVR побайтно. Но физически и память программ, и память данных используют один принцип - это один и тот же (в смысле технологии) FLASH. Только доступ к ячейкам организован по-разному, и EEPROM заточен под больший ресурс.
YS, подал идею по поводу переполнение таймера с разанее записанным в него числом, спс
Ага, я сам так спотыкался. :)
Поэтому при работе с прерыванием по совпадению счётчика с каким-то числом надо:

Сбросить флаг прерывания
Сбросить счётчик в 0
Разрешить прерывание по совпадению
Флаг сбрасывается автоматически при входе в обработчик. Вот если не хочется, чтобы после разрешения прерываний произошел переход в обработчик, тогда перед разрешением его надо сбросить.

Сбрасывать счетчик в ноль можно тогда, когда прерывание одно - для простоты. А вот если на одном таймере висит несколько временных интервалов по прерываниям, тогда в обработчике надо прибавить к соответствующему регистру совпадения число, соответствующее времени до следующего срабатывания. При этом получается, что переполнение также автоматом учитывается.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
srg320
Встал на лапы
Сообщения: 85
Зарегистрирован: Пт фев 01, 2013 17:47:26
Откуда: Украина, Луганская область

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

Сообщение srg320 »

Здравствуйте!
Есть проект в IAR ARM, С и ассемблер вперемешку.
Есть, например, структура
Спойлер

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

typedef struct _NT_TIB {
    struct _EXCEPTION_REGISTRATION_RECORD* ExceptionList;  // 00h
    PVOID StackBase;                                       // 04h
    PVOID StackLimit;                                      // 08h
    ....
    struct _NT_TIB *Self;                                  // 18h
} NT_TIB, *PNT_TIB;
есть макрос на С для вычисления смещения полей структуры

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

#define OFFSET(type, field) ((ULONG_PTR)(&((type *)0)->field))
допустим напишем так

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

#define TeStackLimit OFFSET(NT_TIB, StackLimit)
и TeStackLimit будет всегда равен реальному адресу поля StackLimit в структуре NT_TIB, даже если структура в будущем изменится.

Дальше, есть код на ассемблере

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

LDR     R0,[R2, #+0x08] ; R0 = [R2]->StackLimit, в R2 адрес переменной типа NT_TIB
Вопрос: возможно ли и каким образом в ассеблерных файлах использовать дефайны из С, чтобы каждый раз не считать смещения полей, а написать, например, так

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

LDR     R0,[R2, #+TeStackLimit]
потому как такого кода будет много, и определения структур в будущем будут изменяться.
Отказаться от ассемблера и писать всё на С - не вариант. Заранее благодарен.
Ответить

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