реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Проблема с UART, Не могу разобраться с прерыванием
uzzzer
сообщение Apr 7 2011, 09:52
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 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]
Go to the top of the page
 
+Quote Post
azziz
сообщение Apr 7 2011, 10:19
Сообщение #2





Группа: Новичок
Сообщений: 6
Регистрация: 11-11-10
Из: Украина
Пользователь №: 60 803



какая у Вас версия WINAVR? если из последних, то вместо SIGNAL (SIG_UART_RECV) используйте ISR(USART_RX_vect). и что за ворнинги пишет?
Go to the top of the page
 
+Quote Post
uzzzer
сообщение Apr 7 2011, 10:40
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
azziz
сообщение Apr 7 2011, 11:33
Сообщение #4





Группа: Новичок
Сообщений: 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)
Go to the top of the page
 
+Quote Post
hd44780
сообщение Apr 7 2011, 11:39
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Тогда уж не

uint8_t *pInpunStr = "start";

а

char *pInpunStr = "start";

А если хотите именно uint8_t, то

flag = strcmp((char *)pInpunStr,usart_data);



--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
uzzzer
сообщение Apr 7 2011, 11:47
Сообщение #6


Частый гость
**

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



Цитата(hd44780 @ Apr 7 2011, 14:39) *
;


Все равно выдает те же ворнинги(((

Сообщение отредактировал IgorKossak - Apr 8 2011, 06:49
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 7 2011, 12:04
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Для начала: Попытка из принятого байта сделать указатель на строку лишена смысла: flag = strcmp(pInpunStr,usart_data);
Вам надо сложить принятые байты в какой-то буфер и потом, по какому-то признаку (прнят символ перевода строки, например), сравнить принятый буфер с образцом команды.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
uzzzer
сообщение Apr 7 2011, 12:16
Сообщение #8


Частый гость
**

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



Цитата(Сергей Борщ @ Apr 7 2011, 15:04) *
Для начала: Попытка из принятого байта сделать указатель на строку лишена смысла: flag = strcmp(pInpunStr,usart_data);


Это я просто написал функцию сравнения строк, 0 - если не раны, еденица, если равны)))


Цитата
Вам надо сложить принятые байты в какой-то буфер и потом, по какому-то признаку (прнят символ перевода строки, например), сравнить принятый буфер с образцом команды.


Если можно, поясните, как это сделать... т.е. по переходу из процедуры обработки прерывания в main() уничтожаются все локальные переменные, а как организовать такой буфер ?
Как я понимаю компиллер ругается на несоответствие типов данных.
Go to the top of the page
 
+Quote Post
defunct
сообщение Apr 7 2011, 20:47
Сообщение #9


кекс
******

Группа: Свой
Сообщений: 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]
Go to the top of the page
 
+Quote Post
nk@
сообщение Apr 7 2011, 22:27
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 78
Регистрация: 8-12-09
Пользователь №: 54 138



Прошу прощения за неоригинальность, но AVRLIB от Pascal Stang включает в себя замечательную библиотечку для работы с UART, причем с FIFO, поддержкой прерываний итд sm.gif Имеется также реализация VT100 и даже command-line интерфейса с редактированием, автокомплишеном. Зачем сушить себе мозги и изобретать колесо - берите готовое и радуйтесь.
http://www.mil.ufl.edu/~chrisarnold/compon...ard/AVR/avrlib/

Сообщение отредактировал nk@ - Apr 7 2011, 22:28
Go to the top of the page
 
+Quote Post
uzzzer
сообщение Apr 15 2011, 05:48
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 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
 
Go to the top of the page
 
+Quote Post
uzzzer
сообщение Apr 15 2011, 07:28
Сообщение #12


Частый гость
**

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



И еще: Если Ввожу не полную строку "START" или хотя бы строку больше двух символов, но содержащею, хотя бы один "S", то выводится, как будто ввел полностью слово, если больше 6 символов, то ввод прекращается уже не после третьего нажатия энтер, а послн первого или второго. Если только один "S", то на теминалке выводится до бесконечности мое сообщение.
такое чувство, что функция сравнения просто сравнивает первый символ...

Сообщение отредактировал uzzzer - Apr 15 2011, 07:32
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 04:05
Рейтинг@Mail.ru


Страница сгенерированна за 0.01471 секунд с 7
ELECTRONIX ©2004-2016