Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32f100 USART задержка передачи и потеря символов
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
firstvald
Кристалл stm32f100. Плата Discovery.

Вижу, что передача по USART начинается с задержкой. Т е после записи в DR, на ножке процессора посылка появляется примерно через время равное передачи байта (без стопов и паритета) на выбранной скорости. Для 115200 физически передача начинается через 8 микросекунд, для 19200 - через 400, для 1200 - через 10 миллисекунд. Т е такое впечатление, что после записи в DR автомат вхолостую отрабатывает сдвиг регистра ничего не выдавая на ножку и после одного холостого цикла уже забирает данные из DR.

При одновременной работе нескольких портов теряется первый или второй байт в передаваемой последовательности или даже первый со вторым переставляются местами (во всех портах или в каком то одном , картина может меняться при изменении кода). Причем, даже в длинной последовательности все остальные байты передаются нормально. Это возникает при как при одновременной работе нескольких портов так и если оставить один порт.


Инициирование USART

CODE
//Инициируем UARTы

void USART1_INI(unsigned char spd, unsigned char par, unsigned char stp)
//spd - скорости обмена
// 10 115200
// 9 57600
// 8 38400
// 7 19200
// 6 9600
// 5 4800
// 4 2400
// 3 1200
// 2 600
//par - паритет
// 0 без паритета
// 1 нечетный паритет
// 2 четный паритет
//stp - число стоп битов
// 0, 1 - 1
// 2 - 2
//
//
//
{
GPIO_InitTypeDef GPIO_InitStructure;
short unsigned int i;



//*********************************************************
//Конфигурируем ножки под ввод вывод


//включаем тактирование портов
RCC->APB2ENR|=RCC_APB2ENR_IOPAEN;//GPIOA


//TX1 PA9
//Ножка назначается на вывод пуш пуль
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init( GPIOA , &GPIO_InitStructure);
//RX1 PA10
//Ножка назначается на ввод
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init( GPIOA , &GPIO_InitStructure);

USART1->CR1=0;
USART1->CR1|=USART_CR1_UE;//включили UART
USART1->CR1&=~USART_CR1_M;//8 бит
USART1->CR1&=~USART_CR1_WAKE;// пробуждение по IDLE LINE

//if(par==0){
USART1->CR1&=~USART_CR1_PCE;//без паритета
USART1->CR1&=~USART_CR1_PS;// нечетный паритет
USART1->CR1&=~USART_CR1_M;//8 бит
// }
if(par==1){
USART1->CR1|=USART_CR1_PCE;//паритет
USART1->CR1|=USART_CR1_PS;// нечетный паритет
USART1->CR1|=USART_CR1_M;//9 бит
}
if(par==2){
USART1->CR1|=USART_CR1_PCE;//паритет
USART1->CR1&=~USART_CR1_PS;// четный паритет
USART1->CR1|=USART_CR1_M;//9 бит
}



USART1->CR1|=USART_CR1_PEIE;//общее разрешение прерывания
// USART1->CR1|=USART_CR1_TXEIE;//разрешение прерывания по опустошению буфера передачи
USART1->CR1&=~USART_CR1_TXEIE;//запрещение прерывания по опустошению буфера передачи
USART1->CR1&=~USART_CR1_TCIE;//запрещено прерывание от "передача закончена"
//USART1->CR1|=USART_CR1_TCIE;// прерывание от "передача закончена"
USART1->CR1|=USART_CR1_RXNEIE;// разрешение прерывания по приему
USART1->CR1&=~USART_CR1_IDLEIE;//запрещено прерывание от IDLE
USART1->CR1|=USART_CR1_TE;//передатчик включен
USART1->CR1|=USART_CR1_RE;//приемник включен
USART1->CR1&=~USART_CR1_RWU;//приемник в активном режиме
USART1->CR1&=~USART_CR1_SBK;//запрос передачи длинного 0 выключен

USART1->CR2=0;
//if(stp<=1){//1 стоп
USART1->CR2&=~USART_CR2_STOP;//1 стоп
// }
if(stp==2){//2 стоп
USART1->CR2&=~USART_CR2_STOP;//1 стоп
USART1->CR2|=USART_CR2_STOP_1;//2 стоп
}

USART1->CR3=0;

USART1->SR&=0;//Флаги всех прерываний сбросили


USART1->BRR=0X0480;//19200
if(spd==10){
USART1->BRR=0X00C0;//115200
}

// готовим буферы обмена

//#define rx_buf_long 256
//#define tx_buf_long 256


i=0;
while(i<rx_buf_long){
rx_buf1[i]=0;
i++;
}
i=0;
while(i<tx_buf_long){
tx_buf1[i]=0;
i++;
}

USART1->SR=0;//СБРАСЫВАЕМ ФЛАГИ
// CTS
// LBD
// TC
// RXNE
// IDLE
// NE
//

rx_ptr1=0;
tx_ptr1=0;
//индекс последнего передаваемого элемента буфера
tx_last1=0;

rx_state1=0;
tx_state1=0;

}


Само прерывание от одного порта

CODE
void USART1_IRQHandler(void)
{
//прием
if((USART1->SR&USART_SR_RXNE)!=0) {//что то пришло
USART1->SR&=~USART_SR_RXNE;//сбросим флаг
rx_buf1[rx_ptr1]=USART1->DR;
if(rx_ptr1<rx_buf_long){
rx_ptr1++;
}

}//что то пришло

//передача

if((USART1->SR&USART_SR_TC)!=0) {//данные переписались из буфера в сдвиговый регистр и ушли из него
if(tx_state1==1){//идет передача
USART1->SR&=~USART_SR_TC;//сбросим флаг
if(tx_ptr1>=tx_last1){//ушел последний байт
tx_state1=0;
GPIOC->ODR &= ~GPIO_ODR_ODR4;// смотрим этой ножкой момент, когда закончилась передача
USART1->CR1&=~USART_CR1_TCIE ;
}//ушел последний байт
else{//передаем дальше
tx_ptr1++;
USART1->DR=tx_buf1[tx_ptr1];
}//передаем дальше
}//идет передача
else{//фантомное прерывание- мы ничего не должны передавать
USART1->CR1&=~USART_CR1_TCIE ;//сбросим разрешение этого прерывания
}//фантомное прерывание- мы ничего не должны передавать
}//данные переписались из буфера в сдвиговый регистр
USART1->SR=0;

}



и затравка которая начинает передачу:

CODE
InitGPIO();
Init_OSC_my();//инициализация и переключение синхронизации

USART1_INI(3,2,2);//1200







tx_buf1[0]=0x30;
tx_buf1[1]=0x31;
tx_buf1[2]=0x32;
tx_buf1[3]=0x33;
tx_buf1[4]=0x34;
tx_buf1[5]=0x35;
tx_buf1[6]=0x36;
tx_buf1[7]=0x37;
tx_buf1[8]=0x38;
tx_buf1[9]=0x39;
tx_buf1[10]=0x41;
tx_buf1[11]=0x42;
tx_buf1[12]=0x43;
tx_buf1[13]=0x44;
tx_buf1[14]=0x45;
tx_buf1[15]=0x46;
tx_buf1[16]=0x47;
tx_buf1[17]=0x48;
tx_buf1[18]=0x49;
tx_buf1[19]=0x4a;
tx_buf1[20]=0x4b;

tx_state1=1;
tx_last1=20;
tx_ptr1=0;


__NOP();



USART1->CR1|=USART_CR1_TCIE ;
GPIOC->ODR |= GPIO_ODR_ODR4;// между выставлением этой ножки и началом передачи на ножке - выдержка времени
USART1->DR=tx_buf1[tx_ptr1];
AlanDrakes
На кристалле STM32F107 работает следующий код:
CODE
uint8_t UART4_TX_BUFFER[UART_TX_BUFFER_SIZE]; // Буфер передачи UART'
volatile uint16_t UART4_TX_POS, UART4_WR_POS; // Указатели буфера.

void DMA2_Channel5_IRQHandler(void) {
if (DMA2->ISR & DMA_ISR_TCIF5) {
DMA2->IFCR = DMA_IFCR_CTCIF5; // Сбрасываем бит прерывания.
DMA_STATE &= ~DMA_STATE_UART_ACTIVE;
UART4_ActivateDMA();
};
};
void init_DMA_uart(void) {
RCC->AHBENR |= RCC_AHBENR_DMA2EN;
UART4->CR3 |= USART_CR3_DMAT;
UART4->SR &= ~USART_SR_TC;
DMA2_Channel5->CCR = 0;
DMA2_Channel5->CPAR = (uint32_t)&(UART4->DR);
NVIC_EnableIRQ(DMA2_Channel5_IRQn);
NVIC_SetPriority(DMA2_Channel5_IRQn, 0x04);
};

void init_uart(void) {
SystemCoreClockUpdate(); // Обновляем рабочую частоту.
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // Включаем тактирование порта с UART
GPIOC->ODR |= 0x00000C00; // Поднимаем пины.
GPIOC->CRH |= 0x0000FF00; // GPIOC[10:11] -> 50MHz, OpenDrain Alternate.
RCC->APB1ENR |= RCC_APB1ENR_UART4EN; // Включаем UART4
UART4->CR2 = 0; // Настройки. Сбрасываем.
UART4->CR3 = 0; // Продолжаем.
if (RCC->CFGR & RCC_CFGR_PPRE1_DIV2) {
UART4->BRR = (SystemCoreClock / 115200 / 2); // Ибо делим на 2
} else {
UART4->BRR = (SystemCoreClock / 115200); // Или не делим.
};
UART4->CR1 = (USART_CR1_TE | USART_CR1_RE | USART_CR1_UE); // Разрешаем работу UART.
init_DMA_uart();
};

void UART4_ActivateDMA(void) {
uint16_t CURR_WR_POS = UART4_WR_POS;
if (!(DMA_STATE & DMA_STATE_UART_ACTIVE)) {
DMA2_Channel5->CCR &= ~DMA_CCR_EN;
if (UART4_TX_POS == CURR_WR_POS) {
// Собственно, позиции начала и конца совпали.
} else {
// Есть разница между позициями буфера. Значит, нужно передавать данные.
// Начальная точка передачи - текущее значение указателя TX.
DMA2_Channel5->CMAR = (uint32_t)&(UART4_TX_BUFFER[(UART4_TX_POS)]); // Указатель на память
if (UART4_TX_POS < CURR_WR_POS) {
// Линия
DMA2_Channel5->CNDTR = (CURR_WR_POS - UART4_TX_POS); // Как раз нужная разница.
UART4_TX_POS = CURR_WR_POS;
} else {
// Кольцо
DMA2_Channel5->CNDTR = (UART_TX_BUFFER_SIZE - UART4_TX_POS);
UART4_TX_POS = 0;
};
DMA_STATE |= DMA_STATE_UART_ACTIVE;
DMA2_Channel5->CCR = (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_EN);
};
};
};

void console_put(char *text) {
// Можно попытаться написать под реализацию на двух каналах DMA... Тогда будет ещё быстрее.
while(*text) {
// Пока не нуль-терминатор
UART4_TX_BUFFER[UART4_WR_POS] = *text; // Копируем данные в буфер
text++; // Сдвигаем указатель текста.
UART4_WR_POS++; // Сдвигаем указатель на 1 байт дальше.
UART4_WR_POS = UART4_WR_POS & UART_TX_MASK; // Указатель должен быть в пределах допустимых значений.
};
// Здесь всё хорошо, записываем от старой позиции до новой.
UART4_ActivateDMA();
};

Используется DMA и буфер передачи (32/64/128 и более байт).
Данные не теряются при передаче.
firstvald



спасибо огромное!

это очень пригодится !
AlanDrakes
Да не за что.
Хотя, я просмотрел ваш код и тоже не нашёл никаких грубых ошибок. По идее, должны уходить нормально.
И учтите, я использую заголовочники от HAL, но сам стараюсь писать больше на регистрах.
А строки - нуль-терминированые.
Пример
uint8_t TXT_VAL = "Hello";
'H','e','l','l','o',/0
Ноль после последнего байта обязателен. Ну это так, на всякий случай.
firstvald
ну это важно если мы каким то подпиленным sprintf работаем. так я указываю индекс последнего символа в массиве который должен уйти на передачу. да я бы и не заметил подвоха если бы не стал внимательно смотреть что уходит и тестить в условиях одновременной работы трех портов.

раньше уже отмечали, что при интенсивном обслуживании прерываний были непонятки в работе тела прерывания. высказывалось предположение что процессор попадает в код тела прерывания до того как выставятся флаги. это из за ускорения обработки одновременно возникших прерываний. и воде бы помогала задержка в начале тела прерывания. буквально несколько строк пустого или не связанного с флагами кода. я пробовал набивать начало тела нопами - не, не помогает.
AlanDrakes
А нуль-терминированая строка может оказаться удобнее. Для функции передачи нужен только один параметр в стэке - позиция начала строки. Всё, что до нулевого символа будет скопировано в буфер отправки и передано.
Кстати, в моём коде - только отправка. Приём не требовался, потому под него ничего не писалось.
firstvald
это если передаем символы. последний раз у меня это было году так в 99. а дальше модбас RTU. там в пределах строки все что угодно может быть.
Genadi Zawidowski
О, сколько раз уже можно просить читать документацию....

Код
//прием
    if((USART1->SR&USART_SR_RXNE)!=0) {//что то пришло
        USART1->SR&=~USART_SR_RXNE;//сбросим флаг
        rx_buf1[rx_ptr1]=USART1->DR;


Бит RXNE It is cleared by a read to the USART_DR register
Сбрасывая его "вручную", рискуете сбросить лишнее.
Кроме того, сбрасывать надо так:
USART1->SR = ~ USART_SR_TC;

А не так, как у Вас:

USART1->SR&=~USART_SR_TC;

Разницу увидите сами (представьте себе, что флаг приёма символа появился после чтения SR, но перед обратной записью в этой строке).
На приёме тем более - гасятся прерывания от передатчика таким образом.
IgorKossak
firstvald, при ответе на крайнее сообщение нет нужды в цитировании. Это только загромождает форум.
Модератор
firstvald
Цитата(Genadi Zawidowski @ Mar 6 2016, 22:57) *


бит в регистре во все времена сбрасывался именно так:
регистр &=~ (слово размером с регистр с единичным выставленным битом);

хотя действительно предлагаемая функция USART_ClearFlag (из STM32F10X_USART.C)для сброса использует конструкцию
USARTx->SR = (uint16_t)~USART_FLAG; но это скорее исключение(довольно безграмотное), которое вероятно работает благодаря особенностям регистра SR.



При поочередной передаче флаг приема не может появится после попадания в тело прерывания, иначе как бы мы туда попали? и что вообще бы вызвало прерывание? это могло бы быть теоретически в случает одновременной передачи и приема, но обычный обмен с приборами такого не предполагает, идет запрос ответная работа. и при запросно -ответной работе появление прерывания от приема в момент передачи считается мусором и такие символы должны игнорироваться. аналогично появление прерывания от передачи в момент приема является мусором и его нужно игнорировать и выключить если оно по каким то причинам включилось.

на практике при передаче в приемник действительно может попадать мусор и в некоторых вариантах обмена передаваемая строка. во всех случаях эти символы должны игнорироваться.

посмотрел конструкцию

USART3->SR=~USART_SR_RXNE;//**сбросим флаг

тоже работает. но рекомендовать использовать это я бы никому не стал
Genadi Zawidowski
Цитата
При поочередной передаче флаг приема не может появится после попадания в тело прерывания, иначе как бы мы туда попали

Попали по поводу прерывания от примника, а сбросили флаг передатчика. Как он появился там? Да потому, что передатчик передваал-передавал себе символ, да и передал.

Если не хотите, можете продолжать... и считать допустимой работу "иногда". Как бит в переменно сбрасывается это одно, а как сбросить запрос прерывания в регистре с особенным поведением, это другое. Ситуацию со сбросом лишнего я Вам нарисовал.
firstvald
да нет. по флагу от передатчика сбрасывается флаг передатчика и по флагу приемника сбрасывается флаг приемника. а если кто остался несброшеным - сбросится перед выходом из прерывания.

я нигде не встречал указания, чтобы для сброса битов регистра SR требовался особый синтаксис, нигде больше не применяемый.
Genadi Zawidowski
При наличии других флагов прерывания (если они появились после чтения SR перед записью в него) они тоже сбросятся. Вы напишите на бумажке псевдокод того, как это произойдет.
firstvald
да сбросятся, но они мне тут не нужны . не в приеме дело - ту эффект вот какой:

я вижу вот что. пробую передать строку из 3 символов (0x30 0x31 0x32 ).

что происходит:
по записи (я все поотключал - таймеры и уарты- оставил только этот уарт) я сейчас с 3 работаю - там код одинаковый
USART3->DR=tx_buf3[tx_ptr3];
на ножку вовсе ничего не передается, но возникает прерывание с выставлением TC . у меня в прерывании честно указатель буфера инкрементируется и в регистр DR записывается следующий байт т е 1. и вот он появляется на ножке. а после выхода из прерывания на передачу отправляется 0 байт из буфера! т е в линии оказывается что нулевой и первый байты оказываются переставленными местами! а вот начиная со следующего прерывания последовательность передачи - правильная.

и я вижу что уходит 0x31 0x30 0x32

вот что происходит в начале - почему переставляется 0 и первый байт местами я понять не могу.

и спасибо огромное за внимание!
Genadi Zawidowski
Код
acc = SR 0x01
interrupt!
SR=0x03 - появился дополнительный бит
acc = acc & 0xfe = 0x01 & 0xfe = 0x00

SR = 0x00 - сбрасывабтся все биты вообще
firstvald
вот что удалось понять.

не зря обратил внимание, что байт уходит на передачу вовсе не сразу.
получается , что после инициирования приемопередатчика , несмотря на то, что он был явно сброшен вначале, он еще не готов к работе. ему необходим один (а может два) формальных циклов передачи, прежде чем он будет работать правильно. после того, как будут переданы пара байт, дальше приемопередатчик будет работать без пропусков и перестановок. это объясняет, почему не всегда на это поведение обращают внимание. в готовом приборе после первой битой посылки обмен будет происходить без замечаний.


т е, в инициализации приемопередатчика нужно предусмотреть формальную передачу одного двух байт. если критично появление посылок на ножках - переключение ножек на альтернативные функции нужно перенести после окончания посылки.

Код
    USART3->SR&=~USART_SR_TC;
    USART3->DR=0xff;
    while((USART3->SR&USART_SR_TC)==0){
;
                                         }
    
    
    USART3->SR&=~USART_SR_TC;


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

отмечу, что этот кусочек для скорости 115200 выполнятся порядка 100 микросекунд. т е десятикратно от длительности передачи одного байта.


посмотрю еще как все это себя ведет , может засада эшелонированная.
ViKo
Все не так, ребята! (с) ВВС
Проверьте все свои тактовые частоты на шинах.
Нужно проверять
if (USART2->SR & USART_SR_TXE && USART2->CR1 & USART_CR1_TXEIE) {
...
firstvald
а что значит проверить? скорости обмена соответствуют для линейки от 1200 до 115200. для шин 1 и 2 выбрано 1:1.

и это как-то может объяснить, что приемопередатчик умудряется переставить два байта местами? кстати, это означает, что унутре у него вовсе все не так устроено, как на блок схеме нарисовано.
ViKo
Цитата(firstvald @ Mar 7 2016, 13:55) *
и это как-то может объяснить, что приемопередатчик умудряется переставить два байта местами? кстати, это означает, что унутре у него вовсе все не так устроено, как на блок схеме нарисовано.

Я принимаю и передаю и никаких проблем не имею. Все согласно документации.

Первый байт посылаете не в прерывании. Разрешаете прерывания от TXE. Остальные байты посылаете по прерыванию. Сбрасывать флаг не нужно. Перед передачей последнего байта ('\n'), запрещаете прерывания.
firstvald
мне не нужно TXE , мне нужно TC. фокусы с \n не пройдут (да где вы все работаете что у вас символьные строки бегают до сих пор ?!). все что происходит я описал подробнейшим образом. и как лечится тоже.
ViKo
Цитата(firstvald @ Mar 7 2016, 14:18) *
мне не нужно TXE , мне нужно TC. фокусы с \n не пройдут (да где вы все работаете что у вас символьные строки бегают до сих пор ?!). все что происходит я описал подробнейшим образом. и как лечится тоже.

Я всякое передаю. Последний байт может быть любым, главное, знать, что он последний. Попробуйте TXE, если не хотите время терять (как свое, так и процессора).
firstvald
вот на самом деле именно обратно! чтобы понять, что мы окончили передачу, нужно использовать TC, иначе сразу начинается геморрой с выдержкой времени после TXE, да еще перестраиваемая в зависимости от скорости.

это, кстати, на одноплатках народ попадается - там тяп ляп сделано и когда используют RS485 и аппаратное управление направлением передачи, то в конце посылки 485 переключается на прием в момент, когда последний байт переписывается в сдвиговый регистр и еще не передался (но прерывание возникло, что в уарт можно писать следующее!), а его обкусили т к посчитали, что все уже передали.

TXE я, наверное, посмотрю, как он себя ведет. но дело не в них.
adnega
TXE и TC - это две большие разницы.
Записывать в буфер передатчика нужно по TXE, а после записи последнего байта пакета
разрешаем прерывание от TC. При возникновении TC можно быть уверенным, что байт полностью передан.
Сбрасывать флаги нужно как написано в документации (rc_w0), а не "как обычно".
firstvald
TC поднимается когда TXE выставлен -> записывая в буферный регистр по TC мы имеем двойную гарантию что делаем это вовремя: и из буферного регистра в сдвиговый переписались и уже и из сдвигового выдвинули.

да , флаги помечены как сбрасываются записью нуля (кстати, хорошее замечание). но отладчиком я вижу , что чтение модификация работают (да если посмотреть примеры кода в сети , то народ чтением модификацией стирает).
Сергей Борщ
Цитата(firstvald @ Mar 7 2016, 14:42) *
TC поднимается когда TXE выставлен -> записывая в буферный регистр по TC мы имеем двойную гарантию что делаем это вовремя:
Первой гарантии достаточно. Вторая гарантия даст только паузы между байтами если программа делет что-нибудь еще кроме передачи.
Цитата(firstvald @ Mar 7 2016, 14:42) *
да если посмотреть примеры кода в сети , то народ чтением модификацией стирает
Да если посмотреть примеры в сети, то народ и дорогу на красный переходит, и через двойную сплошную переезжает... Продолжать?
firstvald
сразу не сообразил.
чтение модификация запись - как раз точно то, что надо и делает.
флаг помечен как rc_w0 - т е его можно прочитать и он сбрасывается записью нуля.
ну так, чтение модификация запись собственно это и делает. мы прочитали (да, этого можно было и не делать) , сбросили нужный бит и записали .
все в стандартной, принятой для битовой работе манере. и то, что нужно по описанию регистру
AHTOXA
Ну какой же вы тупой! (с)
Цитата(firstvald @ Mar 7 2016, 17:59) *
ну так, чтение модификация запись собственно это и делает. мы прочитали (да, этого можно было и не делать) , сбросили нужный бит и записали .

Вам уже и пример привели, и на словах объяснили. Вы прочитали, там ещё несколько нулей. И все эти биты вы сбросили записью. А между тем моментом, когда вы прочитали, и записью, могли взвестись ещё флаги. И вы их таким образом потеряете.
Именно для того, чтобы избежать таких ситуаций, делают rc_w0. Чтобы можно было смело писать единичку в остальные биты, и от этого их состояние не менялось.
ViKo
Цитата(adnega @ Mar 7 2016, 15:11) *
... а после записи последнего байта пакета
разрешаем прерывание от TC. При возникновении TC можно быть уверенным, что байт полностью передан.

А когда (зачем) это нужно знать? А, ну если приемопередатчики RS-485 переключать со входа на выход...
firstvald
Цитата(AHTOXA @ Mar 7 2016, 17:32) *
Ну какой же вы тупой! (с)

Вам уже и пример привели, и на словах объяснили. Вы прочитали, там ещё несколько нулей. И все эти биты вы сбросили записью. А между тем моментом, когда вы прочитали, и записью, могли взвестись ещё флаги. И вы их таким образом потеряете.
Именно для того, чтобы избежать таких ситуаций, делают rc_w0. Чтобы можно было смело писать единичку в остальные биты, и от этого их состояние не менялось.


это надумано. тогда подумайте что будет в момент между чтением флагов когда мы решили что они нули и записью туда 0 прямой командой записи.
не повторяйте чужие мантры, учитесь думать сами и внимательно слушать, когда до вашего сведения аккуратно доводят, что тут что-то не так.
а как научитесь, милости просим на форум.

Цитата(ViKo @ Mar 7 2016, 17:49) *
А когда (зачем) это нужно знать? А, ну если приемопередатчики RS-485 переключать со входа на выход...


ну двухпроводной уарт в промышленности практически не используется (если только диагностический порт с морды или какой прибор с несетевым обменом). если только при общении с беспроводными модулями - у них еще отдельные TX RX. А так, поголовно RS485 (там где не TCP).
ViKo
Цитата(firstvald @ Mar 7 2016, 17:12) *
это надумано. тогда подумайте что будет в момент между чтением флагов когда мы решили что они нули и записью туда 0 прямой командой записи.

Вы не разобрались, как работает rc_w0. Такой бит можно прочитать, или сбросить, записав 0. А записать 1 в него невозможно. И поэтому можно смело записывать единицы, они не повредят.
firstvald
Цитата(ViKo @ Mar 7 2016, 15:02) *
Я принимаю и передаю и никаких проблем не имею. Все согласно документации.

Первый байт посылаете не в прерывании. Разрешаете прерывания от TXE. Остальные байты посылаете по прерыванию. Сбрасывать флаг не нужно. Перед передачей последнего байта ('\n'), запрещаете прерывания.



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

Цитата(ViKo @ Mar 7 2016, 18:19) *
Вы не разобрались, как работает rc_w0. Такой бит можно прочитать, или сбросить, записав 0. А записать 1 в него невозможно. И поэтому можно смело записывать единицы, они не повредят.

я -то как раз прекрасно разобрался в rc_w0
SasaVitebsk
Цитата(firstvald @ Mar 7 2016, 17:22) *
я -то как раз прекрасно разобрался в rc_w0

Странно, вам не кажется? Во всём разобрался, а не работает.
firstvald
Цитата(SasaVitebsk @ Mar 9 2016, 10:17) *
Странно, вам не кажется? Во всём разобрался, а не работает.


да у меня- то работает. а вы уверены, что у вас работет? описал фичу, написал как обойти, а "пронициательные читатели" так видно ничего не поняли. ну эта скрепа в порядке вещщей.
ViKo
Цитата(firstvald @ Mar 9 2016, 12:01) *
да у меня- то работает.

Вы понимаете, что у вас байты передаются с паузами, а могли бы идти сплошным потоком? Посмотрите осциллографом.
Genadi Zawidowski
Цитата
написал как обойти

Вы понимаете, что последовательный порт которому надо несколько символов чтобы запуститься - такого не бывает? Работает оно, из любого положения! И передает только то, что надо, пауз от себя не добавляет.
SasaVitebsk
Цитата(Genadi Zawidowski @ Mar 9 2016, 12:33) *
Вы понимаете ...

Были бы у автора хоть малейшие задатки критически оценивать свои действия, то тема бы закончилась после поста №8.
И закончилась бы просто словами "Спасибо".
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.