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

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
indi_88
Родился
Сообщения: 17
Зарегистрирован: Чт май 06, 2010 16:09:40

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

Сообщение 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);
}


Хоть убейте, но не вижу причин, почему б ему не работать)))
Помогите кто чем сможет))

Принципиалка устройства в прикрепленке.
Вложения
sch2.pdf
(43.54 КБ) 414 скачиваний
Аватара пользователя
Aheir
Модератор
Сообщения: 4517
Зарегистрирован: Пн апр 03, 2006 11:43:25
Откуда: Санкт - Петербург
Контактная информация:

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

Сообщение Aheir »

Зато я вижу причину для удаления темы. :)
Код оформляется вложением. Тема по WinAVR - в начале раздела. Сутки на исправление.
Оптимизм х (Опыт + Знания) = const
san822
Родился
Сообщения: 9
Зарегистрирован: Чт янв 03, 2008 17:48:02

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

Сообщение san822 »

А откуда схема ?

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

Вернуться в «Микроконтроллеры и ПЛИС»