zoukankan      html  css  js  c++  java
  • STM8S——Universal asynchronous receiver transmitter (UART)

    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("
    ");
     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("
    
    please input something: 
    
    ");
    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
    
    ",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("
    
    Hello World !!
    
    ");
    39     }
    40     /*--------------------------------*/
    41     
    42   }
    43 
    44 }
    main
    • 说明:

    这里的打印和上面的回显虽然都是输出到终端,但是不同的是,回显是为了让用户知道自己是在实时输入内容的,而打印是把用户本次输入的字符串处理之后再一并返回给终端,方便用户检查自己输入的内容;

      如用户输入:ABCED'backspace''backspace'DE

      在终端中实时回显的就是字符串:ABCED'backspace''backspace'DE

      而打印的字符串是处理过后的字符串,为:ABCDE

    把uart_GetStr的第二个参数分别设置为TRUE和FALSE后观察终端输入操作的不同,这样就能明白他们的不同了。

  • 相关阅读:
    PAT 顶级 1010 Lehmer Code (35 分)
    PAT 顶级 1010 Lehmer Code (35 分)
    CCF CSP 201909-4 推荐系统
    CCF CSP 201909-4 推荐系统
    Codeforces 1251C Minimize The Integer
    Codeforces 1251C Minimize The Integer
    CCF CSP 201803-4 棋局评估
    CCF CSP 201803-4 棋局评估
    【DP_树形DP专题】题单总结
    【DP_树形DP专题】题单总结
  • 原文地址:https://www.cnblogs.com/Christal-R/p/7131591.html
Copyright © 2011-2022 走看看