Страница 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