firstvald
Mar 6 2016, 12:58
Кристалл 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
Mar 6 2016, 14:43
На кристалле 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
Mar 6 2016, 16:22
спасибо огромное!
это очень пригодится !
AlanDrakes
Mar 6 2016, 16:37
Да не за что.
Хотя, я просмотрел ваш код и тоже не нашёл никаких грубых ошибок. По идее, должны уходить нормально.
И учтите, я использую заголовочники от HAL, но сам стараюсь писать больше на регистрах.
А строки - нуль-терминированые.
Пример
uint8_t TXT_VAL = "Hello";
'H','e','l','l','o',/0
Ноль после последнего байта обязателен. Ну это так, на всякий случай.
firstvald
Mar 6 2016, 16:44
ну это важно если мы каким то подпиленным sprintf работаем. так я указываю индекс последнего символа в массиве который должен уйти на передачу. да я бы и не заметил подвоха если бы не стал внимательно смотреть что уходит и тестить в условиях одновременной работы трех портов.
раньше уже отмечали, что при интенсивном обслуживании прерываний были непонятки в работе тела прерывания. высказывалось предположение что процессор попадает в код тела прерывания до того как выставятся флаги. это из за ускорения обработки одновременно возникших прерываний. и воде бы помогала задержка в начале тела прерывания. буквально несколько строк пустого или не связанного с флагами кода. я пробовал набивать начало тела нопами - не, не помогает.
AlanDrakes
Mar 6 2016, 16:46
А нуль-терминированая строка может оказаться удобнее. Для функции передачи нужен только один параметр в стэке - позиция начала строки. Всё, что до нулевого символа будет скопировано в буфер отправки и передано.
Кстати, в моём коде - только отправка. Приём не требовался, потому под него ничего не писалось.
firstvald
Mar 6 2016, 16:49
это если передаем символы. последний раз у меня это было году так в 99. а дальше модбас RTU. там в пределах строки все что угодно может быть.
Genadi Zawidowski
Mar 6 2016, 18:57
О, сколько раз уже можно просить читать документацию....
Код
//прием
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
Mar 6 2016, 19:56
firstvald, при ответе на крайнее сообщение нет нужды в цитировании. Это только загромождает форум.
Модератор
firstvald
Mar 6 2016, 20:45
Цитата(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
Mar 6 2016, 20:47
Цитата
При поочередной передаче флаг приема не может появится после попадания в тело прерывания, иначе как бы мы туда попали
Попали по поводу прерывания от примника, а сбросили флаг передатчика. Как он появился там? Да потому, что передатчик передваал-передавал себе символ, да и передал.
Если не хотите, можете продолжать... и считать допустимой работу "иногда". Как бит в переменно сбрасывается это одно, а как сбросить запрос прерывания в регистре с особенным поведением, это другое. Ситуацию со сбросом лишнего я Вам нарисовал.
firstvald
Mar 6 2016, 21:03
да нет. по флагу от передатчика сбрасывается флаг передатчика и по флагу приемника сбрасывается флаг приемника. а если кто остался несброшеным - сбросится перед выходом из прерывания.
я нигде не встречал указания, чтобы для сброса битов регистра SR требовался особый синтаксис, нигде больше не применяемый.
Genadi Zawidowski
Mar 6 2016, 21:15
При наличии других флагов прерывания (если они появились после чтения SR перед записью в него) они тоже сбросятся. Вы напишите на бумажке псевдокод того, как это произойдет.
firstvald
Mar 6 2016, 21:28
да сбросятся, но они мне тут не нужны . не в приеме дело - ту эффект вот какой:
я вижу вот что. пробую передать строку из 3 символов (0x30 0x31 0x32 ).
что происходит:
по записи (я все поотключал - таймеры и уарты- оставил только этот уарт) я сейчас с 3 работаю - там код одинаковый
USART3->DR=tx_buf3[tx_ptr3];
на ножку вовсе ничего не передается, но возникает прерывание с выставлением TC . у меня в прерывании честно указатель буфера инкрементируется и в регистр DR записывается следующий байт т е 1. и вот он появляется на ножке. а после выхода из прерывания на передачу отправляется 0 байт из буфера! т е в линии оказывается что нулевой и первый байты оказываются переставленными местами! а вот начиная со следующего прерывания последовательность передачи - правильная.
и я вижу что уходит 0x31 0x30 0x32
вот что происходит в начале - почему переставляется 0 и первый байт местами я понять не могу.
и спасибо огромное за внимание!
Genadi Zawidowski
Mar 6 2016, 21:31
Код
acc = SR 0x01
interrupt!
SR=0x03 - появился дополнительный бит
acc = acc & 0xfe = 0x01 & 0xfe = 0x00
SR = 0x00 - сбрасывабтся все биты вообще
firstvald
Mar 7 2016, 10:10
вот что удалось понять.
не зря обратил внимание, что байт уходит на передачу вовсе не сразу.
получается , что после инициирования приемопередатчика , несмотря на то, что он был явно сброшен вначале, он еще не готов к работе. ему необходим один (а может два) формальных циклов передачи, прежде чем он будет работать правильно. после того, как будут переданы пара байт, дальше приемопередатчик будет работать без пропусков и перестановок. это объясняет, почему не всегда на это поведение обращают внимание. в готовом приборе после первой битой посылки обмен будет происходить без замечаний.
т е, в инициализации приемопередатчика нужно предусмотреть формальную передачу одного двух байт. если критично появление посылок на ножках - переключение ножек на альтернативные функции нужно перенести после окончания посылки.
Код
USART3->SR&=~USART_SR_TC;
USART3->DR=0xff;
while((USART3->SR&USART_SR_TC)==0){
;
}
USART3->SR&=~USART_SR_TC;
после инициализации и вот такого кусочка кода, дальше посылки уходят правильно.
отмечу, что этот кусочек для скорости 115200 выполнятся порядка 100 микросекунд. т е десятикратно от длительности передачи одного байта.
посмотрю еще как все это себя ведет , может засада эшелонированная.
Все не так, ребята! (с) ВВС
Проверьте все свои тактовые частоты на шинах.
Нужно проверять
if (USART2->SR & USART_SR_TXE && USART2->CR1 & USART_CR1_TXEIE) {
...
firstvald
Mar 7 2016, 10:55
а что значит проверить? скорости обмена соответствуют для линейки от 1200 до 115200. для шин 1 и 2 выбрано 1:1.
и это как-то может объяснить, что приемопередатчик умудряется переставить два байта местами? кстати, это означает, что унутре у него вовсе все не так устроено, как на блок схеме нарисовано.
Цитата(firstvald @ Mar 7 2016, 13:55)

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

мне не нужно TXE , мне нужно TC. фокусы с \n не пройдут (да где вы все работаете что у вас символьные строки бегают до сих пор ?!). все что происходит я описал подробнейшим образом. и как лечится тоже.
Я всякое передаю. Последний байт может быть любым, главное, знать, что он последний. Попробуйте TXE, если не хотите время терять (как свое, так и процессора).
firstvald
Mar 7 2016, 12:02
вот на самом деле именно обратно! чтобы понять, что мы окончили передачу, нужно использовать TC, иначе сразу начинается геморрой с выдержкой времени после TXE, да еще перестраиваемая в зависимости от скорости.
это, кстати, на одноплатках народ попадается - там тяп ляп сделано и когда используют RS485 и аппаратное управление направлением передачи, то в конце посылки 485 переключается на прием в момент, когда последний байт переписывается в сдвиговый регистр и еще не передался (но прерывание возникло, что в уарт можно писать следующее!), а его обкусили т к посчитали, что все уже передали.
TXE я, наверное, посмотрю, как он себя ведет. но дело не в них.
TXE и TC - это две большие разницы.
Записывать в буфер передатчика нужно по TXE, а после записи последнего байта пакета
разрешаем прерывание от TC. При возникновении TC можно быть уверенным, что байт полностью передан.
Сбрасывать флаги нужно как написано в документации (rc_w0), а не "как обычно".
firstvald
Mar 7 2016, 12:42
TC поднимается когда TXE выставлен -> записывая в буферный регистр по TC мы имеем двойную гарантию что делаем это вовремя: и из буферного регистра в сдвиговый переписались и уже и из сдвигового выдвинули.
да , флаги помечены как сбрасываются записью нуля (кстати, хорошее замечание). но отладчиком я вижу , что чтение модификация работают (да если посмотреть примеры кода в сети , то народ чтением модификацией стирает).
Сергей Борщ
Mar 7 2016, 12:54
Цитата(firstvald @ Mar 7 2016, 14:42)

TC поднимается когда TXE выставлен -> записывая в буферный регистр по TC мы имеем двойную гарантию что делаем это вовремя:
Первой гарантии достаточно. Вторая гарантия даст только паузы между байтами если программа делет что-нибудь еще кроме передачи.
Цитата(firstvald @ Mar 7 2016, 14:42)

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

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

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

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

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

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

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

Вы не разобрались, как работает rc_w0. Такой бит можно прочитать, или сбросить, записав 0. А записать 1 в него невозможно. И поэтому можно смело записывать единицы, они не повредят.
я -то как раз прекрасно разобрался в rc_w0
SasaVitebsk
Mar 9 2016, 06:17
Цитата(firstvald @ Mar 7 2016, 17:22)

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

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

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

Вы понимаете ...
Были бы у автора хоть малейшие задатки критически оценивать свои действия, то тема бы закончилась после поста №8.
И закончилась бы просто словами "Спасибо".
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.