|
|
  |
Проблема с UART, Не могу разобраться с прерыванием |
|
|
|
Apr 7 2011, 09:52
|

Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 7-10-10
Из: Москва
Пользователь №: 59 985

|
Доброго времени, суток) Такая проблема: Пишу программу на WINAVR, смысл таков - по прерыванию UART по линии Rx, программа должна возвращать символ, в зависимости от символа введенного в терминале. НО, все попытки - сравнение строк, условия if и т.д. были тщетными... компилятор выдавал ворнинги... В общем вопрос: Как организовать отправку строки символов, в зависимости от строки введенной в теминале ? Либо как корректно передать в main() содержание UDR из SIGNAL (SIG_UART_RECV)Вот так я писал функцию обработки прерывания изначально, но ничего не получалось: SIGNAL (SIG_UART_RECV) uint8_t usart_data; uint8_t *pInpunStr = "start"; char *pDispatch; int flag; usart_data= UDR; flag = strcmp(pInpunStr,usart_data); if(flag = 1) pDispatch = "GOOD"; else{ pDispatch = "TRY AGAIN"; } usart_send_c(pDispatch); } CODE #include <avr/io.h> #include <avr/interrupt.h>
#include <inttypes.h> #include <util/delay.h>
#define F_OSC 16000000 /* oscillator-frequency in Hz (F_OSC) - caiaieou!!! */ #define UART_BAUD_RATE 9600 #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16l)-1)
void delay_ms(unsigned short ms) { unsigned short outer1, outer2; outer1 = 200; while (outer1) { outer2 = 1000; while (outer2) { while ( ms ) ms--; outer2--; } outer1--; } }
int strcmp(unsigned char *t1,unsigned char *t2) { while(*t1) if(*t1-*t2) return 0; else{ t1++; t2++; } return 1; }
void usart_send_c(uint8_t c) { // wait until UDR ready while(!(UCSRA & (1 << UDRE))); UDR = c; // send character }
void uart_send_s(uint8_t *s) { // loop until *s != NULL while (*s) { usart_send_c(*s); s++; } }
/*Eieoeaeecaoey UART*/ void init(void) { // set baud rate UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)>>8); UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);
// Enable receiver and transmitter; enable RX interrupt UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
//asynchronous 8N1 UCSRC = (1 << URSEL) | (3 << UCSZ0); }
SIGNAL (SIG_UART_RECV) { // USART RX interrupt uint8_t usart_data; usart_data= UDR; usart_send_c(usart_data); }
int main(void) { init(); // init USART
while(!(UCSRA & (1 << UDRE))); UDR = 0x0d; char *p = "READY!"; while (*p){ while(!(UCSRA & (1 << UDRE))); UDR = (uint16_t)*p; p++; }
#define LED1 7 #define LED_PORT PORTD #define LED_DDR DDRD
LED_DDR = 1<<LED1; sei(); // enable interrupts
while(1) { LED_PORT=0<<LED1; _delay_ms(1000); LED_PORT=1<<LED1; _delay_ms(1000); } return 0; }
Сообщение отредактировал IgorKossak - Apr 7 2011, 10:57
Причина редактирования: [codebox]
|
|
|
|
|
Apr 7 2011, 10:19
|
Группа: Новичок
Сообщений: 6
Регистрация: 11-11-10
Из: Украина
Пользователь №: 60 803

|
какая у Вас версия WINAVR? если из последних, то вместо SIGNAL (SIG_UART_RECV) используйте ISR(USART_RX_vect). и что за ворнинги пишет?
|
|
|
|
|
Apr 7 2011, 10:40
|

Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 7-10-10
Из: Москва
Пользователь №: 59 985

|
Цитата(azziz @ Apr 7 2011, 13:19)  какая у Вас версия WINAVR? если из последних, то вместо SIGNAL (SIG_UART_RECV) используйте ISR(USART_RX_vect). и что за ворнинги пишет? У меня из последних версия, вот какие ворнинги пишет для обоих случаев: SIGNAL (SIG_UART_RECV)../main.c:82: warning: pointer targets in initialization differ in signedness ../main.c:89: warning: passing argument 2 of 'strcmp' makes pointer from integer without a cast ../main.c:91: warning: suggest parentheses around assignment used as truth value ../main.c:110: warning: passing argument 1 of 'usart_send_c' makes integer from pointer without a cast ISR(USART_RX_vect)../main.c:79: warning: 'USART_RX_vect' appears to be a misspelled signal handler ../main.c: In function 'USART_RX_vect': ../main.c:82: warning: pointer targets in initialization differ in signedness ../main.c:89: warning: passing argument 2 of 'strcmp' makes pointer from integer without a cast ../main.c:91: warning: suggest parentheses around assignment used as truth value ../main.c:110: warning: passing argument 1 of 'usart_send_c' makes integer from pointer without a cast
Сообщение отредактировал uzzzer - Apr 7 2011, 10:41
|
|
|
|
|
Apr 7 2011, 11:33
|
Группа: Новичок
Сообщений: 6
Регистрация: 11-11-10
Из: Украина
Пользователь №: 60 803

|
у Вас неверная формула определения скорости UBRR = F_OSC/(16*UART_BAUD_RATE) - 1 какой у Вас контроллер? имя вектора другое. посмотрите как он определен в файле iomXX.h где пишете *char напишите unsigned char*. вместо if(*t1-*t2) попробуйте if((*t1-*t2) == 0)
|
|
|
|
|
Apr 7 2011, 11:47
|

Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 7-10-10
Из: Москва
Пользователь №: 59 985

|
Цитата(hd44780 @ Apr 7 2011, 14:39)  ; Все равно выдает те же ворнинги(((
Сообщение отредактировал IgorKossak - Apr 8 2011, 06:49
|
|
|
|
|
Apr 7 2011, 12:16
|

Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 7-10-10
Из: Москва
Пользователь №: 59 985

|
Цитата(Сергей Борщ @ Apr 7 2011, 15:04)  Для начала: Попытка из принятого байта сделать указатель на строку лишена смысла: flag = strcmp(pInpunStr,usart_data); Это я просто написал функцию сравнения строк, 0 - если не раны, еденица, если равны))) Цитата Вам надо сложить принятые байты в какой-то буфер и потом, по какому-то признаку (прнят символ перевода строки, например), сравнить принятый буфер с образцом команды. Если можно, поясните, как это сделать... т.е. по переходу из процедуры обработки прерывания в main() уничтожаются все локальные переменные, а как организовать такой буфер ? Как я понимаю компиллер ругается на несоответствие типов данных.
|
|
|
|
|
Apr 7 2011, 20:47
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(uzzzer @ Apr 7 2011, 15:16)  Если можно, поясните, как это сделать... т.е. по переходу из процедуры обработки прерывания в main() уничтожаются все локальные переменные, а как организовать такой буфер ? Как я понимаю компиллер ругается на несоответствие типов данных. например так CODE volatile char write_index = 0; volatile char enter_pressed = FALSE; char cmd[64];
uart_rx_isr() { char ch = UDR;
if (enter_pressed) // drop the char, previous command hasn't handled yet. return;
if (ch >= 0x20) { // common case cmd[ write_index++ ] = UDR; } else if (ch == 0x0D) { // нажали кнопку enter if (write_index) enter_pressed = TRUE; } else { // other control chars, backspace, tab etc. handle here }
if (write_index >= sizeof(cmd)) write_index = 0; }
main() { memset( cmd, 0x00, sizeof(cmd));
for(;;) { if(enter_pressed) { if ( memcmp( "cmd1", cmd, sizeof("cmd1")-1 ) ) .... else if ( memcmp( "cmd2", cmd, sizeof("cmd2")-1 ) ) ....
// cmd handled write_index = 0; enter_pressed = FALSE; } } }
Сообщение отредактировал IgorKossak - Apr 8 2011, 06:50
Причина редактирования: [codebox]
|
|
|
|
|
Apr 15 2011, 05:48
|

Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 7-10-10
Из: Москва
Пользователь №: 59 985

|
Огромное все спасибо за помощь. Вообщем я частично решил проблему с помощью примера к статьи: http://www.chipenable.ru/index.php/program...sart-uart-queueПеределав основную программу таким образом: Код int main(void) { unsigned char counter=0; // for test unsigned char StrRx[counter];// for test unsigned char StrTx[counter]; unsigned char index; //for test char *pRx=0; unsigned char *pTx=0; char pCmd[]="START"; unsigned char pEcho[]="TEST PASS !!!"; unsigned char pFail[]="Try again !!!"; unsigned char symbol; int flag;
//unsigned char symbol; USART_Init(); asm("sei");
while(1){ /*symbol = USART_GetChar(); if (symbol == 't') USART_SendStr(pEcho); */ unsigned char tmp; tmp = USART_GetChar(); //pRx=pCmd;
while(tmp){ pRx++; *pRx = tmp;
tmp=USART_GetChar(); }
flag = strcmp(pRx,pCmd);
if(flag==0) USART_SendStr(pEcho); //else {USART_SendStr(pFail);}
} return 0; } Но возник такой вопрос: USART_SendStr(pEcho); - выводит строку символов pEcho ("TEST PASS !!!"), примерно так: TEST PASS !!! TES т.е. по 18 символов, причем три раза нажимаю энтер и три раза выводится по 18 символов... стоит уменьшить SIZE_BUF, до 10 - 11 символов, выводится строка с меньшим количеством символов и два раза нажав энтер выводится два раза соответственно... причем больше трех раз при значении SIZE_BUF=16 не выводится и больше двух раз при значении SIZE_BUF = 10... Это скрин терминалки:
Прикрепленные файлы
UART_2.rar ( 19.88 килобайт )
Кол-во скачиваний: 20
|
|
|
|
|
Apr 15 2011, 07:28
|

Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 7-10-10
Из: Москва
Пользователь №: 59 985

|
И еще: Если Ввожу не полную строку "START" или хотя бы строку больше двух символов, но содержащею, хотя бы один "S", то выводится, как будто ввел полностью слово, если больше 6 символов, то ввод прекращается уже не после третьего нажатия энтер, а послн первого или второго. Если только один "S", то на теминалке выводится до бесконечности мое сообщение. такое чувство, что функция сравнения просто сравнивает первый символ...
Сообщение отредактировал uzzzer - Apr 15 2011, 07:32
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|