ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
1430795 Топик полностью
SciFi (28.04.2024 18:38, просмотров: 236) ответил RxTx на Спасибо, Коль, за объяснение, всегда приятно тебя читать. Да, DMA это достаточно несложно, автора видать отпугивает непонятность реализации. А реализовать его проще всего "поженив" с программным циркулярным буфером. Тогда "пишущий" в буфер указатель (или лучше index) будет программный. "Заворачивается" он банальным AND, т.е. &= . А читающий указатель (или index) выполняется на DMA с тем нюансом что надо будет обслужить "заворот".
Вот, например: 
#include "uart.h"
#include "stm32f107xc.h"
#include "systime.h"
#include <string.h>
#define RX_BUFSIZE 64 #define TX_BUFSIZE 64
static USART_TypeDef* const usart = USART1; static uint8_t volatile rxfifo[RX_BUFSIZE]; static uint8_t volatile txbuf[TX_BUFSIZE]; static unsigned int rxtail, txhead; static DMA_Channel_TypeDef* const txstream = DMA1_Channel4; static DMA_Channel_TypeDef* const rxstream = DMA1_Channel5;
void uart_init(void) { rxstream->CMAR = (int)&rxfifo; rxstream->CPAR = (int)&usart->DR; rxstream->CNDTR = RX_BUFSIZE; rxstream->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN; uart_mode_boot(); }
void uart_mode_norm(void) { usart->BRR = SYSTIME_TPS / 4000000; usart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; usart->CR3 |= USART_CR3_HDSEL; }
void uart_mode_boot(void) { usart->BRR = SYSTIME_TPS / 57600; usart->CR3 = USART_CR3_DMAR | USART_CR3_DMAT; usart->CR1 = USART_CR1_PCE | USART_CR1_M | USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; }
bool uart_txe(void) { return txstream->CNDTR == 0; }
void uart_putbytes(const void* src, int n) { memcpy((void*)(txbuf + txhead), src, n); txhead += n; }
void uart_putbyte(int b) { txbuf[txhead++] = b; }
int uart_send(void) { while (!uart_txe()) ; txstream->CCR = 0; while (txstream->CCR & DMA_CCR_EN) ; DMA1->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTCIF4 | DMA_IFCR_CHTIF4 | DMA_IFCR_CTEIF4; txstream->CMAR = (int)txbuf; txstream->CPAR = (int)&usart->DR; txstream->CNDTR = txhead; txstream->CCR = DMA_CCR_DIR | DMA_CCR_MINC | DMA_CCR_EN; int ret = txhead; txhead = 0; return ret; }
void uart_sendbytes(const void* src, int n) { while (!uart_txe()) ; txstream->CCR = 0; while (txstream->CCR & DMA_CCR_EN) ; DMA1->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTCIF4 | DMA_IFCR_CHTIF4 | DMA_IFCR_CTEIF4; txstream->CMAR = (int)src; txstream->CPAR = (int)&usart->DR; txstream->CNDTR = n; txstream->CCR = DMA_CCR_DIR | DMA_CCR_MINC | DMA_CCR_EN; txhead = 0; }
void uart_sendbyte(int b) { static uint8_t buf; buf = b; uart_sendbytes(&buf, 1); }
int uart_getbyte(void) { return rxfifo[rxtail++ & (RX_BUFSIZE - 1)]; }
void uart_getbytes(void* dst, int n) { uint8_t* dst8 = dst; while (n-- > 0) { *dst8++ = uart_getbyte(); } }
int uart_rxcount(void) { return (0 - rxstream->CNDTR - rxtail) & (RX_BUFSIZE - 1); }
int uart_peek(int i) { return rxfifo[(rxtail + i) & (RX_BUFSIZE - 1)]; }
void uart_flush(int n) { rxtail += n; }
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้