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

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


Местный
***

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



Цитата(prottoss @ Aug 3 2012, 08:09) *
2 Dikoy
а нужно использовать прерывание UDRE.

Помимо передачи, у меня есть ещё и приём. UDRE будет возникать в обоих случаях. Насколько помню, для разделения процессов приёма и передачи TxC/RxC и были придуманы. По крайней мере до этого я использовал именно их, и сейчас, после отключения лишних прерываний, данный код отлично работает.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 15:01
Сообщение #17


Гуру
******

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



Цитата(Dikoy @ Aug 3 2012, 17:51) *
Помимо передачи, у меня есть ещё и приём. UDRE будет возникать в обоих случаях.

Да ну?

Цитата
• Bit 5 – UDREn: USART Data Register Empty
The UDREn flag indicates if the transmit buffer (UDRn) is ready to receive new data. If UDREn is
one, the buffer is empty, and therefore ready to be written. The UDREn flag can generate a Data
Register Empty interrupt (see description of the UDRIEn bit).
UDREn is set after a reset to indicate that the Transmitter is ready.


Цитата(Dikoy @ Aug 3 2012, 17:51) *
Насколько помню, для разделения процессов приёма и передачи TxC/RxC и были придуманы.


RxC - флаг приёма.
TxC - байт передан, нужен для определения окончания передачи пакета (RS485 и тп)
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 3 2012, 15:34
Сообщение #18


Местный
***

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



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

Посмотрите, во что компилятор оптимизирует эту строчку.
Есть волшебное слово volatile.

Вы предполагаете, что компилятор засунул структуру в регистры? Зря. Даже если убрать #pragma pack(1), этого не будет.
Адрес берётся от расположения структуры или массива в ОЗУ, а нем от того, куда в итоге засунули данные.
Тем не менее, первое что я сделал, ещё до создания этой темы, это сделал волатайлом всё. Ничего не поменялось.

Цитата(_Артём_ @ Aug 3 2012, 19:01) *
Да ну?
RxC - флаг приёма.
TxC - байт передан, нужен для определения окончания передачи пакета (RS485 и тп)

Попробую, раз такая пьянка.
Но принимать данные то по RxC прерыванию?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 15:43
Сообщение #19


Гуру
******

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



Цитата(Dikoy @ Aug 3 2012, 18:34) *
Вы предполагаете, что компилятор засунул структуру в регистры? Зря. Даже если убрать #pragma pack(1), этого не будет.
Адрес берётся от расположения структуры или массива в ОЗУ, а нем от того, куда в итоге засунули данные.
Тем не менее, первое что я сделал, ещё до создания этой темы, это сделал волатайлом всё. Ничего не поменялось.

Похоже так, volatile нипричом.
Указатель в прерывании правильно меняется.
Может delay_cycles заменить чем-нибудь синхронизированным от таймера.
И стеки увеличить.

Цитата(Dikoy @ Aug 3 2012, 18:34) *
Но принимать данные то по RxC прерыванию?

Да, приём в USART0_RXC_vect или проверкой бита RxC, передача в USART0_UDRE_vect или проверкой бита UDRE (если USART0 используется).
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 3 2012, 23:10
Сообщение #20


Гуру
******

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



QUOTE (Dikoy @ Aug 3 2012, 05:59) *
Ещё до отключения SPI провёл эксперимент.
Все верно. 01, 02, 03 остались на своих местах и передаются. Значит прерывание и передача работают, и работают правильно. Портится содержимое структуры. Либо стеком, либо при записи по указателю где-то за пределы массива улетаете.
Начните с увеличения DATA STACK - 32 байта как-то несерьезно для серьезной программы. Если виноват стек - то его надо увеличивать минимум на размер этой структуры, ибо она портится вся. И то - это если она последняя перед стеком, а ведь весьма вероятно, что портится не только она. Радикальное решение - подправить скрипт линкера, чтобы он размещал RSTACK и CSTACK от конца памяти. Тогда для CSTACK автоматически будет доступна вся свободная память и вопрос выделения памяти под него отпадет автоматически. Насколько помню, это достигалось заменой '=' на '#' в командах размещения этих сегментов (и размещение RSTACK должно идти в скрипте до размещения CSTACK).


--------------------
На любой вопрос даю любой ответ
"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
_Артём_
сообщение Aug 4 2012, 00:09
Сообщение #21


Гуру
******

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



Цитата(Сергей Борщ @ Aug 4 2012, 02:10) *
Значит прерывание и передача работают, и работают правильно.

Запускал программу TC в симуляторе - данные только один раз передаются.
Но у меня ИАР 5.

Цитата(Сергей Борщ @ Aug 4 2012, 02:10) *
Портится содержимое структуры. Либо стеком,


А каким образом глобальные переменные стеком могут портится?
ИАР располагает их так(адреса увеличиваются):
СSTACK- RSTACK-глобальные переменные.
Стек растёт вниз.
В ИАР-е 3 и 4 по-другому что ли?

Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 4 2012, 01:01
Сообщение #22


Местный
***

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



Почитал про UDRE.
Получается, прерывание оное надо держать всегда выключеным. Включать только когда пошёл первый байт, и отключать до ухода последнего. Иначе флаг будет всегда стоять и МК из прерывания не выйдет.
Угумс?

Увеличил стек ажно до FF. Не помогло
Код
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
5F1A016900A5F19686581ADA8958A59199465F1A026900A5F19686581ADA8958A59199465F1A0369
00A5F19686581ADA8958A59199465F1A5F69
5F1A0169F8A4C19686571AF68950A56199065F1A0269F8A4C19686571AF68950A56199065F1A0369
F8A4C19686571AF68950A56199065F1A5D69
5F1A0169FCA4E19606581AD88954A57199465F1A0269FCA4E19606581AD88954A57199465F1A0369
FCA4E19606581AD88954A57199465F1A5E69
5F1A0169FCA4D196C6571AE88958A56199065F1A0269FCA4D196C6571AE88958A56199065F1A0369
FCA4D196C6571AE88958A56199065F1A5D69


Отключаю АЦП и всё снова работает:
Код
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 4 2012, 01:17
Сообщение #23


Гуру
******

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



Цитата(Dikoy @ Aug 4 2012, 04:01) *
Почитал про UDRE.
Получается, прерывание оное надо держать всегда выключеным. Включать только когда пошёл первый байт, и отключать до ухода последнего. Иначе флаг будет всегда стоять и МК из прерывания не выйдет.
Угумс?

Из прерывания выйдет, выполнит одну команду и опять войдёт. Но в общем так - угумс .

Код
void StopUartTx()
{
    UCSR0B&=~(1<<UDRIE0);
}
#pragma vector=USART0_UDRE_vect
__interrupt void ExtUartTx()
{
    unsigned char i=TxBuffer.ReadByte();
    UDR0=i;
    if (TxBuffer.BufferNotEmpty()==0)
        StopUartTx();
}
void StartUartTx()
/*
Если есть данные для передачи
*/
{
    UCSR1B|=(1<<UDRIE1);
}



Цитата(Dikoy @ Aug 4 2012, 04:01) *
Увеличил стек ажно до FF. Не помогло

Который стек? Или оба?

Цитата(Dikoy @ Aug 4 2012, 04:01) *
Отключаю АЦП и всё снова работает:

Потому чта АЦП - это зло, а DAC - добро.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 5 2012, 18:01
Сообщение #24


Местный
***

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





Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 5 2012, 19:39
Сообщение #25


Гуру
******

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



Цитата(Dikoy @ Aug 4 2012, 04:01) *
Отключаю АЦП и всё снова работает:

Возможно ошибка в чтении данных от АЦП:

Код
ADC1_temp = ADC1_RxC_counter;
   ADC1_temp--;  
    Buf_ADC1[ADC1_temp] = UDR2;

После того как ADC1_RxC_counter станет равным 0 прерывания по spi не запрещаются и если это прерывание как-нибудь возникнет, то оно начнет переписываться память вне массива Buf_ADC.
Нет ли возможности поставить data breakpoint на запись в TransmisionFrame?
Если есть то можно так выявить ошибку.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 5 2012, 20:32
Сообщение #26


Местный
***

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



Я уже писал тут где-то, что у меня цепь из 2 чипов по JTAG и дракон категорически отказывается отлаживать эту цепь, настраиваясь всегда на 1 чип. И как это изменить я так и не понял.
По этому отлаживаюсь методом UART+осциллограф.
По осциллу прерывания АЦП отрабатывают верно. Но косяк явно в нём.
Сейчас просто выключил таймер, который инициирует чтение АЦП, оставив се тела функций и прерываний активными, и всё работает. В смысле, передача корректна.
Стоит запустить процесс - и всё падает.

Увеличил оба стека до FF, ибо не жалко. Не помогает. Но если б стек переполнился, то а) компилер бы об этом сказал, б) всё бы рушилось и с отключённым таймером, ибо компиллер же не знает что без него все прерывания бесполезны и никогда не сработают.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 5 2012, 21:00
Сообщение #27


Гуру
******

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



Цитата(Dikoy @ Aug 5 2012, 23:32) *
Я уже писал тут где-то, что у меня цепь из 2 чипов по JTAG и дракон категорически отказывается отлаживать эту цепь, настраиваясь всегда на 1 чип. И как это изменить я так и не понял.
По этому отлаживаюсь методом UART+осциллограф.

Без jtag-а плохо.
А в симуляторе сбой возникает? Ведь у вас программа работает как spi-master и uart transmitter, значит ошибка возможно может проявится и в симуляторе.

Цитата(Dikoy @ Aug 5 2012, 23:32) *
Но если б стек переполнился, то а) компилер бы об этом сказал

Поставьте стеки CSTACK и RSTACK в 1-2 байта и увидите, что ИАР будет молчать как партизан.

Цитата(Dikoy @ Aug 5 2012, 23:32) *
всё бы рушилось и с отключённым таймером, ибо компиллер же не знает что без него все прерывания бесполезны и никогда не сработают.

Не обязательно рушилось бы: смотря что переполнилось: может и просто глючить непонятным образом.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 5 2012, 23:54
Сообщение #28


Местный
***

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



В общем, память однозначо перетирают прерывания от АЦП.
Код
volatile unsigned char laja; // TEST

#pragma vector=(0x48*0x02)
__interrupt void ADC3_RxC_isr(void) { //
    unsigned char ADC3_temp;
    
    ADC3_temp = ADC3_RxC_counter;
    ADC3_temp--;    
    laja = UDR1;
//   Buf_ADC3[ADC3_temp] = UDR1;

    if(ADC3_temp) {
        UDR1 = ADC3_temp;    
    } else {
        ADC3_CS_PASSIV;  
    }
    
    ADC3_RxC_counter = ADC3_temp;
     PORTA ^= ((1<<1));  
}


Как только слив данных поставил в volatile переменную вместо массивов, сразу всё стало пучкасто.
Провёл серию экспериментов, проинициализировал Buf_ADCx[], на выход идёт всё корректно. То есть цикл прерываний отрабатывается правильно, данные из временных буферов Buf_ADCx[] перекладываются во фрейм и т.д.
То есть рушит всё именно строчка Buf_ADCx[ADCx_temp] = UDRx;. Только непонятно почему - по лапе PORTA я вижу правильное число заходов в прерывание.
Go to the top of the page
 
+Quote Post
Petka
сообщение Aug 6 2012, 06:33
Сообщение #29


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

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(Dikoy @ Aug 6 2012, 03:54) *
В общем, память однозначо перетирают прерывания от АЦП.
Код
volatile unsigned char laja; // TEST

#pragma vector=(0x48*0x02)
__interrupt void ADC3_RxC_isr(void) { //
    unsigned char ADC3_temp;
    
    ADC3_temp = ADC3_RxC_counter;
    ADC3_temp--;    
    laja = UDR1;
//   Buf_ADC3[ADC3_temp] = UDR1;

    if(ADC3_temp) {
        UDR1 = ADC3_temp;    
    } else {
        ADC3_CS_PASSIV;  
    }
    
    ADC3_RxC_counter = ADC3_temp;
     PORTA ^= ((1<<1));  
}


Полный бред.
1) ADC3_temp = ADC3_RxC_counter;
2) ADC3_temp--;
3) Buf_ADC3[ADC3_temp] = UDR1;
4) ADC3_RxC_counter = ADC3_temp;
5) goto 1
Разумеется после обнуления ADC3_temp команда из п.2 сделает ADC3_temp==0xFF и тогда п.3 сломает память.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 6 2012, 11:12
Сообщение #30


Гуру
******

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



Цитата(Petka @ Aug 6 2012, 09:33) *
Разумеется после обнуления ADC3_temp команда из п.2 сделает ADC3_temp==0xFF и тогда п.3 сломает память.

Но для этого нужно чтобы возникло прерывание.Оно возникнет?

Цитата(kolobok0 @ Aug 3 2012, 00:41) *
нигде не указано, что менять местами поля нельзя в структуре. особенно первые и последнии.

А как указать чтобы поля не менялись местами?
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 14:45
Рейтинг@Mail.ru


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