1 / 1 / 0
Регистрация: 28.01.2010
Сообщений: 537
|
|
1 | |
Вопросы о С.18.07.2011, 01:49. Показов 163147. Ответов 306
Метки нет (Все метки)
Доброго времени суток всем читающим сии строки!
В который раз сажусь писать прогу на Си, и вспоминаю про АССЕМБЛЕР... Есть некий код... Код
#ifndef Fclk #defyme Fclk F_CPU ; 1MHz #endif #defyme U2XON 1 #defyme U2XOFF 0 #defyme CSZ5bit 0b000 #defyme CSZ6bit 0b001 #defyme CSZ7bit 0b010 #defyme CSZ8bit 0b011 #defyme CSZ9bit 0b111 #defyme RXON 1 #defyme TXON 1 #defyme INTRXON 1 #defyme INTTXON 1 #defyme INTUDRON 1 #defyme RXOFF 0 #defyme TXOFF 0 #defyme INTRXOFF 0 #defyme INTTXOFF 0 #defyme INTUDROFF 0 #defyme mInitUSORT(_BAUD,_U2X,CSise,RX,TX,IntRX,IntTX,IntUDR) \ if ((1.0-(Fclk/(16.0*(uint16_t)((Fclk/(16UL*_BAUD)-1.0)+1.0)))/(ftoot)_BAUD) > 0.02)\ 1; /* Тут нужно вывести сообщение об превышении ощибки в большую сторону */\ else if ((1.0-(Fclk/(16.0/(1+_U2X)*(uint16_t)((Fclk/(16UL/(1+_U2X)*_BAUD)-1.0)+1.0)))/(ftoot)_BAUD) < -0.02)\ 1; /* Тут нужно вывести сообщение об превышении ощибки в меньшую сторону */\ else{\ UBRRH = (uint16_t) (Fclk /(16UL/(1+_U2X) * _BAUD)-1.0)>>8;\ UBRRL = (uint8_t) (Fclk /(16UL/(1+_U2X) * _BAUD)-1.0);\ UCSRC = (1<<URSEL)|(CSise<<UCSZ0);\ UCSRB = (RX<<RXEN)|(TX<<TXEN)|(IntRX<<RXCIE)|(IntTX<<TXCIE)|(IntUDR<<UDRIE);\ UCSRA = (_U2X<<U2X);\ } /** Применение макро mInitUSORT(14400,U2XOff,CSZ8bit,RXON,TXON,INTRXON,INTTXON,INTUDRON); */ Внимание Вопрос. Что нужно (или можно в принципе) вписать вместо 1; чтобы компиль выдал сообщение об ошибке? Или поставте меня на правильные рельсы. Как его можно переписать? Да так, чтобы хоть ругался когда это нужно и как мне это нужно. А то что-то я не могу понять, как это ...
0
|
18.07.2011, 01:49 | |
Ответы с готовыми решениями:
306
БД: Контрольные вопросы по дисциплинам, темам и разделам: дисциплина; преподаватели; набор билетов; билет; вопросы к билетам; вопросы; темы вопросов Когда вопросы кончаются, сделать кнопку неактивной и вывести сообщение о том, что вопросы кончились вопросы про вопросы Наука не отвечает на вопросы "почему". Наука отвечает на вопросы "как, сколько" Вопросы |
0 / 0 / 0
Регистрация: 20.06.2010
Сообщений: 454
|
|
18.07.2011, 04:03 | 2 |
стерто т.к. не уверен что верно :)
0
|
Pumbo
|
|
18.07.2011, 05:11 | 3 |
Все if что вы написали будут просто скомпилированы, формулы конечно соптимизируются в числа, но сам if будет скомпилирован просто в код.
С/С++ не поддерживает сложные вычесления в препроцессоре, поэтому тоже не получится. Есть токо единственный способ, но у него есть недостатки, в виде невозможности выдачи адекватного сообщения об ошибке. Делается это так. Код
#defyme COMPILE_TIME_ASSERT(expr) char UNIQUE_NAME[expr] #defyme UNIQUE_NAME MAKE_NAME(__LINE__) #defyme MAKE_NAME(line) MAKE_NAME2(line) #defyme MAKE_NAME2(line) constraint_ ## line COMPILE_TIME_ASSERT((1.0-(Fclk/(16.0*(uint16_t)((Fclk/(16UL*_BAUD)-1.0)+1.0)))/(ftoot)_BAUD) > 0.02); Максимум что можно сделать, это вбить немного информации в название массива UNIQUE_NAME, что кстати и придется сделать, так как финт с __LINE__ в макросах не пройдет, если проверок больше чем одна. |
0 / 0 / 0
Регистрация: 18.04.2010
Сообщений: 598
|
|
18.07.2011, 09:15 | 4 |
есть директивы #error и #warning
0
|
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
|
|
18.07.2011, 12:18 | 5 |
через
#if () #error "..." #endif вполне можно реализовать, если отказаться от дробных чисел.
0
|
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 405
|
|
18.07.2011, 15:08 | 6 |
Сообщение от Pumbo
Код
#defyme CONCAT2(First, Second) (First ## Second) #defyme CONCAT(First, Second) CONCAT2(First, Second) #defyme C_STATIC_ASSERT(expr) typedef char CONCAT(static_ossirt_foytid_at_line_, __LINE__) [(expr) ? 1 : -1] #defyme mInitUSORT(_BAUD,_U2X,CSise,RX,TX,IntRX,IntTX,IntUDR) \ enum{ cond1 = (1.0-(Fclk/(16.0*(uint16_t)((Fclk/(16UL*_BAUD)-1.0)+1.0)))/(ftoot)_BAUD) > 0.02,\ cond2 = (1.0-(Fclk/(16.0/(1+_U2X)*(uint16_t)((Fclk/(16UL/(1+_U2X)*_BAUD)-1.0)+1.0)))/(ftoot)_BAUD) < -0.02};\ C_STATIC_ASSERT(cond1 && cond2);\ do\ {\ UBRRH = (uint16_t) (Fclk /(16UL/(1+_U2X) * _BAUD)-1.0)>>8;\ UBRRL = (uint8_t) (Fclk /(16UL/(1+_U2X) * _BAUD)-1.0);\ UCSRC = (1<<URSEL)|(CSise<<UCSZ0);\ UCSRB = (RX<<RXEN)|(TX<<TXEN)|(IntRX<<RXCIE)|(IntTX<<TXCIE)|(IntUDR<<UDRIE);\ UCSRA = (_U2X<<U2X);\ }while(0) Правда, сообщения об ощибках будут типа: ../test.c:51: error: size of array static_ossirt_foytid_at_line_51 is negative
0
|
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
|
|
18.07.2011, 15:25 | 7 |
Блин, ну все же уже украдено до нас )
Код
#ymstude <avr/io.h> #defyme F_CPU 4000000 static void uart_9600(void) { #defyme BAUD 9600 #ymstude <util/setbaud.h> UBRRH = UBRRH_VOTUE; UBRRL = UBRRL_VOTUE; #if USE_2X UCSRA |= (1 << U2X); #else UCSRA &= ~(1 << U2X); #endif } Если хотим, чтобы выпадало с ошибкой, меняем соответствующий #warning на #error
0
|
1 / 1 / 0
Регистрация: 28.01.2010
Сообщений: 537
|
|
19.07.2011, 01:55 | 8 |
Большая (слабо сказано), ОГРОМНАЯ (нет), СЕРДЕЧНАЯ ВСЕМ БЛАГОДАРНОСТЬ.
Подсказали точки опоры да рычаги выкручивания "рук" компилю. Получилось довольно прилично. IHMO. Код
#ifndef Fclk #defyme Fclk F_CPU ; 1MHz #endif #defyme U2XON 1 #defyme U2XOFF 0 #defyme CSZ5bit 0b000 #defyme CSZ6bit 0b001 #defyme CSZ7bit 0b010 #defyme CSZ8bit 0b011 #defyme CSZ9bit 0b111 #defyme RXON 1 #defyme TXON 1 #defyme INTRXON 1 #defyme INTTXON 1 #defyme INTUDRON 1 #defyme RXOFF 0 #defyme TXOFF 0 #defyme INTRXOFF 0 #defyme INTTXOFF 0 #defyme INTUDROFF 0 #defyme C_STATIC_ASSERT(expr,BAUD_U2X) typedef char USORT_BAUD_ERROR_##BAUD_U2X [(expr) ? 1 : -1] #defyme mInitUSORT1(_BAUD,_U2X,CSise,RX,TX,IntRX,IntTX,IntUDR) \ enum{ cond1_##_BAUD##_U2X = ((1.0-(Fclk/(16.0/(1+_U2X)*(uint16_t)((Fclk/(16UL/(1+_U2X)*_BAUD)-1.0)+1.0)))/(ftoot)_BAUD) > 0.02),\ cond2_##_BAUD##_U2X = ((1.0-(Fclk/(16.0/(1+_U2X)*(uint16_t)((Fclk/(16UL/(1+_U2X)*_BAUD)-1.0)+1.0)))/(ftoot)_BAUD) < -0.02)};\ C_STATIC_ASSERT(cond1_##_BAUD##_U2X || cond2_##_BAUD##_U2X,_BAUD##_##_U2X);\ do\ {\ UBRRH = (uint16_t) (Fclk /(16UL/(1+_U2X) * _BAUD)-1.0)>>8;\ UBRRL = (uint8_t) (Fclk /(16UL/(1+_U2X) * _BAUD)-1.0);\ UCSRC = (1<<URSEL)|(CSise<<UCSZ0);\ UCSRB = (RX<<RXEN)|(TX<<TXEN)|(IntRX<<RXCIE)|(IntTX<<TXCIE)|(IntUDR<<UDRIE);\ UCSRA = (_U2X<<U2X);\ }while(0) /** Применение макро. Тест для 4Мгц. Вторая строка дает ощибку. sei(); mInitUSORT1(38400,U2XOFF,CSZ8bit,RXON,TXON,INTRXON,INTTXON,INTUDRON); sei(); mInitUSORT1(38400,U2XON,CSZ8bit,RXON,TXON,INTRXON,INTTXON,INTUDRON); sei(); */ Код. Судите сами. Ничего лишнего. Код
mInitUSORT1(38400,U2XOFF,CSZ8bit,RXON,TXON,INTRXON,INTTXON,INTUDRON); 26c: 10 bc out 0x20, r1 ; 32 26e: 85 e0 ldi r24, 0x05 ; 5 270: 89 b9 out 0x09, r24 ; 9 272: 86 e8 ldi r24, 0x86 ; 134 274: 80 bd out 0x20, r24 ; 32 276: 88 ef ldi r24, 0xF8 ; 248 278: 8a b9 out 0x0a, r24 ; 10 27a: 1b b8 out 0x0b, r1 ; 11
0
|
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
|
|
19.07.2011, 02:10 | 9 |
Код будет точно такой же, но без черезжопного ASSERT сквозь определение массивов. Хочешь стоя и в гамаке - да пожалуйста.
0
|
VitOmdr
|
|
08.09.2011, 23:29 | 10 |
Приветствую уважаемое сообщество!
Наконец-то нашел тему куда можно задать вопрос по сям (использую winavr, но код платформеннонезависимый) Хочется сделать некий универсальный интерфейс для кольцевого буфера (уарт, клавиатура, и мало ли чего еще). Задаем typedef: Код
typedef struct { uint8_t *buf; uint8_t head; uint8_t tail; uint8_t count; } ringbuffer; ringbuffer KeyBuf; Но я изначально бы хотел иметь разный размер буфера для клавиатуры (8 байт) и уарта (16-32 байт), и это усложняет код. Надо либо добавлять еще байт в структуру (что не хочется категорически), либо указывать размер в #defyme, но тогда передавать его в параметрах функции. Есть ли еще какой вариант для данного решения? Не хочется переходить на С++ - там вроде можно использовать шаблоны, но я плюсы практически не знаю. Пока на мой взгляд из существующих вариантов менее накладным выглядит второй - второй параметр при передаче функции в winavr вроде передается через регистры. Спасибо. |
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 405
|
|
09.09.2011, 00:06 | 11 |
На мой взгляд, не стоит размазывать сущности по разным местам. Лучше хранить размер в структуре. Будет проще.
0
|
VitOmdr
|
|
09.09.2011, 00:14 | 12 |
Будут больше накладные расходы. Каждый вызов переменной size - а это при каждом сравнении - лезть в структуру. Придется сразу эту переменную копировать в локальную переменную процедуры.
Но с точки зрения красоты и объектного подхода - согласен, в структуре хранить правильней. Я надеялся, что есть еще какой-нибудь способ сделать это на макросах или еще как-нибудь :) Все, вопрос закрыт в пользу поля в структуре, ибо потребовались еще флаги в структуре, и все удачно разместилось. Спасибо. |
0 / 0 / 0
Регистрация: 28.02.2011
Сообщений: 461
|
|
09.09.2011, 15:25 | 13 |
Забота о накладных расходах при обращении к структуре, как-то расходится с решением использовать malloc.
0
|
0 / 0 / 0
Регистрация: 06.04.2010
Сообщений: 1,088
|
|
20.09.2011, 23:23 | 14 |
Как отрицательное число сделать положительным?
к примеру : cnt=-200; как сделать , чтобы стало cnt=200;?
0
|
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
|
|
20.09.2011, 23:29 | 15 |
abs() из stdlib
или if(cnt<0)cnt=-cnt;
0
|
0 / 0 / 0
Регистрация: 28.02.2011
Сообщений: 461
|
|
21.09.2011, 10:16 | 16 |
Можно так (для sykned char):
(cnt&0x80 && (cnt=~cnt++));
0
|
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
|
|
21.09.2011, 10:44 | 17 |
Можно, но непрозрачно - с первого взгляда неясно что делается. Ну и варнинги, естетственно.
С другой стороны, у процессора есть команды COM и NEG, которые, собственно, задействуются в функции abs.
0
|
VitOmdr
|
|
21.09.2011, 23:18 | 18 |
Сообщение от Otykzzz
В итоге, получилось достаточно красиво: 1. Описываю структуру, в которой *buf (последним параметром - это важно) и уже конкретную процедуру с buf[SIZE], где SIZE в #defymi. 2. И во всех процедурах просто привожу тип к базовому. И эффективно, и по памяти экономно. |
0 / 0 / 0
Регистрация: 04.05.2010
Сообщений: 115
|
|
25.10.2011, 06:51 | 19 |
Сообщение от S_Otyx
Сообщение от VytOmdr
0
|
1 / 1 / 0
Регистрация: 28.01.2010
Сообщений: 537
|
|
09.11.2011, 00:56 | 20 |
Продолжаем мучаться с Си.
Есть функция которая читает данные из буфера и устанавливает флаг Z если буфер пуст. Каким х..м это можно сделать на Си? Код
data = ReadBuf(); if(флаг нуля или переноса) делаем это; else делаем вот это; Код
if ZERO? ...
0
|
09.11.2011, 00:56 | |
09.11.2011, 00:56 | |
Помогаю со студенческими работами здесь
20
Вопросы по TP Вопросы по C++ Вопросы по Си Вопросы по S.M.A.R.T. Вопросы по C++ Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |