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

 
 
> UART и прерывания, передает назад не все
AnKing
сообщение Oct 21 2010, 00:00
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 2-02-08
Пользователь №: 34 686



не могу понять тут то ли строка записывается не до конца, то ли не до конца выводится

В гипертерминале ввожу (123-enter) подряд много раз
а в выводе получаю последовательно 1 потом после еще одного (123-enter) - 2, еще раз - 3 и пустая строка и так по кругу

Код
#include <avr\io.h>
#include <util\delay.h>
#include <stdlib.h>
#include <avr\interrupt.h>
//#include <stdio.h>  

char *StrToPrint; //указатель на строку которую будем выводить uart
char HelloWorld[]="Hello World";

//процедура отправки строки по UART////////
void u_send (char *str) {
    if (str==NULL) return;                    //проверяем не попался ли нам нулевой указатель, если попался то сразу выходим
    static char j=0;                         //счетчик
    if (*(str+j)!='\0'){                        //проверяем не достигнут ли конец строки
//    USART_Transmit('t');
//        UDR0=str[j];                            //отправляеме байт (так компилятор ругается почему то)
        UDR0=*(str+j);                        //то же самое тока компиляиор не ругается
        j++;                                //инкрементируем счетчик
    }
    else {
    UCSR0B&=~(_BV(UDRIE0));                    //запрещаем прерывание по опустошению регистра UDR
    j=0;                                    //сбрасываем счетчик;
    }
}
//////////////////////////////////////////

//////////////////////////////////////////

//процедура приема строки по UART с использованием прерываний////////
/*при первом вызове функции создаем указатель на char выделяем память под 1 символ,
ждем пока он не придет, когда пришел записываем его в выделенную память, если
есть еще символы то выделяем еще байт и так до тех пор пока все символы не кончатся.
При последуюющих вызовах функции сначала нужно очистить память которую выделяли в прошлый раз
для этого указатель str объявляли как static.

выход из функции происходит только когда придет символ '\r' или '\0'
*/
char * u_receive_int (void) {
static char * str=NULL;        //объявляем указатель на строку статическим что бы при повторных вызовах можно было очистить память
static int i=0;            //создаем счетчик
char temp;                    //временная переменная
if (i==0) {                //если i==0 то либо функция еще не вызывалась либо в прошлый раз строка закончилась и надо освободить память
    free(str);            //то освобождаем память
    str=NULL;            //сбрасываем указаель    
}
temp=UDR0;                     //Считываем принятый байт в temp
if ((temp!='\0')&&(temp!='\r')) {    //Если приянтый байт не равен '\r' или '\0' то:
    str=(char*) realloc(str, i+1);        //выделяем память под символы
    *(str+i)=temp;                    //записываем принятый байт в конец массива
    i++;                    //инкрементируем счетчик
    //PORTB=1<<1;
    return NULL;            //так так это еще не конец строки то возвращаем нулевой указатель
}
else {
    //PORTB=1<<2;
    *(str+i)='\0';                    //записываем '\0' в конец массива
    i=0;                             //обнуляем счетчик
    return str;                        // возвращаем указатель на область памяти, по которому можно обратиться к принятым данным
};

}

//////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////


//Обработчик прерывания от UART, по завершению приема//////////
SIGNAL(SIG_USART_RECV){
    StrToPrint=u_receive_int();     //
}
//////////////////////////////////////////////////////////////


//Обработчик прерывания от UART, по опустошению UDR//////////
SIGNAL(SIG_USART_DATA){
PORTB=1<<2;
    u_send (StrToPrint);
}
//////////////////////////////////////////////////////////////*/



void USART_Init( unsigned int baud )
    {
    // Set baud rate
    //UCSRB|=_BV(RXCIE); //Разрешение прерывания по завершению приема
    UBRR0H = (unsigned char)(baud>>8);
    UBRR0L = (unsigned char)baud;
    // Enable receiver and transmitter & interrupts
    UCSR0B = (1<<RXCIE0)|(1<<UDRIE0)|(1<<RXEN0)|(1<<TXEN0);
    // Set frame format: 8data, 1stop bit
    UCSR0C = (0<<USBS0)|(3<<UCSZ00);
    }


int main (void)
{
//char k='s';

DDRB=0x00;

USART_Init(47);

while(1){
    sei();

    //u_send(HelloWorld);
    if (StrToPrint){            //печатаем то на что указывает StrToPrint, если указатель нулевой, то ничего не напечатается
    u_send(StrToPrint);
    StrToPrint=NULL;                    //Если напечаталось, то сбрасываем указатель, что бы больш не печаталось
      }
    //printf("Hello, World");  //не работает
    _delay_ms(100);
}
}
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
AnKing
сообщение Oct 23 2010, 07:27
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 2-02-08
Пользователь №: 34 686



Спасибо что разъяснили, хотя над сдвигом еще придется голову поломать
Набросал себе такой хидер для удобства, точнее украл с avrfreaks
Код
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define GETBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define BITWRITE(c,p,m) (c ? SETBIT(p,m) : CLEARBIT(p,m))

на первое время я думаю покатит, все же лучше чем сдвиги самому продумывать

А вот кольцевой буфер идею которого я нашел где-то в гугле
Правда работать не хочет... и несколько отличается от того, что мне писали здесь, вместо указателейц используется побитовая маска, идею которой я, дурак, так и не понял
В статье писали что лучше всего использовать такой буфер в размерности 256, при этом битовую маску задавать одним байтом... может кто пояснит, спасибо.
Код
#define RXBUF_SIZE    16  //размер буфера обязательно равен степени двойки!
#define RXBUF_MASK    (RXBUF_SIZE-1)
#define BLOCK_TIMEOUT 10
#define BYTE_TIMEOUT 10
#define BLOCK_SIZE 8


unsigned char rxbuf[RXBUF_SIZE];
unsigned char inrx, outrx;

unsigned char rxtimeout = 0;

unsigned char idxDiff(unsigned char idxIN, unsigned char idxOUT, unsigned char bufsize)
{
    if (idxIN >= idxOUT){
        return (idxIN - idxOUT);
        FLIPBIT(PORTB,0);
        }
    else{
        return ((bufsize - idxOUT) + idxIN);
        FLIPBIT(PORTB,1);
        }
}

//программка отслеживает прием и его таймауты, и в зависимости от приема
// сбрасывает буфер либо переключает режим работы. Подпрограмма должна
// вызываться в бесконечном цикле main.
void usartPool (void)
{
    char value;
    unsigned char rxcnt = idxDiff (inrx, outrx, RXBUF_SIZE);
    if (0 == rxcnt)
    {
        //в буфере ничего нет
        if (rxtimeout >= BLOCK_TIMEOUT)
        {
            //в буфере ничего нет давно
            //...
        }
    }
    else if (rxcnt < BLOCK_SIZE)
    {
        //в буфере что-то есть, но мало
        if (rxtimeout >= BYTE_TIMEOUT)
        {
            //прошла слишком большая пауза между байтами,
            // сбрасываем буфер приема
            outrx = inrx;
        }
    }
    else
    {
        //в буфере корректно приняты BLOCK_SIZE байт,
        // обрабатываем данные
        //...
        do{
        value = rxbuf[outrx++];
        while ( !( UCSR0A & (1<<UDRE0)) ) UDR0 = value;
        outrx &= RXBUF_MASK;
        }
        while(inrx!=outrx);
    }
}


int main (void)
{
    
USART_Init(BAUD_PRESCALE);
sei();
   for(;;) // Loop forever
   {
   usartPool();
   }  
}
ISR(USART_RX_vect)
{
   char ReceivedByte;
   ReceivedByte = UDR0; // Fetch the recieved byte value into the variable "ByteReceived"
   //while ( !( UCSR0A & (1<<UDRE0)) )
   UDR0 = ReceivedByte; // Echo back the received byte back to the computer
   rxbuf[inrx++] = ReceivedByte;
   inrx &= RXBUF_MASK;
   rxtimeout = 0;
   FLIPBIT(PORTB,0);
}
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- AnKing   UART и прерывания   Oct 21 2010, 00:00
- - XVR   Использование malloc/free в AVR явно плохая идея, ...   Oct 21 2010, 08:51
|- - Danis   Цитата(XVR @ Oct 21 2010, 11:51) Использо...   Oct 21 2010, 17:33
|- - AnKing   Цитата(Danis @ Oct 21 2010, 21:33) Соглас...   Oct 21 2010, 19:05
- - smalcom   Цитатаstatic char j=0; //с...   Oct 21 2010, 08:55
- - AnKing   Переписал по другому, теперь легче разобраться заю...   Oct 21 2010, 16:12
|- - Сергей Борщ   Цитата(AnKing @ Oct 21 2010, 19:12) прога...   Oct 21 2010, 16:25
- - DpInRock   Вы бы посмотрели какие-нибудь примеры для начала. ...   Oct 21 2010, 16:24
|- - AnKing   Цитата(DpInRock @ Oct 21 2010, 20:24) Вы ...   Oct 21 2010, 17:03
|- - Danis   Цитата(DpInRock @ Oct 21 2010, 20:24) То,...   Oct 24 2010, 18:06
- - XVR   ЦитатаНо у меня почемуто ничего не происходитЧто б...   Oct 21 2010, 18:48
- - AnKing   Разобрался почему не работало... Было включено пре...   Oct 21 2010, 20:17
- - Danis   Цитата(AnKing @ Oct 21 2010, 23:17) как м...   Oct 22 2010, 04:04
- - AnKing   Вам это может показаться элементарным но все же ...   Oct 22 2010, 07:24
|- - Палыч   Цитата(AnKing @ Oct 22 2010, 11:24) Средн...   Oct 22 2010, 07:56
|- - Danis   Цитата(Палыч @ Oct 22 2010, 10:56) Символ...   Oct 22 2010, 08:36
|- - ILYAUL   Цитата(Палыч @ Oct 22 2010, 11:56) (учите...   Oct 22 2010, 08:56
|- - Danis   Цитата(ILYAUL @ Oct 22 2010, 12:56) Похож...   Oct 22 2010, 16:12
- - Палыч   Цитата(AnKing @ Oct 23 2010, 11:27) ... в...   Oct 23 2010, 08:00
- - rezident   Цитата(Палыч @ Oct 23 2010, 14:00) Если д...   Oct 23 2010, 19:15
- - Палыч   Цитата(rezident @ Oct 23 2010, 23:15) Иде...   Oct 24 2010, 11:18


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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 19:24
Рейтинг@Mail.ru


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