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

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Одноразовый UART в AVR, Отправляет данные корректно только 1 раз..
Dikoy
сообщение Aug 2 2012, 18:17
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



IAR 4.30, ATmega640.
Структура. Надо её всю слить в UART.
Беру указатель на начало и попёр. Вроде всё правильно. Но отправляется корректно она только первый раз, а потом идёт мусор.

CODE
#pragma pack(1)
typedef struct
{
unsigned char Length;
unsigned char Cmd;
unsigned char ADC1[ADCBUFSISE]; // ADCBUFSISE == 18
unsigned char ADC2[ADCBUFSISE];
unsigned char ADC3[ADCBUFSISE];
unsigned char crc_h;
unsigned char crc_l;
} Response_str;
#pragma pack()


Response_str TransmisionFrame;
unsigned char *pUart0_tx_pointer;


void USART0_Transmit( unsigned char data ) {
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}


// инициирую отправку пакета раз в 2 секунды, пакет отправляется 2 мс, по этому период огромен
void main( void ) {
while(1) {
pUart0_tx_pointer = &TransmisionFrame.Cmd;
USART0_Transmit( TransmisionFrame.Length );
__delay_cycles(8000000*8);

}
}


// прерывание
// USART0 Transmitter interrupt service routine
#pragma vector=(0x36*0x02)
__interrupt void USART0_TXC_isr(void) { //

if( pUart0_tx_pointer <= &TransmisionFrame.crc_l ) {
UDR0 = *pUart0_tx_pointer++;
}
}


Результат:

Код
223A0000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000A55A - верный пакет
1A606908A5019746581A058A58A58199C65F1A606908A5019746581A058A58A58199C65F1A606908
A5019746581A058A58A58199C65F1A606908 - лажа
1A626910A52197C6581A078A64A5A19906601A626910A52197C6581A078A64A5A19906601A626910
A52197C6581A078A64A5A19906601A626910 - лажа


Подумал, указатель сползает... Сделал так:

Код
while( 1 )
  {
    pUart0_tx_pointer = &TransmisionFrame.Cmd;
    USART0_Transmit( TransmisionFrame.Length );  
    __delay_cycles(8000000*8);
    memset( &TransmisionFrame, 0xAA, sizeof(TransmisionFrame) );    
  }


Получил:

Код
223A0000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000A55A
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


Лага категорически не вижу sad.gif

Сообщение отредактировал IgorKossak - Aug 2 2012, 18:23
Причина редактирования: [codebox] для длинного кода!!!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 2 2012, 21:34
Сообщение #2


Гуру
******

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



Что-то (стек?) затирает содержимое структуры после первой передачи. Можно заполнять какое-либо поле структуры константой непосредственно перед передачей, чтобы подтвердить или опровергнуть это предположение.


--------------------
На любой вопрос даю любой ответ
"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
kolobok0
сообщение Aug 2 2012, 21:41
Сообщение #3


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Dikoy @ Aug 2 2012, 22:17) *
...инициирую отправку пакета раз в 2 секунды, пакет отправляется 2 мс...
Код
..1A606908-A5019746581A058A58A58199C65F1A606908-A5019746581A058A58A58199C65F1A606908-A5019746581A058A58A58199C65F1A606908 - лажа
1A626910-A52197C6581A078A64A5A19906601A626910-A52197C6581A078A64A5A19906601A626910-A52197C6581A078A64A5A19906601A626910 - лажа
...


1) что то по времени не понятно. скорость какая порта? структура имеет 3*18+4=58 байт. за две милисекунды - дюже скорость не плохая...

2) у вас повтор идёт 18 байтовый в посылках которая лажа...

3) программа плохо написана. нигде не указано, что менять местами поля нельзя в структуре. особенно первые и последнии. не факт что кто то это будет знать через много дней. или вообще что такие поля будут существовать.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 3 2012, 02:59
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Да, скорее всего стек...
18 байт, это размер массивов ADCх[ADCBUFSISE]; в структуре.
У меня три порта USART в режиме SPI читают три АЦП и складывают байты в промежуточные буферы.
Потом эти буферы быстренько перекладываются в данную структуру и она уходит на отправку через UART0. Приложил проект, если кому интересно.
Сейчас полностью отключил эти SPI и их обработку, закомментировав adc_hardware_init();, и всё стало работать идеально.

Значит прерывания дерутся. Расширить стек?

2kolobok0: скорость мегабит, через FT232R. При тупом поллинге работает прекрасно, это далеко не первый прибор такой, дело не в железе.
Структура - стандартный протокол. Никто ничего менять и не будет wink.gif


Цитата(Сергей Борщ @ Aug 3 2012, 00:34) *
Что-то (стек?) затирает содержимое структуры после первой передачи. Можно заполнять какое-либо поле структуры константой непосредственно перед передачей, чтобы подтвердить или опровергнуть это предположение.

Ещё до отключения SPI провёл эксперимент.

CODE

do {
pUart0_tx_pointer = &(TransmisionFrame.Length);
TransmisionFrame.ADC1[0] = 0x01;
TransmisionFrame.ADC2[0] = 0x02;
TransmisionFrame.ADC3[0] = 0x03;
UDR0 = *pUart0_tx_pointer++;

__delay_cycles(8000000*8);

} while(1);

//***************************

223A01000000000000000000000000000000000002000000000000000000
0000000000000000030000000000000000000000000000000000A55A

5F1A016908A5119746581AD3895CA59199C65F1A026908A5119746581AD3
895CA59199C65F1A036908A5119746581AD3895CA59199C65F1A6169

5F1A016908A5119786581AEE8960A59199C65F1A026908A5119786581AEE
8960A59199C65F1A036908A5119786581AEE8960A59199C65F1A6069


Как видно, первый раз всё срабатывает, а потом кирдык.

Размер стека по умолчанию, 32 бутеса...



Go to the top of the page
 
+Quote Post
prottoss
сообщение Aug 3 2012, 04:09
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



2 Dikoy
Вы не верно строите прерывание. Как Вы знаете, в USART AVR при передаче работают два регистра - UDR (Доступен из программы пользователя) и Transmit Shift Register (будем для краткости называть его TSR). Когда Вы записываете данные в UDR, они, если TSR пуст, автоматически переписываются в него. Второй как раз занимается передачей последовательных данных на выход TXDx. О состоянии этих регистров можно судить по флагам UDRE (регистр данных пуст) и TXC (TSR пуст). Так вот, не нужно при передаче пакета данных использовать прерывание TXC, а нужно использовать прерывание UDRE. А вот окончание сеанса передачи всего пакета уже можно отследить по TXC, т.е. данных для отправки нет, и TSR освободился.


--------------------
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 3 2012, 08:44
Сообщение #6


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Может организуйте fifo для отправки данных?

CODE
unsigned char Rx0Buf[UART_0_RXBUFSIZE];// the receiver buffer.
unsigned char Rx0Head = 0;// the circular buffer index
unsigned char Rx0Tail = 0;
unsigned char Tx0Buf[UART_0_TXBUFSIZE];// the transmit buffer.
unsigned int Tx0Head = 0;// the circular buffer index
unsigned int Tx0Tail = 0;

signed int _getcharUART0()
{
__disable_interrupt();
signed int temp = -1;
if (Rx0Tail != Rx0Head)
{
temp = Rx0Buf[Rx0Tail++];
if (Rx0Tail >= UART_0_RXBUFSIZE) Rx0Tail = 0;
}
__enable_interrupt();
return(temp);
}

void _putcharUART0(signed char in_char)
{
__disable_interrupt();
if ((Tx0Head == Tx0Tail) && (UCSR0A & (1<<UDRE0)))
{
UDR0 = in_char;
}
else
{

Tx0Buf[Tx0Head++] = (unsigned char) in_char;
if (Tx0Head >= UART_0_TXBUFSIZE) Tx0Head = 0;
}
__enable_interrupt();
}


#pragma vector=USART0_RX_vect
__interrupt void USART0_RX_IRQ(void)
{
Rx0Buf[Rx0Head++] = UDR0;
if (Rx0Head >= UART_0_RXBUFSIZE) Rx0Head = 0;
}

#pragma vector = USART0_TX_vect
__interrupt void USART0_TX_IRQ(void)
{
if (Tx0Tail != Tx0Head)
{
UDR0 = Tx0Buf[Tx0Tail++]; // send a byte of data
if (Tx0Tail >= UART_0_TXBUFSIZE) Tx0Tail = 0;// check for wrap around.
}
}


Закидываете всю структуру сразу на передачу с помощью

Код
while(size--)
{
_putcharUART0(*pStruct++);
}


size - размер структуры
pStruct - указатель на первый её элемент

Подобное fifo 100% рабочее применялось во многих моих серийных проектах на AVR.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 10:51
Сообщение #7



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Код
while( 1 )
  {
    pUart0_tx_pointer = &TransmisionFrame.Cmd;
...
  }

Посмотрите, во что компилятор оптимизирует эту строчку.
Есть волшебное слово volatile.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 11:02
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 13:51) *
Код
while( 1 )
  {
    pUart0_tx_pointer = &TransmisionFrame.Cmd;
...
  }

Посмотрите, во что компилятор оптимизирует эту строчку.

Несоптимизировал компилятор строчку.

Цитата(xemul @ Aug 3 2012, 13:51) *
[code]while( 1 )
Есть волшебное слово volatile.

Кого здесь volatile делать?

Сообщение отредактировал IgorKossak - Aug 3 2012, 11:27
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 11:56
Сообщение #9



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 15:02) *
Несоптимизировал компилятор строчку.

У меня нет иара, чтобы проверить, но, имхо, любой компилятор вынесет указанную строку в init() при любом отличном от 0 уровне оптимизации.
Цитата
Кого здесь volatile делать?

Есть варианты?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 12:18
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 14:56) *
У меня нет иара, чтобы проверить, но, имхо, любой компилятор вынесет указанную строку в init() при любом отличном от 0 уровне оптимизации.

И что будет? Работать перестанет?

Цитата(xemul @ Aug 3 2012, 14:56) *
Есть варианты?

Как минимум два.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 12:25
Сообщение #11



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 16:18) *
И что будет? Работать перестанет?

Будет работать именно так, как написано - передавать по TransmisionFrame.Length байтов, начиная с pUart0_tx_pointer. Но pUart0_tx_pointer будет равен &TransmisionFrame.Cmd только единожды.
Без оптимизации будет работать как задумано, кроме, вероятно, __delay_cycles().
Цитата
Как минимум два.

Да ну? "Огласите, пожалуйста, весь список", и с комментами, если можно.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 12:43
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 15:25) *
Да ну? "Огласите, пожалуйста, весь список", и с комментами, если можно.


Код
volatile Response_str TransmisionFrame;
unsigned char * volatile  pUart0_tx_pointer;


Строчка
Код
__delay_cycles(8000*8);

вызывает варнинги
Цитата
Warning[Pe061]: integer operation result is out of range FirstChip\main.c 162
Warning[Pe068]: integer conversion resulted in a change of sign FirstChip\main.c 162

и программа дальше не идёт.

Если так:
Код
__delay_cycles(8000UL*8);

то идёт.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 12:48
Сообщение #13



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 16:31) *
Код
volatile Response_str TransmisionFrame;

Из приведённого ТС кода не следует, что TransmisionFrame имеет смысл объявлять volatile, но прокатит. Правда, потянет за собой оверхед при обращениях к TransmisionFrame.
Цитата
Код
unsigned char * volatile  pUart0_tx_pointer;

Йес-с-с, Вы угадали. Это единственная переменная, модифицируемая в прерывании, и только в прерывании.
Почти тот же эффект получится, если внутри while(1) {} pUart0_tx_pointer будет как-нибудь бесполезно изменяться, но так, чтобы компилятор не догадался, что оно бесполезно.

__delay_xxx() не использую, но в комментах к подобным функциям обычно оговаривается уровень оптимизации, достаточный, чтобы они не выдавали цену на дрова.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 13:07
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 15:48) *
Йес-с-с, Вы угадали. Это единственная переменная, модифицируемая в прерывании, и только в прерывании.

Прыз в студию...

Цитата(xemul @ Aug 3 2012, 15:48) *
Почти тот же эффект получится, если внутри while(1) {} pUart0_tx_pointer будет как-нибудь бесполезно изменяться, но так, чтобы компилятор не догадался, что оно бесполезно.

Обычно и без volatile работает. Хотя случаи могут быть разные.

Цитата(xemul @ Aug 3 2012, 15:48) *
__delay_xxx() не использую, но в комментах к подобным функциям обычно оговаривается уровень оптимизации, достаточный, чтобы они не выдавали цену на дрова.

Там только про то говорится что параметр - константа. И всё.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 13:19
Сообщение #15



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 17:07) *
Обычно и без volatile работает. Хотя случаи могут быть разные.

Вольному - воля.
Цитата
Там только про то говорится что параметр - константа. И всё.

Тогда скорее всего в иар в либах живёт что-то вроде void __delay(unsigned long), а __delay_xxx() выполнены её обёртками.
В gcc-avr, если склероз не врёт, подобное шло в сорцах и с оговорками.
Go to the top of the page
 
+Quote Post

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

 


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


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