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

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

Добавлено: Пн сен 03, 2012 22:52:41
HHIMERA
Аlex писал(а):
HHIMERA писал(а):Очень смелое заявление... :))
А что, я не прав ? :))
ПисАли не дураки... а пользователи разные бывают... бывает по ошибке, бывает по недопониманию или незнанию...
Ограничения и нюансы то присутствуют...

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

Добавлено: Вс сен 09, 2012 11:37:07
phanis
Не знаю на сколько я правильно ставлю вопрос, но он таков:
Можно ли как нибудить сделать такой союз структуры и массива чтобы при фомировании ответа на запрос (например модбаса но не обязательно) от МК элемент Data был переменной длинны, но при этом элемент СRC был всегда в конце ответа,ну т.е. сам ответ тоже переменной длинны ?
Что типа этого.

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

union{
unsigned char Buffer[100];
struct{
unsigned char Addr;
unsigned char Command;
unsigned char *Data;//элемент переменный длинны
unsigned int *CRC16;
};
}PAKET;

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

Добавлено: Вс сен 09, 2012 14:24:39
vitalik_1984
Ну для начала длина с одной буквой н пишется.
А чтобы даже передать массив разной длины нужно обозначить ее самую эту длину.

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

Добавлено: Вс сен 09, 2012 14:45:59
Goldsmith
phanis писал(а):Можно ли как нибудить сделать такой союз структуры и массива чтобы при фомировании ответа на запрос (например модбаса но не обязательно) от МК элемент Data был переменной длинны, но при этом элемент СRC был всегда в конце ответа,ну т.е. сам ответ тоже переменной длинны ?
Если я правильно понял вопрос, Вас интересует структура вроде [заголовок пакета][тело пакета переменной длины][CRC]?

В соответствии со стандартом C99 (§6.7.2.1 п. 16):
As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.
"Гибкий" массив (т.е. массив, размер которого неизвестен во время компиляции) обязан быть последним членом структуры, добавить после него CRC не получится. Вам придется самостоятельно выудить значение CRC как 2 (или 4, или какую Вы там длину CRC используете) последних байта этого массива. Компилятор тут не помощник, он обязан знать смещение каждого члена структуры во время компиляции.

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

Добавлено: Вс сен 09, 2012 17:09:38
Davydov
Доброго всем времени суток!
Помогите пожалуйста прояснить, как грамотнее сделать:
На INT0 приходил лог. 1, срабатывает прерывание, внутри прерывания АЦП преобразует значение и далее над ним производятся некие операции:

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

interrupt [2] void INT_0(void) //Обработка прерывания
{
 delay_us(10);
 ADCSRA = (1 << ADSC);
 while ((ADCSRA&(1 << ADIF))== 0);
 GET_ADC = (ADCL|ADCH << 8);
...

...операции над значением...

... 
}        
Заранее благодарен за ответ :beer:

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

Добавлено: Вс сен 09, 2012 17:42:02
vitalik_1984
Для начала не нужно в прерывании ждать пока появится результат ацп, можно сделать запуск ацп, а потом в прерывании ацп считать значение, и если вычисления на связаны с делением или выводом на экран, то можно их сделать тут.
А вот это совсем тут не нужно.

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

delay_us(10);

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

Добавлено: Вс сен 09, 2012 17:55:10
Davydov
vitalik_1984 писал(а):Для начала не нужно в прерывании ждать пока появится результат ацп, можно сделать запуск ацп, а потом в прерывании ацп считать значение

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

delay_us(10);
Просто тут такая штука, что напряжение на АЦП появляется вместе с прерыванием INT0. Тогда у меня ещё вопрос, а как тогда лучше сконфигурировать запуск АЦП? Непрерывное преобразование или по внешнему прерыванию INT0, а если по INT0 тот как он себя поведёт? МК - mega8

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

Добавлено: Вс сен 09, 2012 19:29:44
vitalik_1984
Так и делайте

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

iinterrupt [EXT_INT0] void ext_int0_isr(void)
{
 ADCSRA = (1 << ADSC);
} 
 

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

unsigned int adc_data;
interrupt [ADC_INT] void adc_isr(void)
{
// Read the AD conversion result
adc_data=ADCW;
// Place your code here
} 
void main(void)
{...........
..............
while(1){
if(adc_data){
//.........вычисления........
adc_data=0;
}
 

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

Добавлено: Чт сен 13, 2012 15:32:42
eess9
Привет всем!
Вопрос следующий. Есть кусок кода который принимает команды от RC5 пульта. Игнорируется все кроме команды (последние 5 бит). Далее эта переменная (command) по USART передается на комп. Код USART рабочий, принимал с компа данные и посылал их обратно; прием и передача работает. Но на комп приходят постоянно ноли от RC5. Следовательно бок в куске обработки сигнала с пульта. Внешнее прерывание настроено на любое изменение уровня сигнала от TSOP.
Спойлер

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

EMPTY_INTERRUPT(BADISR_vect)
 
#define Tmin 40 
#define Tmax 68  
#define TminK 22 
#define TmaxK 34 

uint8_t i = 0,j=0;
unsigned char sct_bit = 0;     
unsigned char RC5_buffer; 
uint8_t centre =  0;              
uint8_t not_korr = 0;             
unsigned char Timer = 0;           
unsigned char command = 0;    

void rc5_ti_stop(void)
{       
   	GIMSK|=0x00;
   	TCCR0B = 0x00;
   	TCNT0 = 0;
   	sct_bit = 0;
} 

ISR(INT0_vect)
{
	Timer = TCNT0;   
	TCNT0 = 0;     
	not_korr = 1;                         
	if(sct_bit==0)
	{
		//PORTD^=(1<<PD4);
     	TCCR0B = 0x04;
		if ((PIND & (1 << PD2)) == 0)
			RC5_buffer^=1<<sct_bit;
        sct_bit++;            
        centre = 1;           
    }
	else
	{ 
     	if ((Timer>TminK)&&(Timer<TmaxK))
		{  
			//PORTD^=(1<<PD5);
         	if (centre)
			{
             	centre = 0;
                not_korr = 0; 
            }
			else
			{
                centre = 1;
				if ((PIND & (1 << PD2)) == 0)
					RC5_buffer^=1<<sct_bit;
                sct_bit++;
                not_korr=0;
            }
		} 
        if ((Timer>Tmin)&&(Timer<Tmax))
		{
			//PORTD^=(1<<PD6);
         	if ((PIND & (1 << PD2)) == 0)
				RC5_buffer^=1<<sct_bit;
            sct_bit++;
            not_korr = 0;
        }                              
        if (not_korr == 1)
		{             
        	rc5_ti_stop();   
            RC5_buffer = 0;     
        }
        if (sct_bit == 14)
		{  
			//PORTD^=(1<<PD4);     
            command=0;
			rc5_ti_stop();
			j=0; 
			for (i=13;i>7;i--)
			{
				if(bit_is_set(RC5_buffer, i))
					command^=1<<j;
				j++;
			} 
			RC5_buffer = 0; 
			EIFR=0x40;   
        }                                                                         
 	}    
}

ISR(TIMER0_OVF_vect)
{   
	rc5_ti_stop();        
	RC5_buffer = 0;        
	GIMSK|=0x40; 
	EIFR=0x40;  
} 
Может кто заметит ошибку? Буду признателен.

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

Добавлено: Чт сен 13, 2012 18:55:39
menzoda
Не нашел раздела с алгоритмами, поэтому спрошу здесь.

Есть программный демодулятор FSK. На его выходе получаю сигнал, который необходимо привести к окончательному виду с двумя уровнями 0 и 1:
Изображение

В нормальном случае я получаю сигнал как на верхней картинке. Выделить из него цифровой очень просто: больше нуля - "1", меньше - "0". Ну можно еще ввести некоторый гистерезис.
В случае некоторых помех сигнал становиться, как на второй картинке - меньше по амплитуде и смещенный вверх (вниз). Теперь я уже не могу использовать простое правило "больше нуля - 1, меньше - 0". Мне необходимо как-то опустить сигнал на свое место. Как можно это сделать?

П.С.: Пробовал некоторые виды ФВЧ. Работает хорошо, но я не могу его использовать: при необходимых параметрах возникает переполнение (плавающей точки в МК к сожалению нет).

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

Добавлено: Чт сен 13, 2012 21:29:02
ut1wpr
Правила форума читали? На счёт оформления постов?
ploop




Зависит от частоты. Простейший путь, уйти от действующей постоянной составляющей разделительным конденсатором. А вход АЦП подвязать к исуксственно созданой средней точке между 0 и VCC. Грубо, но иногда работает. Повторяю, от частоты и формы сигнала сильная зависимость.

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

Добавлено: Чт сен 13, 2012 21:43:42
vitalik_1984
eess9 писал(а): Может кто заметит ошибку? Буду признателен.
Для начала сравните чем отличаются две процедуры обработки прерывания.
Спойлер

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

 
EMPTY_INTERRUPT(BADISR_vect)
 
#define Tmin 40 
#define Tmax 68  
#define TminK 22 
#define TmaxK 34 

uint8_t i = 0,j=0;
unsigned char sct_bit = 0;     
unsigned char RC5_buffer; 
uint8_t centre =  0;              
uint8_t not_korr = 0;             
unsigned char Timer = 0;           
unsigned char command = 0;    

void rc5_ti_stop(void)
{       
      GIMSK|=0x00;
      TCCR0B = 0x00;
      TCNT0 = 0;
      sct_bit = 0;
}  
Удивительно как ваш компилятор это мог пропустить.Даже без компиляции понятно, что она закончится крахом.
И снабдите ваш код комментариями, может сами ошибку найдете.
Такое ощущение, что из CVAVR код частями слизан.
Что за волшебные числа?

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

 EIFR=0x40; 
 
Следующая запись не произведет никакого эффекта.

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

GIMSK|=0x00; 
 
для очистки бита нужно и (&) а не или(|)
в данном случае можно было вообще присвоить 0x00

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

Добавлено: Чт сен 13, 2012 21:49:46
Goldsmith
menzoda писал(а):Мне необходимо как-то опустить сигнал на свое место. Как можно это сделать?
  • 1. Определяем пиковые значения Umin, Umax.
  • 2. Вычисляем размах сигнала Upp=Umax-Umin и среднее значение Umid=(Umax+Umin)/2.
  • 3. Убираем постоянную составляющую, нормируем амплитуду: Uout=(Uin-Umid)*K/Upp
Хотя лично я предпочел бы убрать постоянную составляющую аппаратно, разделительным конденсатором или трансформатором.

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

Добавлено: Чт сен 13, 2012 22:17:00
menzoda
Goldsmith писал(а):
menzoda писал(а):Мне необходимо как-то опустить сигнал на свое место. Как можно это сделать?
  • 1. Определяем пиковые значения Umin, Umax.
  • 2. Вычисляем размах сигнала Upp=Umax-Umin и среднее значение Umid=(Umax+Umin)/2.
  • 3. Убираем постоянную составляющую, нормируем амплитуду: Uout=(Uin-Umid)*K/Upp
Хотя лично я предпочел бы убрать постоянную составляющую аппаратно, разделительным конденсатором или трансформатором.
Аппаратно никак, весь демодулятор программный. А насчет максимума я тоже думал, но тут возникает сложность вычисления этого максимума. Сигнал то идет непрерывно, и мне понадобится движущееся окно, в котором я буду измерять максимум и минимум. В голову приходит только вариант с массивом значений (наше окно), добавлением очередного значения, выкидыванием старого, и расчетом новых мин. макс. на всем массиве. Сложновато...

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

Добавлено: Чт сен 13, 2012 22:26:47
Goldsmith
menzoda писал(а):мне понадобится движущееся окно, в котором я буду измерять максимум и минимум.
Совершенно верно. Заводим кольцевой буфер на один-два периода, заносим в него разумное количество отсчетов (думаю, 8 или 16 должно хватить).
menzoda писал(а):В голову приходит только вариант с массивом значений (наше окно), добавлением очередного значения, выкидыванием старого, и расчетом новых мин. макс. на всем массиве. Сложновато...
В кольцевом буфере новое значение автоматически затрет самое старое. А если не делать буфер слишком большим, то и искать в нем не будет накладно. Нам ведь главное - не пропустить верхнюю и нижнюю горизонтальные площадки, несколько отсчетов за период вполне хватит.

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

Добавлено: Чт сен 13, 2012 23:15:34
спящий
че за?) только что начал осваивать С++,и поторю вопрос че за .... ошибка?и как ее исправить?

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

Добавлено: Пт сен 14, 2012 00:14:48
спящий
все разобрался ошибка была в том что я неподключил sours к проекту,но сейчас я немогу откомпелировать,почему?может быть это иззо неправильной установки проги,открыл другой проект пытался изменить таже фигня.

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

Добавлено: Пт сен 14, 2012 01:08:35
спящий
нашел косяк -прога косячная,а в протеусе програ написанная на С пошагово отлаживается? каким файлом(расширением) тогда прошивать?

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

Добавлено: Пт сен 14, 2012 04:15:20
КРАМ
Goldsmith писал(а):
menzoda писал(а):Мне необходимо как-то опустить сигнал на свое место. Как можно это сделать?
  • 1. Определяем пиковые значения Umin, Umax.
  • 2. Вычисляем размах сигнала Upp=Umax-Umin и среднее значение Umid=(Umax+Umin)/2.
  • 3. Убираем постоянную составляющую, нормируем амплитуду: Uout=(Uin-Umid)*K/Upp
Хотя лично я предпочел бы убрать постоянную составляющую аппаратно, разделительным конденсатором или трансформатором.
И правильно предпочли бы...
Потому что алгоритм вычисления среднего неверный.
Для доказательства этого достаточно взять два сигнала, которые дадут по такому алгоритму одинаковый результат, но будут иметь очевидно разные средние значения. Например меандр и очень короткие импульсы той же амплитуды.
Что бы понять как правильно реализовать вычисление среднего значения сигнала, достаточно обратиться к математике интегрирующего конденсатора...
1. Создаем скользящее окно с интервалом дискретизации соответствующем спектру сигнала по теореме Котельникова.
2. Вычисляем среднее значение буфера скользящего окна.
Среднее значение и будет нулем сигнала при его знаковом представлении.

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

Добавлено: Пт сен 14, 2012 08:32:40
Goldsmith
КРАМ писал(а):алгоритм вычисления среднего неверный.
Для доказательства этого достаточно взять два сигнала, которые дадут по такому алгоритму одинаковый результат, но будут иметь очевидно разные средние значения. Например меандр и очень короткие импульсы той же амплитуды.
В общем случае для произвольного сигнала - конечно, неверный, и придется интегрировать. Но в данном случае это продолжение разговора из другой темы про манчестерское кодирование (наверное, в ней и нужно было продолжать).

То есть мы заранее знаем, что: 1) среднее значение исходного сигнала за период равно нулю, 2) ширина импульса либо T, либо T/2. При этих условиях среднее арифметическое между пиками дает очень хорошее приближение к "истинному" среднему, а в вычислительном плане обойдется дешевле.