串口通訊(下)——簡單的USART數據收發實驗
簡單做個USART的串口數據收發實驗。實驗在stm32f103上完成。
我們選擇CH340G晶元來完成,其可以實現USB轉USART。
查閱開發板原理圖可得,CH340G晶元TXD、RXD默認與USART1的TX、RX連接,即PA9、PA10引腳。如圖11-1。
圖11-1
當然了,如果你想用其他串口,如USART2的收發引腳,直接用杜邦線連接到相應引腳即可。
實驗中會用到USART接收中斷,當USART收到數據即執行中斷函數。所以我們需要配置NVIC。
static void NVIC_Configuration(void)n{n NVIC_InitTypeDef NVIC_InitStructure;ntn NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);nn NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;n NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;n NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;n NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;ntn NVIC_Init(&NVIC_InitStructure);n}n
這裡如何配置不再贅述,專欄里之前的文章已經有了相關介紹,有不明白的地方可移步閱讀。
接下來進行USART初始化的配置。GPIO_InitTypeDef和NVIC_InitTypeDef兩個結構體分別定義對應的結構體對象。然後開啟GPIO和USART時鐘。接下來配置USART的TX、RX引腳和串口的參數。我們配置其波特率為115200,8個數據位,1個停止位,無校驗,無硬體流控制,數據收發一起。
void USART_Config(void)n{n GPIO_InitTypeDef GPIO_InitStructure;n USART_InitTypeDef USART_InitStructure;ntn RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);ntn /* USART_TX GPIO配置 */n GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;n GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;n GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;n GPIO_Init(GPIOA, &GPIO_InitStructure);ntn /* USART_RX GPIO配置 */n GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;n GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;n GPIO_Init(GPIOA, &GPIO_InitStructure);ntn /* 串口參數配置 */n USART_InitStructure.USART_BaudRate = 115200;n USART_InitStructure.USART_WordLength = USART_WordLength_8b;n USART_InitStructure.USART_StopBits = USART_StopBits_1;n USART_InitStructure.USART_Parity = USART_Parity_No;n USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;n USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;n USART_Init(USART1, &USART_InitStructure);ntn NVIC_Configuration();ntn USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能USART1接收中斷ntn USART_Cmd(USART1, ENABLE);n}n
相關的配置已經完成,接下來開始發送數據。之前的文章說到過,發送時由TDR寄存器逐位將數據轉移到發送移位寄存器,然後由移位寄存器一位一位發送。所以如果需要發送字元串數據,則可按此原理進行逐位發送。
/* 發送單個字元 */nvoid Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data)n{n // 操作USART_DR寄存器發送單個數據n USART_SendData(pUSARTx, data);n // 等待發送寄存器TDR為空,為空時則置1n while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);n}nn/* 發送字元串 */nvoid Usart_SendStr(USART_TypeDef* pUSARTx, char *str)n{n uint8_t i = 0;n don {ntUsart_SendByte(pUSARTx, *(str+i));nti++;n }while(*(str+i) != 0);n // 等待發送完成n while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);n}n
當USART收到數據即會執行中斷函數,那麼我們在stm32f10x_it.c中編寫中斷服務函數USART1_IRQHandler()。
void USART1_IRQHandler(void)n{n uint8_t ucTemp;n if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)n {ntucTemp = USART_ReceiveData(USART1);nt// 調用庫函數,把接收到的數據發給串口調試助手n USART_SendData(USART1, ucTemp);n }n}n
最後就是在main函數里調用以上的函數進行數據收發了。
int main(void)n{n USART_Config();ntn Usart_SendStr(USART1, "This is a test data.n");ntn while(1);n}n
用USB轉串口線連接電腦和開發板,根據程序配置的參數調試串口助手的參數,把程序燒錄到板子,便可以開始收發數據了。如下圖的助手發送接收截圖。
圖11-2我們也可以利用收發的數據進而控制LED。有一點需要注意的是,如果想通過串口發送指令控制LED,那麼就會涉及到字元讀取,這時我們需要重定向c庫函數scanf到串口,即重新定義fgetc函數。如果需要列印串口信息,同樣也需要重定向printf函數。另外,需要在工程配置里需勾選「Use MicroLIB」。
/* 重定向c庫函數printf */nint fputc(int ch, FILE *f)n{n USART_SendData(USART1, (uint8_t)ch);n while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);ntn return ch;n}nn/* 重定向c庫函數scanf */nint fgetc(FILE *f)n{n while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);ntn return (int)USART_ReceiveData(USART1);n}n
附:串口通訊(上)——基礎概念、串口通訊(中)--USART
-----------------------------------------------------------------------
文章首發於知乎專欄 - stm32,轉載請私信,並註明原文出處。
推薦閱讀:
※串口通訊(上)——基礎概念
※python 3.5 中pyserial串口通信如何向串口發送十六進位通信指令?
※串口通訊(中)——USART
※為什麼同為3.5mm耳機介面,電腦能放聲音,手機卻不行?
TAG:串口通信 |