1. 程式人生 > >Universal asynchronous receiver transmitter (UART)

Universal asynchronous receiver transmitter (UART)

是把 desc config 封裝 -1 返回 func support when

UART基本介紹:

通用異步收發器UART他的功能非常強大

我們只使用UART的全雙工異步通信功能,使用中斷接收數據。

UART_RX:串行數據輸入。

UART_TX:串行數據輸出。

硬件支持:

連接串口(RS232)實現在超級終端裏輸入輸出

技術分享

軟件支持:

超級終端,teraterm-4.75

技術分享

1、配置UART,我們使用UART2

(1)設置波特率為115200,設置數據字段長為8字,使用1個停止位,無基偶校驗,UART Clock disabled,打開發送和接收使能

  以上基本設置使用一個函數進行封裝設置:

技術分享

  函數內部實現:

    設置數據字段長為8字:UART2->CR1 |= 0x00;

    使用1個停止位: UART2->CR3 |= 0x00;

    使用基數位校驗:UART2->CR1 |= 0x00;

    UART Clock disabled、打開發送和接收使能等等

(2)打開接收中斷,當接收發生或者溢出發生時候,產生接收中斷

技術分享

(3)UART使能

 UART2->CR1 &= (uint8_t)(~0x02);

(4)全局中斷使能

 enableInterrupts();

總體UART配置函數實現如下代碼所示:

技術分享
 1 static void UART2_Config(void)
 2 {
 3   /* EVAL COM (UART) configuration -----------------------------------------
*/ 4 /* USART configured as follow: 5 - BaudRate = 115200 baud 6 - Word Length = 8 Bits 7 - One Stop Bit 8 - Odd parity 9 - Receive and transmit enabled 10 - UART Clock disabled 11 */ 12 UART2_Init((uint32_t)115200, UART2_WORDLENGTH_8D,UART2_STOPBITS_1, UART2_PARITY_NO,
13 UART2_SYNCMODE_CLOCK_DISABLE, UART2_MODE_TXRX_ENABLE); 14 15 /* Enable the UART Receive interrupt: this interrupt is generated when the UART 16 receive data register is not empty */ 17 UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE); 18 19 /* Enable the UART Transmit complete interrupt: this interrupt is generated 20 when the UART transmit Shift Register is empty */ 21 UART2_ITConfig(UART2_IT_TXE, ENABLE); 22 23 /* Enable UART */ 24 UART2_Cmd(ENABLE); 25 26 /* Enable general interrupts */ 27 enableInterrupts(); 28 }
UART2_Config

2、UART輸出功能

如果直接使用C語言的printf函數,只會在編譯器的Terminal-I/O中輸出,不會在我們想要的超級終端裏面輸出,所以需要對輸出函數做重定向;

實現每次想要輸出的時候,將信息打印到超級終端中,故重定向putchar (int c)函數,在函數內使用UART的傳送數據功能就可以了,即將要輸出的信息寫入UART的數據寄存器

 1 #define PUTCHAR_PROTOTYPE int putchar (int c)
 2 ...
 3 /**
 4   * @brief Retargets the C library printf function to the UART.
 5   * @param c Character to send
 6   * @retval char Character sent
 7   */
 8 PUTCHAR_PROTOTYPE
 9 {
10   /* Write a character to the UART2 */
11   UART2_SendData8(c);
12   /* Loop until the end of transmission */
13   while (UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
14 
15   return (c);
16 }

3、UART輸入功能

輸入功能實際上是字符串處理過程的實現,在超級終端中輸入內容實際上是在UART的數據寄存器裏寫內容,所我們只需要去數據寄存器裏面讀取並處理字符串即可;

  • 處理函數功能

首先我們得定義一個支持終端回顯的函數uart_GetStr,其中功能包括:

(1)當有我們在終端裏敲鍵盤的時候會立馬有正確的內容顯示;

(2)當按下特殊按鍵的時候會有正確的反應;比如backspace會刪除一個字符;return會表示輸入完畢進入發送;

(3)對於其他特殊案件處理不了應當屏蔽;比如不想實現delete功能,刪除剛剛讀入的delete字符,並不會回顯;

  • 函數實現:

uart_GetStr傳入的第一個參數是指向接收數據數組的指針,第二個參數表示是否允許回顯;

幾個有用變量:

  __IO uint8_t ReciveBuff = 0; //save the current char

  uint8_t RxBuffer[32] = {0}; //save the input string

  __IO uint8_t RxCounter = 0; //the length of valid string

所以,RxBuffer就是uart_GetStr函數的第一個參數,在uart_GetStr函數內部會對每一個字符進行處理,正確的字符才放入RxBuffer中;

技術分享
  1 //====================================================================================
  2 //Function Name    | dbg_GetStr
  3 //Description    | Get string via UART port.
  4 //Input        | *p_recv_buff : pointer to receive data buffer
  5 //        | b_echo_on : echo back on or off
  6 //Output    | detect terminal(0x0d character) :TRUE or FALSE
  7 //Remark    |
  8 //====================================================================================
  9 uint8_t uart_GetStr(uint8_t *p_recv_buff, bool b_echo_on)
 10 {
 11     uint8_t b_end = 0;
 12     int i;
 13     static uint8_t len = 0;
 14     static uint8_t pos = 0;
 15     static uint8_t esc_seq = 0;
 16     uint8_t c;
 17 
 18     // Get a character.
 19     if((c = ReciveBuff) == 0){
 20           return 0;
 21     }
 22     // echo back
 23     if(b_echo_on){
 24           printf("%c",c); //show the input
 25     }
 26 
 27     //Check
 28     switch(esc_seq){
 29         // Normal
 30         case 0:
 31           // Return(Terminate)
 32           if(c == 0x0d){
 33             p_recv_buff[len] = 0;
 34             len =  pos = 0;    // clear
 35             if(b_echo_on){
 36               printf("\n");
 37             }
 38             b_end = 1;
 39           }
 40           // Back Space
 41           else if(c == 0x08){
 42             if(len){
 43               if(b_echo_on){
 44                 printf(" ");
 45                 printf("%c",0x08);      // BS
 46               }
 47               len--;    // update length info.
 48               pos--;    // update pos info
 49             }
 50           }
 51           // ESC
 52           else if(c == 0x1b){
 53             esc_seq = 1;
 54           }
 55           // DEL
 56           else if(c == 0x7f){
 57             if(len){
 58               DeleteChar(pos, len, &p_recv_buff[0]);
 59               len --;   // update length info
 60               if(b_echo_on){
 61                 printf("%s",&p_recv_buff[pos]);
 62                 printf(" ");
 63                 printf("%c",0x08);      // BS
 64         // move cursor to character end.
 65         for(i = 0; i < len - pos; i++){
 66                   printf("%c",0x1b);    // ESC
 67                   printf("%c",[);
 68                   printf("%c",D);
 69                 }
 70               }
 71             }
 72           }
 73           // Other
 74           else{
 75             p_recv_buff[pos] = c;
 76             len++;      // update length info
 77             pos++;      // update pos info
 78           }
 79           break;
 80           // ESC SEQ -> 1st
 81         case 1:
 82           if(c == [){
 83             esc_seq = 2;        // Next seq.
 84           }
 85           else{
 86             esc_seq = 0;        // not support(to normal)
 87           }
 88           break;
 89           //ESC SEQ -> 2nd
 90         case 2:
 91           if(c==D){
 92             if(pos){
 93               pos--;    // "<-" key
 94             }
 95           }
 96           else if(c==C){
 97             if(pos < len){
 98               pos++;    // "->" key
 99             }
100           }
101           esc_seq = 0;  // To normal
102           break;
103         }
104         
105         return (b_end);
106 }
uart_GetStr

uart_GetStr函數值為0或者為1,只有在終端中輸入回車時才會返回1,其他情況均返回0;

有了這一特點,我們在使用這個函數的時候,只需要獲取返回值,當返回0時,把處理過後的、用戶正確輸入的字符串打印出來看;

  • 運行流程

(1)當終端中有輸入的時候,即數據寄存器不為空,從而觸發接收中斷;

(2)在接收中斷中,我們每次從數據寄存器UART2->DR中讀取一個字節,賦值到ReciveBuff;

(3)然後調用uart_GetStr函數,對當前輸入字符進行處理;(即每一個輸入調用一次處理函數)

(4)將uart_GetStr函數的返回值賦值給RT;

技術分享
 1  INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21)
 2 {
 3   
 4   /* Read one byte from the receive data register and send it back */
 5   
 6   ReciveBuff = (UART2_ReceiveData8() & 0x7F); //get input char
 7   
 8   RT = uart_GetStr(RxBuffer, TRUE); //operate the char
 9   
10 }
interrupt

(5)在主函數裏死等,直到RT的值變為1(表示有return發生,即一次輸入完畢);

(6)當RT=1時,主函數輸出正確的輸入字符串RxBuffer(這裏可以實現更強大的功能,此處只是簡單實現驗證功能,可以對正確字符串做判斷後實現更強大的功能)

技術分享
 1 void main(void)
 2 {
 3   /* Clock configuration -----------------------------------------*/
 4   CLK_Config();  
 5  
 6   /* TIM4 configuration -----------------------------------------*/
 7   TIM4_Config();
 8   
 9   
10   /* UART2 configuration -----------------------------------------*/
11   UART2_Config(); 
12   
13   
14   while(1){
15     printf("\n\rplease input something: \n\r");
16     
17     while(1){ //wait until input something
18      
19       if(RT) // return occurred
20       {
21         RT = 0; //clear flag
22         
23         printf("your put is:");
24         printf("%s\n\r",RxBuffer); //verify the input
25         
26         /*-- operate the string --*/
27         /*------------------------*/
28         
29         //memset(RxBuffer,0,32); //clear the buffer
30         break; //operation finished
31       }
32       
33     }
34     
35     /*-- or operate the string here --*/
36     if(strcmp(RxBuffer, "Hello") == 0)
37     { //case sensitive
38       printf("\n\rHello World !!\n\r");
39     }
40     /*--------------------------------*/
41     
42   }
43 
44 }
main

  • 說明:

這裏的打印和上面的回顯雖然都是輸出到終端,但是不同的是,回顯是為了讓用戶知道自己是在實時輸入內容的,而打印是把用戶本次輸入的字符串處理之後再一並返回給終端,方便用戶檢查自己輸入的內容;

  如用戶輸入:ABCED‘backspace‘‘backspace‘DE

  在終端中實時回顯的就是字符串:ABCED‘backspace‘‘backspace‘DE

  而打印的字符串是處理過後的字符串,為:ABCDE

把uart_GetStr的第二個參數分別設置為TRUE和FALSE後觀察終端輸入操作的不同,這樣就能明白他們的不同了。

Universal asynchronous receiver transmitter (UART)