Страница 1 из 1

WinAVR Помогите с прошивкой ультразвукового дальномера

Добавлено: Сб май 29, 2010 18:23:17
indi_88
Всем доброе время суток, спаял я все таки ультразвуковой дальномер.
Думал, что с написанием проги не возникнут проблема, но...
Небось прерывания - штуки капризные.

Вот наваял такой код:

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

#include <avr/io.h> 
#include <avr/interrupt.h> 
#include <math.h> 
#include <util/delay.h>

#define iter 64000UL		// переполнение = 8 мс
#define HI(x) ((x)>>8)
#define LO(x) ((x)&0xFF)

// a f b e d dp c g 
//						  			 0	 1	  2    3    4    5    6     7    8    9    .    
volatile unsigned char codes[] = {0xFA,0x22,0xB9,0xAB,0x63,0xCB,0xDB,0xA2,0xFB,0xEB,0x04,0x00};

volatile unsigned char answer[] = {0x00, 0x00, 0x00};

volatile unsigned char flags = 0b0000000;
//								            ||
//									         | ----- прерывание ИНТ0
//									           ------ прерывание ИНТ1

volatile unsigned int ov_count = 0;

volatile	unsigned int iteration = 0;
volatile	float dist = 0;
volatile	unsigned int ans = 0;

/* Функция перевода числа в коды, для отображения 
   на динамической индикации */
void FORMAT(unsigned int val)
{
	unsigned char a, b, c, temp = 0;
	
	a = val/100;
	temp = val - 100*a;
	b = temp/10;
	c = temp - b*10;
	
	answer[0] = codes[a];
	answer[1] = codes[b];
	answer[2] = codes[c];
}

/* Функция отображения данных на индикаторе */
void DISPLAY()
{
	PORTB = answer[0];
	PORTD |= 0b00010000;
	_delay_ms(5);	
	PORTD &= 0b11101111;
		
	PORTB = answer[1];
	PORTD |= 0b00100000;
	_delay_ms(5);		
	PORTD &= 0b11011111;
		
	PORTB = answer[2];
	PORTD |= 0b01000000;
	_delay_ms(5);			
	PORTD &= 0b10111111;	
}

/* Функция отправки пачки УЗ импульсов (10 шт) */
void SENDIMPULSE()
{
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);	
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);
	PORTD |= 0b00000001;
	_delay_us(12.5);
	PORTD &= 0b11111110;
	_delay_us(12.5);	
}

// Обработчие прерывания от таймера 1
ISR(TIMER1_COMPA_vect)
{
	ov_count++;	
}


// Обработчик внешнего прерывания INT1 (пришло эхо)
ISR(INT1_vect)
{	
	TCCR1B = 0b00001000; //останавливаем таймер
	flags |= 0b00000010;	
}

// Обработчик внешнего прерывания INT0 (нажата кнопка)
ISR(INT0_vect)
{
	flags |= 0b00000001;
}


int main()
{
	cli();	// запрещаем все прерывания
	
	DDRB = 0b11111111;	// все ноги порта В на вывод
	DDRD = 0b11110011;  // все кроме инт1 и инт0 на вывод, те на ввод
	
	// даташит с 62 страницы	
	
	MCUCR &= 0b11111010;	// прерывания инт1 и инт0 по falling edge
	GIMSK = 0b11000000;    // разрешаем прерывание инт1 и инт0
	
	TCCR1A = 0b00000000;	// выбираем режим СТС
	TCCR1B = 0b00001000; 	// таймер пока остановлен

	OCR1AH = HI(iter);		// старший байт
	OCR1AL = LO(iter);		// младший байт	

	TIMSK = 0b01000000; // прерывание по сравнению
	
	sei(); // разрешаем все прерывания
			
	
	for(;;)
	{
		if((flags & 0b00000001) == 1) // если взведен флаг инт0
		{
			TCCR1B = 0b00001000;	// останавливаем счетчик
			ov_count = 0;			// обнуляем переменную переполнения счетчика
			TCNT1H = 0;				// обнуляем значения счетчика
			TCNT1L = 0;
			flags &= 0b11111110;	// очищаем флаг
	
			TCCR1B = 0b00001001; 	//запускаем счетчик	
			SENDIMPULSE();			//начинаем посылать импульсы
		}		
		
		if((flags & 0b00000010) == 2) // если взведен флаг инт1
		{	
			cli();					// запрещаем все прерывания
			
			flags &= 0b11111101;	// очищаем флаг
			
			iteration = 0;			// обнуляем перменные
			dist = 0;
			ans = 0;

			iteration |= TCNT1H;	
			iteration <<= 8;
			iteration |= TCNT1L;	// прочитали значение счетчика
	

			dist = (iteration * 0.000125 + ov_count) * 16.5;	// посчитали расстояние в см

			ans = trunc(dist + 0.5);	// округлили
	
			FORMAT(ans);			// софрмировали ответ для отображения
			
			sei();					// разрешили все прерывания
		}	
					
		DISPLAY();					// отображаем что насчитали
	}
	return(0);
}
Хоть убейте, но не вижу причин, почему б ему не работать)))
Помогите кто чем сможет))

Принципиалка устройства в прикрепленке.

Re: WinAVR Помогите с прошивкой ультразвукового дальномера

Добавлено: Ср июн 02, 2010 14:40:28
Aheir
Зато я вижу причину для удаления темы. :)
Код оформляется вложением. Тема по WinAVR - в начале раздела. Сутки на исправление.

Re: WinAVR Помогите с прошивкой ультразвукового дальномера

Добавлено: Сб июл 17, 2010 08:37:51
san822
А откуда схема ?

Может подумать над усилением отраженных сигналов ?
Например, сделать как здесь:
http://www.maxbotix.com/uploads/LV-MaxS ... asheet.pdf