mpower 0 16 июля, 2013 Опубликовано 16 июля, 2013 (изменено) · Жалоба День добрый! Делаю преобразователь/переходник с сигналов RC-аппаратуры (7-ми канальный HiTec) в цифру, с выходом на UART. МК - atmega168, тактирую от встроенных 8мГц. RC-приемник формирует на выходе стандартные серво-PWM сигналы, последовательно по каналам. Первый канал повесил на INT0, остальные на порт С. Данные собираю по таймеру0. Эта часть проги работает. Проблема возникла, когда данные решил отправить в UART. Передаются первые 2-3 байта и все. передача вырубается. Код писал в CVAVR 2.05, пользовался его же визардом. думал, что как-то все не успевает и подвисает, в итоге сократил прогу до обычного присваивания в массив чисел. результат не изменился, выводятся в порт только 3 байта и все. убирая буферы в UART выводится вообще полная ахинея, но передача не прерывается. С последовательным портом в таком виде работаю впервые, поэтому прошу помощи. Гугл должных результатов не подсказал. код: /***************************************************** This program was produced by the CodeWizardAVR V2.05.0 Professional Automatic Program Generator © Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Version : Date : 16.07.2013 Author : NeVaDa Company : Comments: Chip type : ATmega168V Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega168.h> #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_REGISTER_EMPTY (1<<UDRE) #define RX_COMPLETE (1<<RXC) #define MAX_PPM_CHANNELS 7 #define CH1 PIND.2 #define CH2 PINC.5 #define CH3 PINC.4 #define CH4 PINC.3 #define CH5 PINC.2 #define CH6 PINC.1 #define CH7 PINC.0 unsigned int counter; unsigned int Channel[MAX_PPM_CHANNELS],ChannelTX[MAX_PPM_CHANNELS]; unsigned char uart_r,flag,start_ppm,end_ppm,n_chan,lo_b,hi_b,tmp; // USART Receiver buffer #define RX_BUFFER_SIZE0 50 char rx_buffer0[RX_BUFFER_SIZE0]; #if RX_BUFFER_SIZE0 <= 256 unsigned char rx_wr_index0,rx_rd_index0,rx_counter0; #else unsigned int rx_wr_index0,rx_rd_index0,rx_counter0; #endif // This flag is set on USART Receiver buffer overflow bit rx_buffer_overflow0; // USART Receiver interrupt service routine interrupt [uSART_RXC] void usart_rx_isr(void) { char status,data; status=UCSR0A; data=UDR0; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) { rx_buffer0[rx_wr_index0++]=data; #if RX_BUFFER_SIZE0 == 256 // special case for receiver buffer size=256 if (++rx_counter0 == 0) { #else if (rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0; if (++rx_counter0 == RX_BUFFER_SIZE0) { rx_counter0=0; #endif rx_buffer_overflow0=1; } } } #ifndef _DEBUG_TERMINAL_IO_ // Get a character from the USART Receiver buffer #define _ALTERNATE_GETCHAR_ #pragma used+ char getchar(void) { char data; while (rx_counter0==0); data=rx_buffer0[rx_rd_index0++]; #if RX_BUFFER_SIZE0 != 256 if (rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0; #endif #asm("cli") --rx_counter0; #asm("sei") return data; } #pragma used- #endif // USART Transmitter buffer #define TX_BUFFER_SIZE0 50 char tx_buffer0[TX_BUFFER_SIZE0]; #if TX_BUFFER_SIZE0 <= 256 unsigned char tx_wr_index0,tx_rd_index0,tx_counter0; #else unsigned int tx_wr_index0,tx_rd_index0,tx_counter0; #endif // USART Transmitter interrupt service routine interrupt [uSART_TXC] void usart_tx_isr(void) { if (tx_counter0) { --tx_counter0; UDR0=tx_buffer0[tx_rd_index0++]; #if TX_BUFFER_SIZE0 != 256 if (tx_rd_index0 == TX_BUFFER_SIZE0) tx_rd_index0=0; #endif } } #ifndef _DEBUG_TERMINAL_IO_ // Write a character to the USART Transmitter buffer #define _ALTERNATE_PUTCHAR_ #pragma used+ void putchar(char c) { while (tx_counter0 == TX_BUFFER_SIZE0); #asm("cli") if (tx_counter0 || ((UCSR0A & DATA_REGISTER_EMPTY)==0)) { tx_buffer0[tx_wr_index0++]=c; #if TX_BUFFER_SIZE0 != 256 if (tx_wr_index0 == TX_BUFFER_SIZE0) tx_wr_index0=0; #endif ++tx_counter0; } else UDR0=c; #asm("sei") } #pragma used- #endif // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { start_ppm=1;counter=0;n_chan=0; PORTB.0=!PORTB.0; } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCNT0=0xFE; ChannelTX[0]=0x3031; ChannelTX[1]=0x3233; ChannelTX[2]=0x3435; ChannelTX[3]=0x3637; ChannelTX[4]=0x3839; ChannelTX[5]=0x3A3B; ChannelTX[6]=0x3C3D; PORTB.1=!PORTB.1; } // Declare your global variables here void main(void) { // Declare your local variables here // Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif // Input/Output Ports initialization // Port B initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTB=0x00; DDRB=0xFF; // Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=P State5=P State4=P State3=P State2=P State1=P State0=P PORTC=0x7F; DDRC=0x00; // Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P PORTD=0xFF; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 1000,000 kHz // Mode: Normal top=0xFF // OC0A output: Disconnected // OC0B output: Disconnected TCCR0A=0x00; TCCR0B=0x02; TCNT0=0xFE; OCR0A=0x00; OCR0B=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer1 Stopped // Mode: Normal top=0xFFFF // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; 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: Timer2 Stopped // Mode: Normal top=0xFF // OC2A output: Disconnected // OC2B output: Disconnected ASSR=0x00; TCCR2A=0x00; TCCR2B=0x00; TCNT2=0x00; OCR2A=0x00; OCR2B=0x00; // External Interrupt(s) initialization // INT0: On // INT0 Mode: Rising Edge // INT1: Off // Interrupt on any change on pins PCINT0-7: Off // Interrupt on any change on pins PCINT8-14: Off // Interrupt on any change on pins PCINT16-23: Off EICRA=0x03; EIMSK=0x01; EIFR=0x01; PCICR=0x00; // Timer/Counter 0 Interrupt(s) initialization TIMSK0=0x01; // Timer/Counter 1 Interrupt(s) initialization TIMSK1=0x00; // Timer/Counter 2 Interrupt(s) initialization TIMSK2=0x00; // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART0 Mode: Asynchronous // USART Baud Rate: 19200 UCSR0A=0x00; UCSR0B=0xD8; UCSR0C=0x06; UBRR0H=0x00; UBRR0L=0x19; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; ADCSRB=0x00; DIDR1=0x00; // ADC initialization // ADC disabled ADCSRA=0x00; // SPI initialization // SPI disabled SPCR=0x00; // TWI initialization // TWI disabled TWCR=0x00; // Global enable interrupts #asm("sei") while (1) { for (tmp=0;tmp<=6;tmp++) { lo_b=(unsigned char) ChannelTX[tmp]; hi_b=(unsigned char) (ChannelTX[tmp]>>8); putchar(hi_b); putchar(lo_b); putchar('!'); } } } Если в основном цикле запрещать таймер0, то все выводится правильно. что может таймер делать с буфером, если даже когда обработчик пустой, то буфер виснет. TIMSK0=0x00; for (tmp=0;tmp<=6;tmp++) { lo_b=(unsigned char) ChannelTX[tmp]; hi_b=(unsigned char) (ChannelTX[tmp]>>8); putchar(hi_b); putchar(lo_b); putchar('!'); }; putchar(0x0A); putchar(0x0D); TIMSK0=0x01; Изменено 16 июля, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artkam 0 16 июля, 2013 Опубликовано 16 июля, 2013 · Жалоба Я правильно понимаю, по задумке Timer0 у Вас с частотой 100кГц переполняется????? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mpower 0 16 июля, 2013 Опубликовано 16 июля, 2013 · Жалоба Совершенно верно, с этой частотой я измеряю ШИМ из приемника. Такой точности мне вполне хватит. Подумываю уже о том, чтобы сделать последовательно и без таймера замерять шим на выходах, а потом отправлять данные, и затем ждать начала новой посылки сигналов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artkam 0 17 июля, 2013 Опубликовано 17 июля, 2013 · Жалоба С частотой таймера Вы как-то уж слишком замахнулись. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 18 июля, 2013 Опубликовано 18 июля, 2013 · Жалоба Да уж, с таким обработчиком частота вызова перываний таймера 500 кГц? За один период - 16 тактов для процессора, даже Ваш обработчик выполниться поди не успеет :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mpower 0 29 июля, 2013 Опубликовано 29 июля, 2013 · Жалоба Да, именно в этом и была проблема. На пустом обработчике прерываний только и успевал МК не накосячить с uart'ом. Я решил проблему тем, что, сначала замеряю ШИМ по каналам, и в перерыве между сериями отправляю данные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 31 июля, 2013 Опубликовано 31 июля, 2013 · Жалоба А хорошо ли это - пользоваться встроенным RC-генератором для тактирования UART-а? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 1 августа, 2013 Опубликовано 1 августа, 2013 · Жалоба А хорошо ли это - пользоваться встроенным RC-генератором для тактирования UART-а?А это, по-моему, каждый решает в соответствиями с требованиями по точности скорости того самого UART'а :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mpower 0 4 августа, 2013 Опубликовано 4 августа, 2013 · Жалоба Чтобы не плодить темы, задам вопрос здесь. Есть мега644. Нужно организовать два UART'а. Все было бы нормально, но второй uart не заводится вообще. // USART0 initialization // USART0 Baud Rate: 115200 UCSR0A=0x00; UCSR0B=0xD8; UCSR0C=0x06; UBRR0H=0x00; UBRR0L=0x0A; // USART1 initialization // USART1 Baud Rate: 115200 UCSR1A=0x00; UCSR1B=0xD8; UCSR1C=0x06; UBRR1H=0x00; UBRR1L=0x0A; while (1) { while(!(UCSR0A & (1<<UDRE0))); UDR0 = 0b10100011; while(!(UCSR1A & (1<<UDRE1))); UDR1 = 0b10100101; } из UART0 все отсылается как часы, а UART1 молчит вообще (мониторю осциллографом). бьюсь над этим уже пару дней, и с портами шаманствовал на вход/выход/подтяжки, и контроллер менял, результата нет. Уважаемые Гуру, посоветуйте пожалуйста, в какую сторону копать-то. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artkam 0 4 августа, 2013 Опубликовано 4 августа, 2013 (изменено) · Жалоба The ATmega644 has one USART, USART0. Выдрано слово в слово из даташита... Предлагаю копать в сторону другого контроллера )) Изменено 4 августа, 2013 пользователем artkam Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mpower 0 4 августа, 2013 Опубликовано 4 августа, 2013 (изменено) · Жалоба Как так, вот из моего даташита 19.2 USART1 and USART0 The ATmega164A/164PA/324A/324PA/644A/644PA/1284/1284P has two USART’s, USART0 and USART1. Хм, понял, не уточнил. у меня atmega644P И, благодаря Вашему замечанию, есть мысли что попались в партии либо брак, либо ошибка маркировки. Хотя на атмел такое не мог подумать. Изменено 4 августа, 2013 пользователем Vooze Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 5 августа, 2013 Опубликовано 5 августа, 2013 · Жалоба UCSR0B=0xD8 У Вас работают сразу 2 прерывания , причем одно из них похоже Вам совсем не нужно т.к. приемник даже не включён Отключите 0-ой скорее всего будет работать и 1-ый И научитесь писать без всяких HEX и BIN Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mpower 0 8 августа, 2013 Опубликовано 8 августа, 2013 · Жалоба проблема решилась заменой контроллера. походу брак. И научитесь писать без всяких HEX и BIN мне так, как-то удобнее. Это еще со времен z80. BIN в HEX "в уме" раскладывается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 9 августа, 2013 Опубликовано 9 августа, 2013 · Жалоба Я имел ввиду вот так, как пример DDRB = (1<<PB7)|(1<<PB6)|(0<<PB5)|(1<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться