Balabes 0 20 августа, 2014 Опубликовано 20 августа, 2014 · Жалоба Здравствуйте! Подскажите как реализовать отправку в усарт содержимое буффера как только в нем что то появится? Допустим: есть uint8_t RXBuf, и как только в него записывается байт, надо переслать его по усарту. case 5: { write_command_reg(0x05); STATE++; break; } case 6: { if ( GPIO_ReadInputDataBit(GPIOA, IRQN) == 0) STATE++; break; } case 7: { StatusReg = read_status_reg(); if ((StatusReg & 0xD0) == 0xC0) STATE++; break; } case 8: { RXBuf = read_data_reg(); STATE++; break; } case 9: { STATE = 5; break; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 20 августа, 2014 Опубликовано 20 августа, 2014 · Жалоба Вот так, разве нет? case 8: { RXBuf = read_data_reg(); uart_send_byte(RXBuf); STATE++; break; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 20 августа, 2014 Опубликовано 20 августа, 2014 · Жалоба надо еще проверить что отправить можно и есть что отправлять, вдруг скорость входа данных быстрее скорости выхода или наоборот Так же просили ДМА, но в случае отправки 1 байта как появился, это смысла не имеет, запись 1 байта в буфер отправки гораздо быстрее чем настройка ДМА на передачу буфера. Вот если пакеты будут в много байт, то ДМА смысл имеет. На всякий случай замечу что речь идет про железный UART, который после помещения в него байта передает его на выход сам, не трогая проц. В случае программной эмуляции ДМА может быть оправдан, но там сложнее так что case 8: if(TX_BUF_READY) //готовы отправлять { if(read_data_reg(&Temp) == 0) //есть что отправлять UartSendByte(Temp); } STATE++; break; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Balabes 0 20 августа, 2014 Опубликовано 20 августа, 2014 · Жалоба хочется что бы контроллер этим не занимался и данные отправлялись не тратя время, что бы контроллер забрал следующий байт из модема и ничего не потерял. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 20 августа, 2014 Опубликовано 20 августа, 2014 · Жалоба хочется что бы контроллер этим не занимался и данные отправлялись не тратя время, что бы контроллер забрал следующий байт из модема и ничего не потерял. Если под "потерял" понимается пропуск байта изза ожидания завершения отправки типо: while (USART_GetFlagStatus(DECT_UART, USART_FLAG_TC) == RESET); То в данном случае буфер лучше заполнять в прерывании приема данных, а в основной программе проверять кол-во байт в буфере и выплевывать их в уарт. В данном случае уже можно будет использовать ДМА, понятно если накопится соответствующее кол-во байт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 20 августа, 2014 Опубликовано 20 августа, 2014 · Жалоба чтобы запустить ДМА грубо надо заполнить структуру, откуда, куда, сколько байт и так далее... Причем это делается не один раз а каждый раз при запуске. Это гораздо дольше чем считать 1 байт и положить его в передатчик. Если вы все равно попадает в 8 состояние где происходит проверка и забор байта, то вы сильно выиграете если сделаете без ДМА. Если то что приведено - это только схема, то тогда надо делать ДМА который по прерыванию готовы данные (данные от модема) берет их и кладет в буфер отправки. Данные от модема приходят по UART? если так то можно сделать ДМА их забирающие и перекладывающие в другой UART. Но встает вопрос скоростей, у STMов обычно нет FIFO на UARTах, и потому данные могут теряться или забиваться, если скорости входа - выхода не будут совпадать. В ДМА обычно есть цепочки, то есть отработав одну посылку он переключается на вторую, можно сделать посылки которые ссылаются друг на друга, и тогда эта схема будет работать вечно запуская сама себя. Если скорости разные, то имеет смысл сделать ДМА который собирает большое сообщение (если можно выделить пакет), и по окончанию сбора дернет вас прерыванием, в котором вы переложите этот принятый буфер в UART вторым ДМА, когда потери на настройку будут оправданы длинной посылкой. Ну или еще раз объясните какая у вас система, если я не смог правильно разгадать шараду:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 20 августа, 2014 Опубликовано 20 августа, 2014 (изменено) · Жалоба Вот работающий код. Скорости и форматы передачи не здесь - настраиваются ДО вызова stream_initialize. Скорость передачи по COM должна быть больше скорости заполнения. #define DMAUSART1BUFFSIZE8 128 static uint_fast8_t txbuffphase; static unsigned txbufflevel; static uint8_t txbuff [2] [DMAUSART1BUFFSIZE8]; void stream_putchar(uint_fast8_t c) { txbuff [txbuffphase] [txbufflevel] = c; if (++ txbufflevel >= DMAUSART1BUFFSIZE8) { DMA2->HIFCR = DMA_HIFCR_CTCIF7; // сбросил флаг от Stream7 - DMA готово начинать с начала // Запуск передачи заполненного буфера DMA2_Stream7->M0AR = (uint32_t) & txbuff [txbuffphase] [0]; DMA2_Stream7->CR |= DMA_SxCR_EN; // перезапуск DMA // Буфер заполнился - переключаемся на следующий буфер txbuffphase = ! txbuffphase; txbufflevel = 0; } } // Инициализация DMA по передаче USART1 void stream_initialize(void) { /* USART1_TX - Stream7, Channel4 */ /* DMA для передачи по USART1 */ RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // включил DMA2 __DSB(); DMA2_Stream7->PAR = (uint32_t) & USART1->DR; DMA2_Stream7->FCR &= ~ DMA_SxFCR_DMDIS; // use direct mode DMA2_Stream7->CR = (0 * DMA_SxCR_MBURST_0) | // 0: single transfer (0 * DMA_SxCR_PBURST_0) | // 0: single transfer (4 * DMA_SxCR_CHSEL_0) | //канал 4 (1 * DMA_SxCR_DIR_0) | //направление - память - периферия (1 * DMA_SxCR_MINC) | //инкремент памяти (0 * DMA_SxCR_MSIZE_0) | //длина в памяти - 8 bit (0 * DMA_SxCR_PSIZE_0) | //длина в USART_DR - 8 bit (0 * DMA_SxCR_CIRC) | //циклический режим не требуется при DBM (2 * DMA_SxCR_PL_0) | (0 * DMA_SxCR_CT) | // M0AR selected (0 * DMA_SxCR_DBM) | // double buffer mode seelcted 0; DMA2_Stream7->NDTR = (DMA2_Stream7->NDTR & ~ DMA_SxNDT) | (DMAUSART1BUFFSIZE8 * DMA_SxNDT_0) | 0; USART1->CR3 |= USART_CR3_DMAT; /*!< DMA Enable Transmitter */ } Изменено 21 августа, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Balabes 0 21 августа, 2014 Опубликовано 21 августа, 2014 · Жалоба модем это FX919 - и пока пытаюсь реализовать так называемый прозрачный режим, после 2х синхропосылок отправляю некоторые байты по одному непрерывно. а приняв их хочу выкинуть их в усарт. вот и хотелось бы что бы проц вынимал из модема новые байты и просто клал их куда-то а они дальше сами отправлялись что бы он успел взять все байты и не потерять, он же не сможет принять следующий байт пока я не достану этот. По скорости вроде запас есть, т.к. сам модем работает на 9600 (если кондюки и кварц сильно не врут) а усарт 19200. Так вот успеет ли f107 достать байт и положить его в усарт? когда передавал пакеты по 10\12\7 байт первые 10 принимал, но пока их отправлял второй и третий пакетик уже не успевал принять правильно (это было для тренировки, реализовывать решено начать именно с режима по байту). Пакеты будут позже. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 21 августа, 2014 Опубликовано 21 августа, 2014 · Жалоба так у этого модема параллельная шина. В вашем проце есть экстернал мемори интерфейс из которого ДМА сможет забрать данные? По первому описанию 107 проца вроде как нет... не очень понятно как при входной 9600 вы не могли успеть отправить на 19200. Прием полингом был сделан? Вам надо считать байт и сразу его положить одним тактом на выход. Так как входная скорость сильно меньше, выходной передатчик не может забиться, если работает. Вы же не используете управление потоком, правда? Если прием на прерываниях то в прерывании где вы забираете байт, сразу пихайте его на выход и всех делов, опять же нет шансов не успеть что-то забрать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Balabes 0 21 августа, 2014 Опубликовано 21 августа, 2014 · Жалоба как видите вот так RXBuf = read_data_reg(); USART_SendSymbol(USART2, RXBuf); STATE++; вот это некорректно принимает только до А нормально, потом хрень какая то. write_data_reg(outb); outb = outb + 0x01; write_command_reg(0x05); STATE++; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 21 августа, 2014 Опубликовано 21 августа, 2014 · Жалоба а точно read_data_reg возвращает не хрень? Может проблема не в отправке а в приеме? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Balabes 0 21 августа, 2014 Опубликовано 21 августа, 2014 · Жалоба с чего бы ей 10 раз прислать что надо, а потом хрень?) тем более что я делал прием трех пакетов и если их принять, а потом выкинуть в усарт то все нормально было Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 21 августа, 2014 Опубликовано 21 августа, 2014 · Жалоба USART_SendSymbol опубликуйте эту функцию... Есть подозрение что там просто добавление данных в буфер, и отправка по прерыванию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Balabes 0 21 августа, 2014 Опубликовано 21 августа, 2014 (изменено) · Жалоба void USART_SendSymbol(USART_TypeDef *USARTx, uint8_t data) { while((USART_GetFlagStatus(USARTx, USART_FLAG_TC)) == RESET); USART_SendData(USARTx, data); } и USART2->DR = RXBuf Аналогичные результаты дает. и даже на скоростях 115200 и 256000 тоже самое, попробую другой терминал на 115200 в Putty все нормально. Изменено 21 августа, 2014 пользователем Balabes Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 21 августа, 2014 Опубликовано 21 августа, 2014 · Жалоба мда... библиотеки это круто. то есть вместо взять регистр, выделить флаг, проверить на ноль, вы вызываете функцию в которой это делается, и проверяете результат ее работы... USART_FLAG_TC - это случаем не флаг что передача закончена? надо проверять не этот флаг, а флаг что приемник готов принять символ, ну и конечно делать это напрямую из регистра а не через долбанную функцию... едем дальше. Какой бы ни был терминал, он не может повлиять на передатчик, более того терминал отображает только то что принял железный приемник компьютера или драйвер в случае usb - com. То есть смена терминала не может влиять на смену принимаемых данных. Ищите что вы еще изменили, может у вас приемник в режиме автодетекции скорости или что-то типа того? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться