STM32F10x usart数据收发
来源:互联网 发布:java 构造函数返回值 编辑:程序博客网 时间:2024/05/17 01:40
STM32F10x uart的数据发送接收就三种基本方式,轮询、中断和DMA
1. 轮询(polling)方式
以下是轮询的uart初始化以及发送接收的例子,发送和接收都用轮询的方式。
uint8_t TxBuffer[] = "Buffer Send from USARTy to USARTz using Flags";uint8_t RxBuffer[TxBufferSize];int main(void){ /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f10x_xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f10x.c file */ /* System Clocks Configuration */ RCC_Configuration(); /* Configure the GPIO ports */ GPIO_Configuration();/* USARTy and USARTz configuration ------------------------------------------------------*/ /* USARTy and USARTz configured as follow: - BaudRate = 230400 baud - Word Length = 8 Bits - One Stop Bit - Even parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled */ USART_InitStructure.USART_BaudRate = 230400; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_Even; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* Configure USARTy */ USART_Init(USARTy, &USART_InitStructure); /* Configure USARTz */ USART_Init(USARTz, &USART_InitStructure); /* Enable the USARTy */ USART_Cmd(USARTy, ENABLE); /* Enable the USARTz */ USART_Cmd(USARTz, ENABLE); while(TxCounter < TxBufferSize) { /* Send one byte from USARTy to USARTz */ USART_SendData(USARTy, TxBuffer[TxCounter++]); /* void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) { assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); USARTx->DR = (Data & (uint16_t)0x01FF); //往DR写发送的数据 } */ /* Loop until USARTy DR register is empty */ while(USART_GetFlagStatus(USARTy, USART_FLAG_TXE) == RESET) { } //到这里表示数据发送完毕(USART_FLAG_TXE可以参考STM32F10x usart寄存器描述) /* Loop until the USARTz Receive Data Register is not empty */ while(USART_GetFlagStatus(USARTz, USART_FLAG_RXNE) == RESET) { } //到这里表示数据接收完毕(USART_FLAG_RXNE可以参考STM32F10x usart寄存器描述) /* Store the received byte in RxBuffer */ RxBuffer[RxCounter++] = (USART_ReceiveData(USARTz) & 0x7F); } //后面只是看发送接收数据是否一致,这与测试条件有关,不再赘述。 /* Check the received data with the send ones */ TransferStatus = Buffercmp(TxBuffer, RxBuffer, TxBufferSize); /* TransferStatus = PASSED, if the data transmitted from USARTy and received by USARTz are the same */ /* TransferStatus = FAILED, if the data transmitted from USARTy and received by USARTz are different */ while (1) { }}
2. 中断方式读写
STM32F10x USART有很多类型的中断,每个中断类型都有一个使能标志位。
中断设定以及使用ringbuffer输入输出的流程如下
(1) 中断的初始化
NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the USARTy Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USARTy_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable USARTy Receive and Transmit interrupts */ USART_ITConfig(USARTy, USART_IT_RXNE, ENABLE); USART_ITConfig(USARTy, USART_IT_TXE, ENABLE);
一般一个USART端口,输入输出都要设置一个中断位来触发输入输出中断,一般的输入输出只需要设置如下两个中断即可。
USART_IT_RXNE:Receive Data register not empty interrupt
USART_IT_TXE: Transmit Data Register empty interrupt
还有其他的中断位解释如下:
USART_IT_CTS: CTS change interrupt
USART_IT_LBD: LIN Break detection interrupt
USART_IT_TC: Transmission complete interrupt
USART_IT_IDLE: Idle line detection interrupt
USART_IT_PE: Parity Error interrupt
USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
设置完USART_IT_RXNE和USART_IT_TXE中断之后,读写都会触发中断。
这里我们一般不用USART_IT_TC中断,因为一般来说使用发送数据寄存器空中断(USART_IT_TXE)
发送的效率会高一些。
下面用一个使用ringbuffer,且使用中断方式的例子来熟悉一下中断读写。
(参考http://blog.csdn.net/liyuanbhu/article/details/8886407)
中断处理函数的框架如下,如果检测到错误就清除错误,收到数了就处理。发完当前数据了就发下一个。
void USART1_IRQHandler(void) { unsigned int data; if(USART1->SR & 0x0F) { // See if we have some kind of error, Clear interrupt data = USART1->DR; } else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag { data = USART1->DR; // 对收到的数据进行处理,或者干些其他的事 } else if(USART1->SR & USART_FLAG_TXE) { { // 可以发送数据了,如果没有数据需要发送,就在这里关闭发送中断 USART1->DR = something; // Yes, Send character } } }
下面给一个利用环形缓冲区的串口驱动程序。
#ifndef _COM_BUFFERED_H_ #define _COM_BUFFERED_H_ #define COM1 0 #define COM2 1 #define COM_RX_BUF_SIZE 64 /* Number of characters in Rx ring buffer */ #define COM_TX_BUF_SIZE 64 /* Number of characters in Tx ring buffer */ #define COM_NO_ERR 0 /* Function call was successful */ #define COM_BAD_CH 1 /* Invalid communications port channel */ #define COM_RX_EMPTY 2 /* Rx buffer is empty, no character available */ #define COM_TX_FULL 3 /* Tx buffer is full, could not deposit character */ #define COM_TX_EMPTY 4 /* If the Tx buffer is empty. */ /************************************************************ * function : COMGetCharB * parameter: char port, port can be COM1 / COM2 * parameter: char* err is a pointer to where an error code will be placed: * *err is set to COM_NO_ERR if a character is available * *err is set to COM_RX_EMPTY if the Rx buffer is empty * *err is set to COM_BAD_CH if you have specified an invalid channel * return : char * usage : This function is called by your application to obtain a character from the communications * channel. * changelog: *************************************************************/ unsigned char COMGetCharB (unsigned char ch, unsigned char *err); /************************************************************ * function : COMPutCharB * parameter: char port, port can be COM1 / COM2 * return : COMM_NO_ERR if the function was successful (the buffer was not full) * COMM_TX_FULL if the buffer was full * COMM_BAD_CH if you have specified an incorrect channel * usage : This function is called by your application to send a character on the communications * channel. The character to send is first inserted into the Tx buffer and will be sent by * the Tx ISR. If this is the first character placed into the buffer, the Tx ISR will be * enabled. If the Tx buffer is full, the character will not be sent (i.e. it will be lost) * changelog: *************************************************************/ unsigned char COMPutCharB (unsigned char port, unsigned char c); /************************************************************ * function : COMBufferInit * parameter: * return : * usage : This function is called by your application to initialize the communications module. You * must call this function before calling any other functions. * changelog: *************************************************************/ void COMBufferInit (void); /************************************************************ * function : COMBufferIsEmpty * parameter: char port, port can be COM1 / COM2 * return : char * usage : This function is called by your application to see * if any character is available from the communications channel. * If at least one character is available, the function returns * FALSE(0) otherwise, the function returns TRUE(1). * changelog: *************************************************************/ unsigned char COMBufferIsEmpty (unsigned char port); /************************************************************ * function : COMBufferIsFull * parameter: char port, port can be COM1 / COM2 * return : char * usage : This function is called by your application to see if any more characters can be placed * in the Tx buffer. In other words, this function check to see if the Tx buffer is full. * If the buffer is full, the function returns TRUE otherwise, the function returns FALSE. * changelog: *************************************************************/ unsigned char COMBufferIsFull (unsigned char port); #endif
/* * file: com_buffered.c * author: Li Yuan * platform: STM32F107 * date: 2013-5-5 * version: 0.0.1 * description: UART Ring Buffer **/ #include "stm32f10x_usart.h" #include "com_buffered.h" #define OS_ENTER_CRITICAL() __set_PRIMASK(1) #define OS_EXIT_CRITICAL() __set_PRIMASK(0) /** * Enables Transmiter interrupt. **/ static void COMEnableTxInt(unsigned char port) { static USART_TypeDef* map[2] = {USART1, USART2}; USART_ITConfig(map[port], USART_IT_TXE, ENABLE); } /* ********************************************************************************************************* * DATA TYPES ********************************************************************************************************* */ typedef struct { short RingBufRxCtr; /* Number of characters in the Rx ring buffer */ unsigned char *RingBufRxInPtr; /* Pointer to where next character will be inserted */ unsigned char *RingBufRxOutPtr; /* Pointer from where next character will be extracted */ unsigned char RingBufRx[COM_RX_BUF_SIZE]; /* Ring buffer character storage (Rx) */ short RingBufTxCtr; /* Number of characters in the Tx ring buffer */ unsigned char *RingBufTxInPtr; /* Pointer to where next character will be inserted */ unsigned char *RingBufTxOutPtr; /* Pointer from where next character will be extracted */ unsigned char RingBufTx[COM_TX_BUF_SIZE]; /* Ring buffer character storage (Tx) */ } COM_RING_BUF; /* ********************************************************************************************************* * GLOBAL VARIABLES ********************************************************************************************************* */ COM_RING_BUF COM1Buf; COM_RING_BUF COM2Buf; /************************************************************ * function : COMGetCharB * parameter: char port, port can be COM1 / COM2 * parameter: char* err is a pointer to where an error code will be placed: * *err is set to COM_NO_ERR if a character is available * *err is set to COM_RX_EMPTY if the Rx buffer is empty * *err is set to COM_BAD_CH if you have specified an invalid channel * return : char * usage : This function is called by your application to obtain a character from the communications * channel. * changelog: *************************************************************/ unsigned char COMGetCharB (unsigned char port, unsigned char *err) { // unsigned char cpu_sr; unsigned char c; COM_RING_BUF *pbuf; switch (port) { /* Obtain pointer to communications channel */ case COM1: pbuf = &COM1Buf; break; case COM2: pbuf = &COM2Buf; break; default: *err = COM_BAD_CH; return (0); } OS_ENTER_CRITICAL(); if (pbuf->RingBufRxCtr > 0) /* See if buffer is empty */ { pbuf->RingBufRxCtr--; /* No, decrement character count */ c = *pbuf->RingBufRxOutPtr++; /* Get character from buffer */ if (pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE]) { pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0]; /* Wrap OUT pointer */ } OS_EXIT_CRITICAL(); *err = COM_NO_ERR; return (c); } else { OS_EXIT_CRITICAL(); *err = COM_RX_EMPTY; c = 0; /* Buffer is empty, return 0 */ return (c); } } /************************************************************ * function : COMPutCharB * parameter: char port, port can be COM1 / COM2 * return : COMM_NO_ERR if the function was successful (the buffer was not full) * COMM_TX_FULL if the buffer was full * COMM_BAD_CH if you have specified an incorrect channel * usage : This function is called by your application to send a character on the communications * channel. The character to send is first inserted into the Tx buffer and will be sent by * the Tx ISR. If this is the first character placed into the buffer, the Tx ISR will be * enabled. If the Tx buffer is full, the character will not be sent (i.e. it will be lost) * changelog: * 1.first implimented by liyuan 2010.11.5 *************************************************************/ unsigned char COMPutCharB (unsigned char port, unsigned char c) { // unsigned char cpu_sr; COM_RING_BUF *pbuf; switch (port) { /* Obtain pointer to communications channel */ case COM1: pbuf = &COM1Buf; break; case COM2: pbuf = &COM2Buf; break; default: return (COM_BAD_CH); } OS_ENTER_CRITICAL(); if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) { /* See if buffer is full */ pbuf->RingBufTxCtr++; /* No, increment character count */ *pbuf->RingBufTxInPtr++ = c; /* Put character into buffer */ if (pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE]) { /* Wrap IN pointer */ pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0]; } if (pbuf->RingBufTxCtr == 1) { /* See if this is the first character */ COMEnableTxInt(port); /* Yes, Enable Tx interrupts */ OS_EXIT_CRITICAL(); } else { OS_EXIT_CRITICAL(); } return (COM_NO_ERR); } else { OS_EXIT_CRITICAL(); return (COM_TX_FULL); } } /************************************************************ * function : COMBufferInit * parameter: * return : * usage : This function is called by your application to initialize the communications module. You * must call this function before calling any other functions. * changelog: *************************************************************/ void COMBufferInit (void) { COM_RING_BUF *pbuf; pbuf = &COM1Buf; /* Initialize the ring buffer for COM0 */ pbuf->RingBufRxCtr = 0; pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0]; pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0]; pbuf->RingBufTxCtr = 0; pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0]; pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0]; pbuf = &COM2Buf; /* Initialize the ring buffer for COM1 */ pbuf->RingBufRxCtr = 0; pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0]; pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0]; pbuf->RingBufTxCtr = 0; pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0]; pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0]; } /************************************************************ * function : COMBufferIsEmpty * parameter: char port, port can be COM1 / COM2 * return : char * usage : This function is called by your application to see * if any character is available from the communications channel. * If at least one character is available, the function returns * FALSE(0) otherwise, the function returns TRUE(1). * changelog: *************************************************************/ unsigned char COMBufferIsEmpty (unsigned char port) { // unsigned char cpu_sr; unsigned char empty; COM_RING_BUF *pbuf; switch (port) { /* Obtain pointer to communications channel */ case COM1: pbuf = &COM1Buf; break; case COM2: pbuf = &COM2Buf; break; default: return (1); } OS_ENTER_CRITICAL(); if (pbuf->RingBufRxCtr > 0) { /* See if buffer is empty */ empty = 0; /* Buffer is NOT empty */ } else { empty = 1; /* Buffer is empty */ } OS_EXIT_CRITICAL(); return (empty); } /************************************************************ * function : COMBufferIsFull * parameter: char port, port can be COM1 / COM2 * return : char * usage : This function is called by your application to see if any more characters can be placed * in the Tx buffer. In other words, this function check to see if the Tx buffer is full. * If the buffer is full, the function returns TRUE otherwise, the function returns FALSE. * changelog: *************************************************************/ unsigned char COMBufferIsFull (unsigned char port) { // unsigned char cpu_sr; char full; COM_RING_BUF *pbuf; switch (port) { /* Obtain pointer to communications channel */ case COM1: pbuf = &COM1Buf; break; case COM2: pbuf = &COM2Buf; break; default: return (1); } OS_ENTER_CRITICAL(); if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) { /* See if buffer is full */ full = 0; /* Buffer is NOT full */ } else { full = 1; /* Buffer is full */ } OS_EXIT_CRITICAL(); return (full); } // This function is called by the Rx ISR to insert a character into the receive ring buffer. static void COMPutRxChar (unsigned char port, unsigned char c) { COM_RING_BUF *pbuf; switch (port) { /* Obtain pointer to communications channel */ case COM1: pbuf = &COM1Buf; break; case COM2: pbuf = &COM2Buf; break; default: return; } if (pbuf->RingBufRxCtr < COM_RX_BUF_SIZE) { /* See if buffer is full */ pbuf->RingBufRxCtr++; /* No, increment character count */ *pbuf->RingBufRxInPtr++ = c; /* Put character into buffer */ if (pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE]) { /* Wrap IN pointer */ pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0]; } } } // This function is called by the Tx ISR to extract the next character from the Tx buffer. // The function returns FALSE if the buffer is empty after the character is extracted from // the buffer. This is done to signal the Tx ISR to disable interrupts because this is the // last character to send. static unsigned char COMGetTxChar (unsigned char port, unsigned char *err) { unsigned char c; COM_RING_BUF *pbuf; switch (port) { /* Obtain pointer to communications channel */ case COM1: pbuf = &COM1Buf; break; case COM2: pbuf = &COM2Buf; break; default: *err = COM_BAD_CH; return (0); } if (pbuf->RingBufTxCtr > 0) { /* See if buffer is empty */ pbuf->RingBufTxCtr--; /* No, decrement character count */ c = *pbuf->RingBufTxOutPtr++; /* Get character from buffer */ if (pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE]) { pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0]; /* Wrap OUT pointer */ } *err = COM_NO_ERR; return (c); /* Characters are still available */ } else { *err = COM_TX_EMPTY; return (0); /* Buffer is empty */ } } void USART1_IRQHandler(void) { unsigned int data; unsigned char err; if(USART1->SR & 0x0F) { // See if we have some kind of error // Clear interrupt (do nothing about it!) data = USART1->DR; } else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag { data = USART1->DR; COMPutRxChar(COM1, data); // Insert received character into buffer } else if(USART1->SR & USART_FLAG_TXE) { data = COMGetTxChar(COM1, &err); // Get next character to send. if (err == COM_TX_EMPTY) { // Do we have anymore characters to send ? // No, Disable Tx interrupts //USART_ITConfig(USART1, USART_IT_TXE| USART_IT_TC, ENABLE); USART1->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC; } else { USART1->DR = data; // Yes, Send character } } } void USART2_IRQHandler(void) { unsigned int data; unsigned char err; if(USART2->SR & 0x0F) { // See if we have some kind of error // Clear interrupt (do nothing about it!) data = USART2->DR; } else if(USART2->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag { data = USART2->DR; COMPutRxChar(COM2, data); // Insert received character into buffer } else if(USART2->SR & USART_FLAG_TXE) { data = COMGetTxChar(COM2, &err); // Get next character to send. if (err == COM_TX_EMPTY) { // Do we have anymore characters to send ? // No, Disable Tx interrupts //USART_ITConfig(USART2, USART_IT_TXE| USART_IT_TC, ENABLE); USART2->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC; } else { USART2->DR = data; // Yes, Send character } } }
下面给个例子主程序,来演示如何使用上面的串口驱动代码。
#include "misc.h" #include "stm32f10x.h" #include "com_buffered.h" void UART_PutStrB (unsigned char port, uint8_t *str) { while (0 != *str) { COMPutCharB(port, *str); str++; } } void USART1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); /* Configure USART Tx as alternate function push-pull */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART Rx as input floating */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure ); USART_Cmd(USART1, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void USART2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); /* Configure USART Tx as alternate function push-pull */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); /* Configure USART Rx as input floating */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure ); USART_Cmd(USART2, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } int main(void) { unsigned char c; unsigned char err; USART1_Init(); USART2_Init(); COMBufferInit(); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); UART_PutStrB(COM1, "Hello World!\n"); for(;;) { c = COMGetCharB(COM1, &err); if(err == COM_NO_ERR) { COMPutCharB(COM1, c); } } }
3. DMA方式
http://blog.csdn.net/hongzg1982/article/details/47280667
- STM32F10x usart数据收发
- STM32F10x usart数据收发
- STM32F10x DMA介绍以及 dma usart数据收发
- STM32F10x DMA介绍以及 dma usart数据收发
- STM32F103 USART DMA收发不定长数据
- STM32F0xx_DMA收发USART数据配置详细过程
- STM32F407ZET6 USART DMA方式收发数据
- STM32F10X USART发送详解,测试无误
- STM32F10X USART 中断接受+发送,测试无误
- STM32F10x 学习笔记5(USART实现串口通讯 1)
- STM32F10x 学习笔记6(USART实现串口通讯 2)
- STM32F10x 学习笔记7(USART实现串口通讯 3)
- STM32F10x 学习笔记之USART实现串口通讯
- STM32F10x 学习笔记之USART实现串口通讯 DMA 方式
- STM32F10x USART串口映射功能实现串口通讯 485初始化
- ATMEL ATSAMD20G15的USART端口收发
- [stm32] USART USART1收发功能工程
- [stm32] USART USART1收发功能工程
- STM32F10x uart连接端口以及功能描述
- 2017 向前辈致敬 重新开始Android 先说点闲话
- mysql的一些问题
- abc免费建站
- CSU-1008
- STM32F10x usart数据收发
- 学生成绩的处理
- 三十分钟理解计算图上的微积分:Backpropagation,反向微分
- 网易互娱2017在线笔试——题目一:电子数字
- STM32F10x DMA介绍以及 dma usart数据收发
- PAT-1001. 害死人不偿命的(3n+1)猜想
- xshell无法连接linux虚拟机
- openstack实现对数据的通用校验源码分析:validation(以nova为例)
- 使用虚拟机安装Linux系统时的一些问题