Страница 198 из 386

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

Добавлено: Пт июн 27, 2014 10:06:44
WiseLord
Кстати, возможно, есть смысл хранить не весь массив, а только пару-тройку коэффициентов.

Если зависимость линейная - то R = a1 * T + a0.

Нелинейная зависимость, возможно, достаточно хорошо будет аппроксимироваться параболой R = a2 * T * T + a1 * T + a0.

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

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

Добавлено: Пт июн 27, 2014 10:51:54
urry
от себя добавлю, что вероятность повреждения данных в епром очень высокая - нужно данные дублировать и закрывать контрольной суммой.

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

Добавлено: Пт июн 27, 2014 10:59:12
Pink-Pank
Это уж сверхмера. Думаю, вопрошающему в его применении такие усложнения ни к чему. )) Хотя, ради тренеровки можно было бы замутить. ;)

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

Добавлено: Пт июн 27, 2014 11:57:18
kelod
ibiza11 писал(а):
kelod писал(а):это храню массивом... задаю его самостоятельно, при создании массива
Приведите код, который вы пишете для этого. Я вам покажу, где там размер массива.

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

uint32_t EEPROM mass[]={177, 192,240};
значений намного больше, около 15
WiseLord писал(а):Кстати, возможно, есть смысл хранить не весь массив, а только пару-тройку коэффициентов.
зависимость не линейная и не квадратичная, скорее похожа на логарифм, интерполирование или слишком сложное или не удовлетворяет точности, поэтому после долгих размышлений принял решение о линейной интерполяции относительно двух ближайших точек
urry писал(а):вероятность повреждения данных в епром очень высокая
перезапись будет происходить очень редко, только при смене датчика

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

Добавлено: Пт июн 27, 2014 12:01:49
ibiza11

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

uint32_t EEPROM mass[]={177, 192,240};
#define MASS_SIZE (sizeof(mass)/sizeof(uint32_t))
uint32_t massSize = MASS_SIZE;

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

Добавлено: Пт июн 27, 2014 13:13:04
aam
Всем спасибо, все получилось. Сделал так:

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

#define STR(s) #s
#define TO_STR(s) STR(s)

char __flash start0[]="MDIOv1.0 LD" TO_STR(LD_NUM)
***
kelod писал(а):но я думал можно узнать количество элементов, как это есть в обычном си
В обычном си вы тоже не создадите просто так массив произвольной длины. Размер массива в си определяется на этапе компиляции.

В вашем случае размер лучше хранить не в 1-й ячейке ЕЕПРОМ (легко забыть поменять размер), а ввести завершающий символ, который не встречается в реальных данных (например, 0 или 0xFF). И просто просматривать всю таблицу, пока не наткнетесь на этот символ. Если опасаетесь за быстродействие, просматривайте таблицу 1 раз при включении питания и запоминайте в ОЗУ ее размер в переменной.
urry писал(а):от себя добавлю, что вероятность повреждения данных в епром очень высокая
Почему?

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

Добавлено: Сб июн 28, 2014 00:04:35
menzoda
urry писал(а):от себя добавлю, что вероятность повреждения данных в епром очень высокая - нужно данные дублировать и закрывать контрольной суммой.
Могу сказать, что если данные записываются/читаются не очень интенсивно, то с надежностью все хорошо (а на них никто и не будет писать интенсивно, циклов перезаписи же мало). У нас много лет используется по несколько EEPROM в составе частотного инвертора (условия не лучшие), за все время был только один зарегистрированный косяк.

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

Добавлено: Ср июл 02, 2014 09:06:53
aam
Скажите, а можно ли использовать return; в прерываниях?
Ато тут у меня какая-то фигня получается в нештатных ситуациях. Использую библиотеку протокола wake, так если слишком часто слать запросы от компа, то МК виснит и бесконца вызывает прерывание по поступлению данных в приемник УАРТ. Причем не отвисает когда уже я слать данные перестал. Сторожевой таймер тоже не оживляет МК - без конца вызывается прерывание, хотя я смотрел - флаг того, что UDR полон - уже сброшен.
menzoda писал(а):если данные записываются/читаются не очень интенсивно, то с надежностью все хорошо (а на них никто и не будет писать интенсивно, циклов перезаписи же мало)
А я тут девайс с пультом от телека сделал, особых мер, кроме проверки на допустимость значения, не принимал. Вот теперь думаю, а это правильно?

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

Добавлено: Ср июл 02, 2014 09:38:12
ARV
aam писал(а):Скажите, а можно ли использовать return; в прерываниях?
Ато тут у меня какая-то фигня получается в нештатных ситуациях. Использую библиотеку протокола wake, так если слишком часто слать запросы от компа, то МК виснит и бесконца вызывает прерывание по поступлению данных в приемник УАРТ. Причем не отвисает когда уже я слать данные перестал.
а каким боком return может быть связан с вашей бедой?! avr-gcc не нуждается в return в обработчике прерываний, но и при наличии ничего не ухудшается - плевать он хотел на return. на счет других компиляторов не скажу, не знаю.

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

Добавлено: Ср июл 02, 2014 09:46:14
WiseLord
ARV писал(а):плевать он хотел на return
Наверное, корректнее сказать, что обработчик прерывания отработает return как и обычная void-фунция, коей он, по большому счёту, и является.

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

Добавлено: Ср июл 02, 2014 10:27:34
aam
С return понятно уже...
Непонятно другое. Вот щас завел сторожевой таймер. При этом глюке 1 раз срабатывает ватчдог, проц ресетится и начинает выполнять прогу. Но сразу после команды sei начинает беспорядочный вызов прерывания по приему данных, хотя данные УЖЕ не передаются (это видно на осциллографе и терминале Протеуса), бесконечно выскакивает сообщение
Reading from UDR1 while no data received.
При этом регистры имеют значения:
UBBR1H=0
UBBR1L=0x07
UCSR1A=0x20
UCSR1B=0xD8
UCSR1C=0x06
UDR1=0
Прерывание таймера 0, тактирующее прогу, при этом вызывается как и положено.

Не могу понять, это глюк Протеуса или косяк проги?

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

Добавлено: Чт июл 03, 2014 11:33:47
pokk
Здравствуйте, решил я сделать отладку по uart. Т.е расставить контрольные точки в программе и смотреть в терминале как они выполняются ). Естественно что в готовом варианте эта отладка не нужна и чтобы каждый раз не удалять сделал через

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

#if __DEBUG__
....
#endif  
Но в итоге получается не сильно удобный код. Можно ли его как-то ужать до 1 функции ?

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

#if __DEBUG__      
if(debug_ON_OFF==ON){ // вкл/выкл по usart
    USART_SendStr("INIT:......\0"); 
}
#endif   
Пробовал внести #if __DEBUG__ #endif внутрь функции, но после выключения отладчика функция всё равно остаётся хоть она и пустая но это неприемлемо.

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

Добавлено: Чт июл 03, 2014 13:02:04
ibiza11

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

#if __DEBUG__ 
   debug_send_str("INIT:...");
#endif 

//...

void debug_send_str(char * str){
   if(debug_ON_OFF==ON){ // вкл/выкл по usart
      USART_SendStr(str);
   }
}
так?) чего вы добиться то хотите?

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

Добавлено: Чт июл 03, 2014 13:12:10
menzoda
Не так. Вот так:

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

extern void UartSend(const char *msg);

...

#ifdef __DEBUG
    #define Trace(x)    UartSend(x)
#else
    #define Trace(x)
#endif

...

void main(void)
{
    Trace("Hello");
    Trace("World");
}

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

Добавлено: Чт июл 03, 2014 14:27:58
pokk
menzoda, во то что надо. А если UartSend(x) с переменным числом параметров ? Типа функции printf();

чего вы добиться то хотите?
Что бы можно было писать так.

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

DEBUG("ERROR1");
DEBUG("ERROR1",var1);
DEBUG("ERROR2",var2,var3);
DEBUG("ERROR3",var4,var5,var6);
А в готовом варианте что бы можно было убрать/вернуть с минимальными трудозатратами =)

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

Добавлено: Чт июл 03, 2014 15:47:20
virus33
Вопрос тупенький, но все же.
есть два камня которые должны общатся по uart. изначально была следующая мысль - шлем 1 байт на скорости 9600 ввиде 0b0000xxxx, где хххх - состояние уровней на входах RB4-RB7, остальные биты пока не используются.
Создал массив типа short int, по таймеру (1 секунда) в нужные ячейки записывал состояние уровней, сформированный байт отправил в путешествие. По приходу данного байта через сдвиговый регистр хотел так же развалить в подобный массив, чтобы
обработать полученную информацию. Но к сожалению ничего не получилось, компилятор(HI-Tech) выдал следующие предупреждения:
Warning [360] C:\Users\Enter\Documents\pic\sender\main.c; 90.8 array index out of bounds
Warning [358] C:\Users\Enter\Documents\pic\sender\main.c; 111.17 illegal conversion of pointer to integer
банально не знаю как сформировать байт из массива. Подскажите кто знает, заранее благодарен.

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

Добавлено: Чт июл 03, 2014 15:54:39
Pink-Pank
Судя по ругательствам компилятора, Вы запихиваете в массив больше переменных, чем его размер. И пытаетесь указатель (адрес) преобразовать в целое. Чтобы это сделать, нужно указатель разыменовать (т.е. получить значение по его адресу операцией *)

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

Добавлено: Чт июл 03, 2014 16:12:44
BorisSPB
virus33, сколько элементов в массиве? Не следует забывать что в PIC память распределена по банкам и индексный регистр 8 бит, так что ругается на ограничение непрерывного пространства в банке или индекс больше 255.
У HI-TECH short int 16 бит, так что размер массива таких элементов может быть не больше 32.

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

Добавлено: Чт июл 03, 2014 16:48:39
ARV
pokk писал(а):Что бы можно было писать так.

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

DEBUG("ERROR1");
DEBUG("ERROR1",var1);
DEBUG("ERROR2",var2,var3);
DEBUG("ERROR3",var4,var5,var6);
А в готовом варианте что бы можно было убрать/вернуть с минимальными трудозатратами =)
GCC поддерживает макросы с переменным числом параметров:
#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

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

Добавлено: Чт июл 03, 2014 17:02:24
virus33
код убогий, но как то так.

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

unsigned short int array[8];
///////////////////////////////////////////////////////////////////////////////////
void send_Usart(unsigned char e) //	Отправка байта
{
	while(TXIF!=1)	//	Устанавливается, когда регистр свободен
	{}
	TXREG = e;	
}

unsigned char getch_Usart(void)//	Получение байта
{
	while(!RCIF)	//	Устанавливается, когда регистр не пуст.
		continue;
	return RCREG;
}


void interrupt send_data(void)
{
if (T0IF == 1)
	{
	RA2 = ~RA2;
	array[0]=0;
	array[1]=0;
	array[2]=0;
	array[3]=0;
	array[4]=0;
	array[5]=0;
	array[6]=0;
	array[7]=0;
		if (com_0==1)
		{
		array[0]=1;
		} 
	
		if (com_1==1)
		{
		array[1]=1;
		} 
	
		if (com_2==1)
		{
		array[2]=1;
		} 
	
		if (com_3==1)
		{
		array[3]=1;
		} 
	
	send_Usart(*array);
	TMR0 = 1;
	T0IF = 0;					
	}

//	if (TMR2IF == 1)										//таймер 2 - говорим что соединение присутствует
//	{
//	RA2 = ~RA2;			
//	send_Usart(0b00000001);
//	TMR2 = 1;
//	T2CKPS0 = 0; T2CKPS1 = 1; 								//делим тактовую частоту на 4
//	TOUTPS0 = 0; TOUTPS1 = 0; TOUTPS2 = 1; TOUTPS3 = 0; 	//выходной делитель на 5
//	TMR2IF = 0;												// сброс флага
//	}

}
но в протеусе не вижу изменений при подаче уровней на входы мк
вот кстати вопрос, терминал показывает только определенные символьные коды, осцилограф как то странно отображает передачу по uart, есть ли еще способы посмотреть что на выходе имеется?