Делаю так : В во внешнем прерывании запускаю счетчик, и смотрю нет ли 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
};
}