roboforum.ru

Технический форум по робототехнике.


Прием ДМХ пакета на атмегу

Автомат, адаптивный автомат ... разум

Прием ДМХ пакета на атмегу

Сообщение к561ЛА7 » 04 июн 2020, 21:45

Всю самоизолацию бьюсь над решением задачи.

Делаю так : В во внешнем прерывании запускаю счетчик, и смотрю нет ли 1 на вх. если за 88 мкс ее не было, то ставлю переменную признака этого событиа в 1 и отключаю это прерывание програмно, включаю в основном цикле потом.
И в основ цикле делаю подцикл по этому признаку где запускаю прием баитов по примеру задачи 5 в курсе авр 123. В общем или сразу перезагружаетса МК или принимает до 5 баитов а потом виснет. причем если прнимаешь только первыи баит то его значение может быть разным от 0 до 255 , а должно быть не разным. Буду благодарен тому и всем кто поможет мне выити на путь истинныи и выбратьса их этого болота

вот сама прога.
Код: Выделить всёРазвернуть
/*****************************************************

This program was produced by the
CodeWizardAVR V1.25.8 Standard
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 04.01.1980
Author  : F4CG
Company : F4CG
Comments:


Chip type           : ATmega16
Program type        : Application
Clock frequency     : 16,000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega16.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x1B ;PORTA
#endasm

#include <stdio.h>
#include <delay.h>

#include <lcd.h>
// My bits definitions   http://avr123.nm.ru/m8_128.h
#include <m8_128.h>
// в этом файле я сделал определения битов для МК

//_**********************************  обьявление переменных

// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>

#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)  //

//#define DATA_OVERRUN (1<<OVR)  // как у авр123
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)


#define BAUD 250000
#define CLOCK 16000000
//USR=0x18;   //?


// Буфер - USART Receiver buffer
#define RX_BUFFER_SIZE 240

char rx_buffer[RX_BUFFER_SIZE];

#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index, rx_rd_index, rx_counter;
#else
unsigned int rx_wr_index, rx_rd_index, rx_counter;
#endif
// This flag is set on USART Receiver
bit rx_buffer_overflow; // buffer overflow





//++++++++++++++++++++++++++++++++++++++++++++++++

// Функция обработчик прерывания 12 - завершение приема символа в USART
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
/*
В  status  копируется число из UCSRA  -
это регистр  управления и статуса
- состояния  USART  (стр. 162 ДШ).
В  data  копируется число из UDR  -
это регистр для принимаемых данных.
(стр. 161 ДШ).
*/

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {

//if (!status ==0)
//   {
 
/*
Затем  проводится  проверка правильно ли
USART MK принял
то что пришло на ножку RXD от ПК или другого
устройства :
Значит :

То что написано в скобках  {  } после  if() 
будет выполняться при безошибочном принятии данных.
Если же при приеме байта возникла любая из ошибок
:

FRAMING_ERROR    PARITY_ERROR     DATA_OVERRUN

то факт принятия данных  игнорируется и
следующий код функции обработки прерывания
закончен - т.е. программа выходит из прерывания
не помещая "криво" принятый байт в буфер и
возвращается к тому месту где возникло
прерывание № 12.

Код программы написанный здесь будет 
выполнятся ТОЛЬКО если условие в           
скобках    if("истина")  -
       значит "НЕ НОЛЬ"
*/
 

   rx_buffer[rx_wr_index]=data;

/*
Первая строка кода помещает принятый байт
в буфер - конкретно в элемент массива rx_buffer
  с  порядковым номером rx_wr_index   -
  этот номер называют индексом массива.
*/

   
   if (++rx_wr_index == RX_BUFFER_SIZE)
          {
   rx_wr_index=0;
          };
   
   if (++rx_counter == RX_BUFFER_SIZE)
      {
      rx_counter=0;
      rx_buffer_overflow=1;
      };
   };
}
   
/*
Эта функция называется usart_rx_isr()  и
вызывается при возникновении прерывания
USART_RXC (см. ДШ на МК) по приему символа
в регистр  UDR   
это регистр данных USART, причем два регистра
данных и приемника и
передатчика называются одинаково.

Т.е. программа МК перестает делать то что делала,
сохраняет некоторые
данные необходимые для продолжения работы с этого
места после возврата
из обработчика прерывания и начинает выполнять
функцию обработчик
прерывания  -      usart_rx_isr()

*/


//++++++++++++++++++++++++++++++++++++++++++++++++

// Новая Функция getchar()

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
/*
это цикл ожидания поступления символа в буфер.
В ней программа будет "сидеть", а точнее
"молотить" - пока нет прерывания и нет символа
  в буфере, ведь  rx_counter   это счетчик символов
  находящихся в буфере и пока буфер пуст эта
  переменная содержит 0 - вот цикл и повторяется
  ...
*/

data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif         

/*
Если в буфере были символы или появился символ,
программа перейдет
на следующую строку:
data = rx_buffer[rx_rd_index];
Тут все просто:  =  означает присвоить переменной
слева от = результат выражения справа от =     
Значит программа возьмет символ из буфера
(из массива rx_buffer[]) с порядковым номером 
rx_rd_index  и поместит его в   data
Далее происходит увеличение индекса буфера на
1 и если результат будет равен размеру буфера -
индекс обнуляется.
if (++rx_rd_index == RX_BUFFER_SIZE)
{
rx_rd_index=0;
};  // я добавил {  }; для вящей читаемости

Так как мы считали символ из буфера нужно уменьшить число символов в нем подлежащих считыванию.

#asm("cli")   // запретить прерывания глобально
--rx_counter; // вычесть 1 из rx_counter
#asm("sei")   // разрешить прерывания глобально
Обратите внимание что перед декрементом мы
запрещаем прерывания, а после прерывания включаем
опять.
Зачем ?    Вот фо ??? воскликнул бы англоязычный
читатель ...
А затем, что в обработчике прерывания есть
инкремент rx_counter  - и если на декременте
возникнет прерывание мы можем зациклится в
этом месте программы и получить ошибку в числе
символов в буфере.
последняя строчка функции
return data;
означает что функция вернет то что находится в
переменной  data
т.е. если мы напишем такой вызов функции:
nechto = getchar();
то после возврата из функции  в переменной  nechto  окажется то, что было помещено в   data   в функции.
*/


//++++++++++++++++++++++++++++++++++++++++++++++++

unsigned int data_in;
unsigned char dmx_ready;   //  пересенная начала паката
unsigned char e;   //  пересенная   признак разобы теймера на 88   мкс
unsigned char ee;   //  пересенная   
unsigned char   a[240];      // ДМХ массив из 512 перемееных куда пишем значения канала  нижняя срока дисплея
unsigned char   aa[20];      // массив отладочных меток
unsigned int n_in_massiv;  // номер в массиве "а"  - значение канала
unsigned char string[4];   //    массив из 4х переменных  для вывода строки на экран
unsigned char kn2; // счетчик кнопки 2 прокрутка -
unsigned char kn3; //
unsigned char kn4; // счетчик кнопки 3 данные -
unsigned char kn5; // счетчик кнопки 4 данные -




/*
// это из датащита - не работает
unsigned char USART_Receive( void )
{
//* Ожидание окончания приема данных
while ( !(UCSRA & (1<<RXC)) );
//* Загрузка принятых данных из буфера
return UDR;
}
*/






// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
aa[3]++;  // по этим меткам проверяем работу программы в железе
e=1; //    ставим готовность цикла отслеживания 88 мкс
ee=0;  //  обнуляем переменную счетчика
dmx_ready=0; // готовы к отслеживанию

//************** отслеживаем брейк 88 мкс
//  ЗАПУСК ТАЙМЕРА т0 НА 88 МКС на сработку по сравнению

TCCR1A = 0x00; //stop timer        основной таймер по которому идет проверка
TCCR1B = 0x00; //stop timer
TCNT1H=0x00;
TCNT1L=0x00;
TCCR1B=0b00000010;; //старт timer на 62 кгц  clock/-4

//************** цикл отслеживания брейк 88 мкс
while ((PIND.0==0)&(e==1)) { //   0 на линии
// не прошло 88 мкс и 0 на линии
    #asm("wdr") // Сбросить сторожевой таймер
       aa[5]++; //
if (PIND.0==1)    {    //если тут стало 1
       aa[6]++;
       e=0;      // ставим переменную в ноль чтобы выйти из цикла
                  }
aa[7]++;
                  };
aa[8]++;

ee=TCNT1L  ; // после первого же импульса пишем в переменную TCNT1L число тут
if (ee > 175 )    {    // и если счетчик больше 87 мкс
    dmx_ready=1; //   мы это фиксируем
    aa[9]++;
      ee=0;  // и убираем число счетска 175 (177 - 178 надо) из переменнной
                  }
//************** отслеживаем брейк 88 мкс закончилось
TCCR1A = 0x00; //stop timer        основной таймер по которому идет проверка
TCCR1B = 0x00; //stop timer
TCNT1H=0x00;
TCNT1L=0x00;   
// +++++++++++++++++++++Этот кусок тсчитает длину импульса  в тиках таймера  закончилось
}

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
//PORTA=0x00;
//DDRA=0x00;

PORTA=0b00000000; //  0 - без подтяжки, 1 - с подтяжной
DDRA=0b11111111;  //  0 - вход, 1- выход

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=T State2=0 State1=0 State0=0
PORTC=0x00;
DDRC=0xF7;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
//PORTD=0xFC;
//DDRD=0x02;
PORTD=0b11111101; //  0 - без подтяжки, 1 - с подтяжной
DDRD= 0b00000010;  //  0 - вход, 1- выход


// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
// OCR0=0xB0;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x02;  // 2000000
//TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;


// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: Off
// INT2: Off
GICR|=0x40;
// INT0 Mode: Falling Edge
MCUCR=0x02;
MCUCSR=0x00;
GIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;   // их нет

// USART initialization
// Communication Parameters: 8 Data, 2 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 250000
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(1<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (1<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x03;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// LCD module initialization
lcd_init(16);

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
WDTCR=0x1D;
WDTCR=0x0D;

#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Global enable interrupts

n_in_massiv=1;     //чтобы вывод на экран начинался с 1 адреса

//#asm("sei") /* бит_I сделать "1" теперь разрешенные прерывания будут обрабатываться, если есть установленный флаг прерывания то произойдет вызов его функции обработчика */
//#asm("cli")  /* бит_I сделать "0" запретить все прерывания ГЛОБАЛЬНО. */
#asm("cli")//запретить


// LCD module initialization
lcd_init(16);

//*************************************

// приветствие   выводим
lcd_gotoxy(1,0);
lcd_putsf("  DMX IN ");
lcd_gotoxy(0,1);
lcd_putsf("hello world");

     delay_ms(400);  // задержка , ждем

// Global enable interrupts
#asm("sei")   

#asm("wdr") // Сбросить сторожевой таймер
while (1)//
       {

GICR=(0<<INT0);//запрещаем прерывание по инт 0
// *******этот цикл работает только если есть импульсы преырвания на входе!!!!

while (dmx_ready==1)// !!!! инструкция while ЗАПРЕЩАЕТ прерываение!!!!
        {
// ***********это кукок начала приема дмх+++++++++               
#asm("wdr") // Сбросить сторожевой таймер

aa[1]++;         

a[2]=UCSRB; // смотрим что у нас в регистре
a[3]=UCSRA; // смотрим что у нас в регистре

a[4] = getchar(); // читаем символ
//a[4]=data_in;

aa[10]++; 
//LSD_SHKA();//  это сама функция выхпуска на дисплей-
#asm("wdr") // Сбросить сторожевой таймер
//KNOPKI_test();//  вызывем функцию шажптия кнопок

//if (n_in_massiv==0){n_in_massiv=508;} //   чтобы небыло 513 514 ставим до 508
//if (n_in_massiv>508){n_in_massiv=1; }// эффекты кончились, сбрасываем их счетчик

dmx_ready=0;  // это выход из цикла обязательно     
        };   

#asm("wdr") // Сбросить сторожевой таймер


while (dmx_ready==0)// !!!! инструкция while ЗАПРЕЩАЕТ прерываение!!!!
        {

aa[4]++;

LSD_SHKA();//  это сама функция выпуска на дисплей- тут ее нет дл краткости вопроса
#asm("wdr") // Сбросить сторожевой таймер
KNOPKI_test();//  вызываем функцию нажатия кнопок тут ее тоже нет

if (n_in_massiv==0){n_in_massiv=508;} //   чтобы небыло 513 514 ставим до 508
if (n_in_massiv>508){n_in_massiv=1; }// эффекты кончились, сбрасываем их счетчик

delay_ms(100);  // пока задержка , ждем

     };
GICR=(1<<INT0);//allow прерывание по инт 0
     };





}



Ваш IP-адрес 85.140.5.459 был внесён в черный список и заблокирован. Для получения дополнительной информации перейдите по ссылке http://www.spamhaus.org/query/bl?ip=85.140.5.459.
Аватара пользователя
к561ЛА7
 
Сообщения: 404
Зарегистрирован: 08 дек 2009, 19:21
Откуда: Й-Ола

Re: Прием ДМХ пакета на атмегу

Сообщение Madf » 05 июн 2020, 10:24

При любом приёме, не должно быть никогда: "отключаю". Либо используем INT внешний (который очень хорошо подходит для приёма данных), либо используем готовые решения.
Madf
 
Сообщения: 3242
Зарегистрирован: 03 янв 2012, 12:55
Откуда: Москва
прог. языки: VB6, BASCOM, ASM...

Re: Прием ДМХ пакета на атмегу

Сообщение к561ЛА7 » 12 июн 2020, 10:39

Я бы дажу купил это техническое решение.но мне нужно на атмегу 16 и в кодвижинеавр, так как в нем
у меня уже есть отлаженные наработки.
Ваш IP-адрес 85.140.5.459 был внесён в черный список и заблокирован. Для получения дополнительной информации перейдите по ссылке http://www.spamhaus.org/query/bl?ip=85.140.5.459.
Аватара пользователя
к561ЛА7
 
Сообщения: 404
Зарегистрирован: 08 дек 2009, 19:21
Откуда: Й-Ола

Re: Прием ДМХ пакета на атмегу

Сообщение Madf » 12 июн 2020, 12:40

к561ЛА7 писал(а):кодвижинеавр

Не сорри, этим не увлекаюсь. Только баском. :crazy:
Madf
 
Сообщения: 3242
Зарегистрирован: 03 янв 2012, 12:55
Откуда: Москва
прог. языки: VB6, BASCOM, ASM...


Вернуться в Алгоритмы

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

Mail.ru counter