之前试过了DMA的ADC,这次用DMA结合串口的收发。
初始化一些需要用到的参数
#define USART_MAX_BUFFER_SIZE 512
typedef struct usartRT {
uint8_t status;
uint16_t rxBufferSize;
uint16_t txBufferSize;
uint8_t txBuffer[USART_MAX_BUFFER_SIZE];
uint8_t rxBuffer[USART_MAX_BUFFER_SIZE];
}usartPacket_s;
typedef struct serialHandle {
USART_Type* USARTx;
DMA_Channel_Type* rxChannel;
DMA_Channel_Type* txChannel;
usartPacket_s packet;
usartPacket_s DMApacket;
}SerialHandle_s;
SerialHandle_s serialHandle[serialCount] = {
[serial1] = {
.USARTx = USART1,
.rxChannel = DMA1_Channel5,
.txChannel = DMA1_Channel4,
.packet.rxBufferSize = 0,
.DMApacket.rxBufferSize = 0,
},
}
初始化DMA
void USART_DMA_INIT(DMA_Channel_Type* DMAchannelx, uint32_t periphAddr, uint32_t bufferAddr, uint16_t bufferSize, uint32_t Direction)
{
DMA_InitType DMA_InitStructure;
DMA_Reset(DMAchannelx);
DMA_DefaultInitParaConfig(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = periphAddr;
DMA_InitStructure.DMA_MemoryBaseAddr = bufferAddr;
DMA_InitStructure.DMA_Direction = Direction;
DMA_InitStructure.DMA_BufferSize = bufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
DMA_InitStructure.DMA_PeripheralDataWidth = DMA_PERIPHERALDATAWIDTH_BYTE;
DMA_InitStructure.DMA_MemoryDataWidth = DMA_MEMORYDATAWIDTH_BYTE;
DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
DMA_InitStructure.DMA_Priority = DMA_PRIORITY_LOW;
DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
DMA_Init(DMAchannelx, &DMA_InitStructure);
}
设置DMA参数
void USART_DMA_SETUP(SerialHandle_s* serialx)
{
USART_DMA_INIT(serialx->txChannel, (uint32_t) & (serialx->USARTx->DT), (uint32_t)(serialx->DMApacket.txBuffer), USART_MAX_BUFFER_SIZE, UART_TX);
USART_DMA_INIT(serialx->rxChannel, (uint32_t) & (serialx->USARTx->DT), (uint32_t)(serialx->DMApacket.rxBuffer), USART_MAX_BUFFER_SIZE, UART_RX);
DMA_ChannelEnable(serialx->rxChannel, ENABLE);
USART_DMACmd(serialx->USARTx, USART_DMAReq_Rx, ENABLE);
USART_DMACmd(serialx->USARTx, USART_DMAReq_Tx, ENABLE);
}
初始化串口
void USART_ClkCmd(USART_Type* USARTx, FunctionalState NewState)
{
if (USARTx == USART1)
{
RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_USART1, NewState);
}
}
void USART_NVIC_Cmd(USART_Type* USARTx, FunctionalState NewState)
{
if (USARTx == USART1)
{
NVIC_Config(USART1_IRQn, 4, 1, NewState);
}
}
void Usart_Setup(SerialHandle_s* serialx, uint32_t baudrate, uint16_t Wordlength, uint16_t Stopbits, uint16_t Parity, uint16_t Mode, uint16_t HardwareFlowControl)
{
USART_Reset(serialx->USARTx);
USART_ClkCmd(serialx->USARTx, ENABLE);
USART_NVIC_Cmd(serialx->USARTx, ENABLE);
USART_InitType USARTx_InitStructure;
USARTx_InitStructure.USART_BaudRate = baudrate;
USARTx_InitStructure.USART_WordLength = Wordlength;
USARTx_InitStructure.USART_StopBits = Stopbits;
USARTx_InitStructure.USART_Parity = Parity;
USARTx_InitStructure.USART_Mode = Mode;
USARTx_InitStructure.USART_HardwareFlowControl = HardwareFlowControl;
USART_Init(serialx->USARTx, &USARTx_InitStructure);
USART_DMA_SETUP(serialx);
USART_INTConfig(serialx->USARTx, USART_INT_IDLEF, ENABLE);
USART_INTConfig(serialx->USARTx, USART_INT_TRAC, ENABLE);
USART_Cmd(serialx->USARTx, ENABLE);
}
使用串口1发数据
char* myitoa(int num, char* str, int radix)
{
char index[] = "0123456789ABCDEF";
unsigned unum;
int i = 0, j, k;
if (radix == 10 && num < 0)
{
unum = (unsigned)-num;
str[i++] = '-';
}
else
unum = (unsigned)num;
do
{
str[i++] = index[unum % (unsigned)radix];
unum /= radix;
} while (unum);
str[i] = '\0';
if (str[0] == '-')
k = 1;
else
k = 0;
for (j = k; j <= (i - 1) / 2; j++)
{
char temp;
temp = str[j];
str[j] = str[i - 1 + k - j];
str[i - 1 + k - j] = temp;
}
return str;
}
void Serial_puts(SerialHandle_s* serialx, const char* b)
{
while (*b)
{
serialx->packet.txBuffer[serialx->packet.txBufferSize] = *b;
serialx->packet.txBufferSize++;
b++;
if (serialx->packet.txBufferSize == USART_MAX_BUFFER_SIZE)
Serial_flush(serialx);
}
}
void Serial_put(SerialHandle_s* serialx, const char* buffer, uint16_t lenght)
{
if (lenght + serialx->packet.txBufferSize > USART_MAX_BUFFER_SIZE)
{
uint16_t txSize = 0;
txSize = USART_MAX_BUFFER_SIZE - serialx->packet.txBufferSize;
memcpy(&(serialx->packet.txBuffer[serialx->packet.txBufferSize]), buffer, txSize);
serialx->packet.txBufferSize = USART_MAX_BUFFER_SIZE;
Serial_flush(serialx);
memcpy(&(serialx->packet.txBuffer[0]), &buffer[txSize], lenght - txSize);
serialx->packet.txBufferSize = lenght - txSize;
}
else
{
while (lenght)
{
serialx->packet.txBuffer[serialx->packet.txBufferSize] = *buffer;
serialx->packet.txBufferSize++;
buffer++;
lenght--;
}
}
}
void dmaChannelFlush(SerialHandle_s* serialx)
{
if (!serialx->packet.txBufferSize)
return;
uint16_t tryCount = 0;
while (serialx->DMApacket.status & txBusy)
{
delay_us(10);
if (tryCount++ > SystemCoreClock / 1000000)
return;
}
DMA_ChannelEnable(serialx->txChannel, DISABLE);
USART_DMACmd(serialx->USARTx, USART_DMAReq_Tx, DISABLE);
memcpy(serialx->DMApacket.txBuffer, serialx->packet.txBuffer, serialx->packet.txBufferSize);
serialx->DMApacket.txBufferSize = serialx->packet.txBufferSize;
serialx->packet.txBufferSize = 0;
DMA_SetCurrDataCounter(serialx->txChannel, serialx->DMApacket.txBufferSize);
USART_DMACmd(serialx->USARTx, USART_DMAReq_Tx, ENABLE);
DMA_ChannelEnable(serialx->txChannel, ENABLE);
serialx->DMApacket.status |= txBusy;
}
void Serial_flush(SerialHandle_s* serialx)
{
dmaChannelFlush(serialx);
}
void uartPrintfloat(const char* format, ...)
{
char str[30];
char c = 0;
char ch = 0;
bool catchFloat = 0;
union _floatHex
{
double _f;
uint8_t _u8;
int8_t _i8;
uint16_t _u16;
int16_t _i16;
uint32_t _u32;
int32_t _i32;
uint64_t _u64;
int64_t _i64;
uint8_t hex[8];
}ftmp;
va_list ap;
va_start(ap, format);
char *p = 0;
while ((c = *format))
{
switch (c)
{
case '%':
ch = *++format;
switch (ch)
{
case 'd':
{
if(catchFloat)
{
p = va_arg(ap, char[8]);
memcpy(&ftmp.hex[4],p,4);
}
else
{
p = va_arg(ap, char[8]);
memcpy(&ftmp.hex[0],p,8);
}
myitoa(ftmp._i64, str, 10);
Serial_puts(&serialHandle[serial1], str);
break;
}
case 'f':
if (!catchFloat)
{
catchFloat = 1;
p = va_arg(ap, char[8]);
memcpy(ftmp.hex,&p[4],4);
}
p = va_arg(ap, char[8]);
memcpy(&ftmp.hex[4],p,4);
int32_t n;
n = ftmp._f;
myitoa(n, str, 10);
Serial_puts(&serialHandle[serial1], str);
Serial_putc(&serialHandle[serial1], '.');
n = (ftmp._f - n) * 1000000;
if (n < 0)
n = (unsigned)-n;
myitoa(n, str, 10);
Serial_puts(&serialHandle[serial1], str);
memcpy(ftmp.hex,&p[4],4);
break;
case '%':
Serial_putc(&serialHandle[serial1], '%');
break;
default:
Serial_putc(&serialHandle[serial1], '%');
Serial_putc(&serialHandle[serial1], ch);
break;
}
break;
default:
Serial_putc(&serialHandle[serial1], c);
break;
}
format++;
}
va_end(ap);
Serial_flush(&serialHandle[serial1]);
}
void usartPrintf(const char* format, ...)
{
char str[30];
char c = 0;
char ch = 0;
bool catchFloat = 0;
va_list ap;
va_start(ap, format);
while ((c = *format))
{
switch (c)
{
case '%':
{
ch = *++format;
switch (ch)
{
case 'b':
{
uint32_t n = va_arg(ap, int);
myitoa(n, str, 2);
Serial_puts(&serialHandle[serial1], str);
break;
}
case 'c':
{
char c = va_arg(ap, int);
Serial_putc(&serialHandle[serial1], c);
break;
}
case 'd':
{
uint32_t n = va_arg(ap, int);
myitoa(n, str, 10);
Serial_puts(&serialHandle[serial1], str);
break;
}
case 'x':
{
uint32_t n = va_arg(ap, int);
myitoa(n, str, 16);
Serial_puts(&serialHandle[serial1], str);
break;
}
case 'f':
{
if (!catchFloat)
{
catchFloat = 1;
}
double f = va_arg(ap, double);
hexFloatTest(f);
int32_t n;
n = f;
myitoa(n, str, 10);
Serial_puts(&serialHandle[serial1], str);
Serial_putc(&serialHandle[serial1], '.');
n = (f - n) * 1000000;
if (n < 0)
n = (unsigned)-n;
myitoa(n, str, 10);
Serial_puts(&serialHandle[serial1], str);
break;
}
case 's':
{
char* p = va_arg(ap, char*);
Serial_puts(&serialHandle[serial1], p);
break;
}
case '%':
{
Serial_putc(&serialHandle[serial1], '%');
break;
}
default:
{
Serial_putc(&serialHandle[serial1], '%');
Serial_putc(&serialHandle[serial1], ch);
break;
}
}
}
break;
default:
Serial_putc(&serialHandle[serial1], c);
break;
}
format++;
}
va_end(ap);
Serial_flush(&serialHandle[serial1]);
}
使用串口1接收数据
char Serial_getc(SerialHandle_s* serialx)
{
return serialx->packet.rxBuffer[serialx->packet.rxBufferSize++];
}
char* Serial_gets(SerialHandle_s* serialx)
{
return (char*)(serialx->packet.rxBuffer);
}
char Serial_get(SerialHandle_s* serialx, uint16_t byteIndex)
{
if (byteIndex >= USART_MAX_BUFFER_SIZE)
return 0;
return serialx->packet.rxBuffer[byteIndex - 1];
}
uint16_t IsSerialRxHasData(SerialHandle_s* serialx)
{
if (serialx->DMApacket.status & rxDone)
{
return serialx->packet.rxBufferSize;
}
else
return 0;
}
void Serial_Pruge(SerialHandle_s* serialx)
{
serialx->DMApacket.status &= ~rxDone;
serialx->packet.rxBufferSize = 0;
memset(serialx->packet.rxBuffer, 0, USART_MAX_BUFFER_SIZE);
}
中断处理
void Serial_IRQHandler(SerialHandle_s* serialx)
{
uint16_t bufferCount = 0;
if (USART_GetITStatus(serialx->USARTx, USART_INT_IDLEF))
{
USART_ClearITPendingBit(serialx->USARTx, USART_INT_IDLEF);
(void)(serialx->USARTx->DT);
DMA_ChannelEnable(serialx->rxChannel, DISABLE);
serialx->DMApacket.status |= rxDone;
bufferCount = DMA_GetCurrDataCounter(serialx->rxChannel);
serialx->DMApacket.rxBufferSize = USART_MAX_BUFFER_SIZE - bufferCount;
if (serialx->packet.rxBufferSize >= USART_MAX_BUFFER_SIZE)
serialx->packet.rxBufferSize = 0;
memcpy(&serialx->packet.rxBuffer[serialx->packet.rxBufferSize], serialx->DMApacket.rxBuffer, serialx->DMApacket.rxBufferSize);
serialx->packet.rxBufferSize += serialx->DMApacket.rxBufferSize;
DMA_SetCurrDataCounter(serialx->rxChannel, USART_MAX_BUFFER_SIZE);
DMA_ChannelEnable(serialx->rxChannel, ENABLE);
USART_DMACmd(serialx->USARTx, USART_DMAReq_Rx, ENABLE);
}
if (USART_GetITStatus(serialx->USARTx, USART_INT_TRAC))
{
USART_ClearITPendingBit(serialx->USARTx, USART_INT_TRAC);
DMA_ChannelEnable(serialx->txChannel, DISABLE);
serialx->DMApacket.status |= txDone;
serialx->DMApacket.status &= (~txBusy);
serialx->DMApacket.txBufferSize = 0;
}
}
void USART1_IRQHandler(void)
{
Serial_IRQHandler(&serialHandle[serial]);
}