新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STM32F10x 學(xué)習(xí)筆記5(USART實現(xiàn)串口通訊 1)

STM32F10x 學(xué)習(xí)筆記5(USART實現(xiàn)串口通訊 1)

作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
STM32F10x系列單片機(jī)中都包含了USART模塊,所謂USART,就是通用同步異步收發(fā)器。通用同步異步收發(fā)器(USART)提供了一種靈活的方法與使用工業(yè)標(biāo)準(zhǔn)NRZ異步串行數(shù)據(jù)格式的外部設(shè)備之間進(jìn)行全雙工數(shù)據(jù)交換。它支持同步單向通信和半雙工單線通信,也支持LIN(局部互連網(wǎng)),智能卡協(xié)議和IrDA(紅外數(shù)據(jù)組織)SIRENDEC規(guī)范,以及調(diào)制解調(diào)器(CTS/RTS)操作。它還允許多處理器通信。

本文引用地址:http://m.butianyuan.cn/article/201611/318840.htm

從前面的介紹可知USART模塊功能非常的強(qiáng)大。這里我只簡單講講如何用USART模塊來實現(xiàn)標(biāo)準(zhǔn)EIA-232串口通訊

用過單片機(jī)的人肯定都接觸過串口,設(shè)置串口無非就是設(shè)置波特率、數(shù)據(jù)位、停止位、奇偶校驗位。發(fā)送接收也就三種基本方式,輪詢、中斷和DMA。STM32F10x的USART模塊也不過如此。所以我重點講講我在調(diào)試代碼時犯得各種錯誤,那些很容易得到的代碼就不詳細(xì)的講解了。

首先說說我的硬件環(huán)境。還是那塊神舟4號開發(fā)板,用的是串口2,對應(yīng)的是USART2。默認(rèn)情況下USART2是連接到IO端口A的,但是我這里需要將USART的管腿重定向到IO端口D上。具體的管腿的關(guān)系參見下表。這個表是從STM32參考手冊上拷下來的。

初始化USART的代碼很簡單。USART2連接到APB1總線上了,先要打開USART2的時鐘,然后設(shè)置波特率一類的參數(shù)。

  1. USART_InitTypeDefUSART_InitStructure;
  2. RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
  3. USART_InitStructure.USART_BaudRate=9600;
  4. USART_InitStructure.USART_WordLength=USART_WordLength_8b;
  5. USART_InitStructure.USART_StopBits=USART_StopBits_1;
  6. USART_InitStructure.USART_Parity=USART_Parity_No;
  7. USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
  8. USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
  9. USART_Init(USART2,&USART_InitStructure);

這樣設(shè)置了還不能使用。因為我們將USART2重定向了。重定向操作需要寫復(fù)用重映射和調(diào)試I/O配置寄存器(AFIO_MAPR)。GPIO_PinRemapConfig()可以完成這項任務(wù)。

  1. GPIO_PinRemapConfig(GPIO_Remap_USART2,ENABLE);

光這樣操作還不夠。STM32參考手冊上有這么一段話:

對寄存器AFIO_EVCR,AFIO_MAPR和AFIO_EXTICRX進(jìn)行讀寫操作前,應(yīng)當(dāng)首先打開AFIO的時鐘。參考第6.3.7節(jié)APB2外設(shè)時鐘使能寄存器(RCC_APB2ENR)。

所以需要先打開AFIO的時鐘。因此,USART2的重定向需要兩步操作:

[cpp]view plaincopy
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
  2. GPIO_PinRemapConfig(GPIO_Remap_USART2,ENABLE);

我原以為這樣就能工作了,可是結(jié)果還是什么都沒有輸出。沒辦法只能繼續(xù)研究。在讀GPIO的相關(guān)章節(jié)時看到下圖讓我恍然大悟。

USART2的輸入輸出都是借用PD口管腿,PD口的時鐘卻還沒給。用到的幾個IO端口也沒有設(shè)置相應(yīng)的輸入輸出狀態(tài)。在讀到8.1.9復(fù)用功能配置這一小節(jié)時發(fā)現(xiàn)了如下的表格。

按照上面給出的配置,寫好程序:

  1. GPIO_InitTypeDefGPIO_InitStructure;
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
  3. /*ConfigureUSARTTxasalternatefunctionpush-pull*/
  4. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
  5. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
  6. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  7. GPIO_Init(GPIOD,&GPIO_InitStructure);
  8. /*ConfigureUSARTRxasinputfloating*/
  9. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  10. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
  11. GPIO_Init(GPIOD,&GPIO_InitStructure);

再次測試,一切正常。

發(fā)送一個字符的函數(shù)可以這么寫:

  1. voidUART_PutChar(USART_TypeDef*USARTx,uint8_tData)
  2. {
  3. while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET){};
  4. USART_SendData(USARTx,Data);
  5. }
這個函數(shù)可以手工優(yōu)化一下,里面的兩個函數(shù)調(diào)用都可以去掉,甚至于這個函數(shù)可以用匯編來實現(xiàn)或者寫成inline 函數(shù)。不過這里只是個示例代碼,沒有考慮這些。

發(fā)送字符串的函數(shù)如下:

  1. voidUART_PutStr(USART_TypeDef*USARTx,uint8_t*str)
  2. {
  3. while(0!=*str)
  4. {
  5. UART_PutChar(USARTx,*str);
  6. str++;
  7. }
  8. }

上面串口初始化的代碼可以放到一個函數(shù)中:

  1. voidUSART2_init(void)
  2. {
  3. GPIO_InitTypeDefGPIO_InitStructure;
  4. USART_InitTypeDefUSART_InitStructure;
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_AFIO,ENABLE);
  6. /*ConfigureUSARTTxasalternatefunctionpush-pull*/
  7. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
  8. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
  9. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  10. GPIO_Init(GPIOD,&GPIO_InitStructure);
  11. /*ConfigureUSARTRxasinputfloating*/
  12. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  13. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
  14. GPIO_Init(GPIOD,&GPIO_InitStructure);
  15. GPIO_PinRemapConfig(GPIO_Remap_USART2,ENABLE);
  16. RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
  17. USART_InitStructure.USART_BaudRate=9600;
  18. USART_InitStructure.USART_WordLength=USART_WordLength_8b;
  19. USART_InitStructure.USART_StopBits=USART_StopBits_1;
  20. USART_InitStructure.USART_Parity=USART_Parity_No;
  21. USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
  22. USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
  23. USART_Init(USART2,&USART_InitStructure);
  24. USART_Cmd(USART2,ENABLE);
  25. }

今天先寫這么多。接收字符的函數(shù)與發(fā)送字符的函數(shù)差不多,但是這種輪詢方式效率很低,不建議使用。下次寫一篇介紹如何用中斷方式發(fā)送接收串口數(shù)據(jù),中斷方式的效率會高很多。如果有時間再寫一篇DMA方式發(fā)送接收數(shù)據(jù)的文章。




關(guān)鍵詞: STM32F10xUSART串口通

評論


技術(shù)專區(qū)

關(guān)閉