zoukankan      html  css  js  c++  java
  • TQQ2440第三节:串口

    做嵌入式的基本上都清楚,板子基本上跑起来了,第一个肯定要配置的是串口,便于我们后面调试信息的输出,和一些系统参数的输出,让我们有更直观看见程序的运行。

    —————————————————————————————————————————————

    硬件平台:TQ2440 (S3C2440A)

    开发环境:ADS1.2

    时      间:2010-12-12

    —————————————————————————————————————————————

    1:硬件电路:

      image image

                      底板电路                           核心板上的连接管脚

    由于TQ2440的板子上只引出了一个串口,也就是用的UART0作为COM1,所以我吗只需要配置相关的引脚为串口功能即可。

    接着参考2440的说明文档:

    image

    所以把GPH相关的GPH0-3都配置为第二功能UART功能。即可以上至完成了管脚的配置,接着对UART的功能进行配置。

    A:UART寄存器:

    image

    从2440的数据手册上我们可以知道他的寄存器的地址都是连接着的,所以我们直接用结构体来表示,因为他有3个串口,所以,我们这里就可以用3个不同的结构体指针来操作不同的寄存器。代码如下:

       1: #define IO_CON_BASE 0x56000000
       2: #define IO_DAT_BASE 0x56000004
       3:  
       4: #define UART0_BASE  0x50000000  // UART0 Base Address
       5: #define UART1_BASE  0x50004000  // UART1 Base Address
       6: #define UART2_BASE  0x50008000  // UART2 Base Address
       7:  
       8: #define REG8(x)  (*((volatile unsigned char  *)(x)))
       9: #define REG16(x) (*((volatile unsigned short *)(x)))
      10: #define REG32(x) (*((volatile unsigned long  *)(x)))
      11:  
      12: typedef volatile unsigned char  reg8;
      13: typedef volatile unsigned short reg16;
      14: typedef volatile unsigned long  reg32;
      15:                         
      16: /*
      17: GPIO_CFG_SET说明:   group--表示是那组IO(注意没有GPA)
      18:                     index--表示这组中的那个引脚   
      19:                     type --表示是配置为输入还是输出等其他功能
      20: */
      21: #define GPIO_CFG_SET(group,index,type) do{\
      22:                         (*(volatile unsigned int*)(IO_CON_BASE+group*0x10))&=~(0x3<<index<<1);\
      23:                         (*(volatile unsigned int*)(IO_CON_BASE+group*0x10))|=(type<<index<<1);\
      24:                         }while(0)
      25:                         
      26: /*
      27: GPIO_DAT_SET说明:   group--表示是那组IO(注意没有GPA)
      28:                     index--表示这组中的那个引脚   
      29:                     val  --表示对此引脚写入的数据
      30: */
      31: #define GPIO_DAT_SET(group,index,val) do{\
      32:                         (*(volatile unsigned int*)(IO_DAT_BASE+group*0x10))&=~(0x1<<index);\
      33:                         (*(volatile unsigned int*)(IO_DAT_BASE+group*0x10))|=(val<<index);\
      34:                         }while(0)
      35: /*
      36: 因为GPA的控制寄存器,每个引脚只只占用一位,所以为了能统一这里,就没有把
      37: GPA加进来,而后面的GPB-GPJ的控制寄存器每个引脚对应2位
      38: */                        
      39: enum{GPB=1,GPC,GPD,GPE,GPF,GPG,GPH,GPI,GPJ};
      40: /*
      41: 从GPB开始由于用两位表示此引脚的功能所以有四种可能
      42: 0代表INPUT,1代表OUTPUT,2代表第三功能,3代表第四功能
      43: */
      44: enum{INPUT=0,OUTPUT,THI_FUNC,FOR_FUNC};
      45: /*
      46: 定义高低电平
      47: */
      48: enum{LOW=0,HIG};
      49:  
      50: // UART Registers
      51: typedef struct {
      52:   reg32 ULCON;              // UART Line Control          由于控制数据格式,常用的为N-8-1模式 
      53:   reg32 UCON;               // UART Control                控制UART的工作状态,例如DMA,中断等
      54:   reg32 UFCON;              // UART FIFO Control        控制UART的FIFO,这里没有用到
      55:   reg32 UMCON;          // UART MODEM Control    在MODEM模式下的控制寄存器,这里没有用到
      56:   reg32 UTRSTAT;        // UART Tx/Rx Status        UART发送和接受状态寄存器
      57:   reg32 UERSTAT;        // UART Error Status            UART错误状态寄存器
      58:   reg32 UFSTAT;             // UART FIFO Status        UART---FIFO状态寄存器
      59:   reg32 UMSTAT;         // UART MODEM Status    UART---MODEM状态寄存器
      60:   reg8  UTXH;               // UART Tx Hold                UART发送数据寄存器 ##注意这里是一个char类型的
      61:   reg8  pad0[3];
      62:   reg8  URXH;               // UART RX Buffer            UART接受数据寄存器 ##注意这里是一个char类型的
      63:   reg8  pad1[3];
      64:   reg32 UBRDIV;             // UART Baud Rate Divisor UART的波特率产生器的分频率
      65: } regUART;
      66:  
      67: #define pUART0 ((regUART *)UART0_BASE)
      68: #define pUART1 ((regUART *)UART1_BASE)
      69: #define pUART2 ((regUART *)UART2_BASE)

     2:2440的UART的配置

         上面已经把相关的寄存器介绍的很清楚了,所以这里的配置就直接给出代码了,因为可以直接参考数据手册得到:

       1: void uart_init(void)
       2: {
       3:     //设置GPH[0..3]为uart0的输出引脚
       4:     GPIO_CFG_SET(GPH,0,THI_FUNC);
       5:     GPIO_CFG_SET(GPH,1,THI_FUNC);
       6:     GPIO_CFG_SET(GPH,2,THI_FUNC);
       7:     GPIO_CFG_SET(GPH,3,THI_FUNC);
       8:     
       9:     pUART0->ULCON=    0x03;   //N-8-1
      10:     pUART0->UCON=    0x245; //中断和查询模式
      11:     pUART0->UFCON=    0x0;    //No Use
      12:     pUART0->UMCON=    0x0;      //No Use
      13:     pUART0->UBRDIV=    26;      //当前板子的速度是FCLK:400M,HCLK=100M,PCLK=50M,UATR=115200
      14: }

       这样串口就能工作起来的了,自己在把链接串口工具配置成相同的波特率就能正常工作了。

    3: 相关代码的实现

     接下来就是串口发送和接受数据的一些功能函数的实现了,下面也只实现了一些简单的函数:

    输出部分:

       1: void u_printf(char *fmt,...)  //格式化输出
       2: {
       3:     va_list ap;
       4:     char str[100];
       5:     va_start(ap,fmt);
       6:     vsprintf(str,fmt,ap);
       7:     send_str(str);
       8:     va_end(ap);
       9: }
      10: void send_str(char *p_str)   //发送一个字符串
      11: {
      12:     while(*p_str!='\0')
      13:     {
      14:         if(*p_str=='\n')
      15:         {
      16:             send_char('\r');
      17:         }
      18:         
      19:         send_char(*p_str);
      20:         p_str++;
      21:     }        
      22: }
      23: void send_char(char cc)    //发送一个字符
      24: {
      25:     while(!(pUART0->UTRSTAT& 0x2));
      26:     pUART0->UTXH=cc;
      27: }

    输入部分:

       1: char get_char(void)             //接受一个字符
       2: {
       3:     char cc;
       4:     while(!(pUART0->UTRSTAT& 0x1));
       5:     cc=pUART0->URXH;
       6:     return cc;
       7: }
       8:  
       9: void get_str(char *str)    //接受一个字符串
      10: {
      11:     /*
      12:     str_bak是为了存储str地址的,是为了在没有输入的情况下
      13:     输入退格,造成程序的崩溃
      14:     */
      15:     char *str_bak=str,cc; 
      16:     do{
      17:         cc = get_char();
      18:          if(cc=='\b')
      19:         {
      20:             if( (int)str_bak < (int)str)
      21:             {
      22:                 //u_printf("\b \b");
      23:                 send_char('\b');
      24:                 send_char('\b');
      25:                 str--;
      26:             }
      27:         }
      28:         else 
      29:         {
      30:             *str++ = cc;
      31:             send_char(cc);
      32:         }
      33:     }
      34:     while(cc!='\r');
      35:     
      36:     *str = '\0';
      37:     send_char('\n');
      38: }

    4:彩色输出的实现

    在公司的调试东西有时候打印的东西太多了,是在没办法找,所以最后实现了这个彩色打印的方法,便于迅速找到自己想得到的打印消息,从而提高工作效率。其彩色打印的原理为:

    以下内容来自网上:

    +-----------------------------------------------------------------------------------------------+

    在 ANSI 兼容终端(例如 xterm、rxvt、konsole 等)里, 可以用彩色显示文本而不仅仅是黑白。
    下面的语句就输出高亮的黑色背景的绿色字。
    printf("\033[1;40;32m%s\033[0m", Hello,world!\n);
    \033 声明了转义序列的开始,然后是 [ 开始定义颜色。后面的 1 定义了高亮显示字符。然后是背景颜色,这里面是40,表示黑色背景。接着是前景颜色,这里面是32,表示绿色。我们用 \033[0m 关闭转义序列, \033[0m 是终端默认颜色。
    通过上面的介绍,就知道了如何输出彩色字符了。
    下面是对于彩色字符颜色的一些定义:
    前景   背景   颜色
    ---------------------------------------
    30   40   黑色
    31   41   紅色
    32   42   綠色
    33   43   黃色
    34   44   藍色
    35   45   紫紅色
    36   46   青藍色
    37   47   白色

    代码   意义
    -------------------------
    0   终端默认设置
    1   高亮显示
    4   使用下划线
    5   闪烁
    7   反白显示
    8   不可见

    通过串口收发或显示字符时,我们使用的通常是字符的ASCII码。对于非控制字符,也即键入命令时我们可能使用到的命令字符,在控制台中我们使用了ASCII码值从0x20~0x7e之间的字符。对于控制字符,在常用字符ASCII码对照表中我们可以找到Enter键、Backspace(退格)键以及ESC键的ASCII码,但是却没有上下左右方向键以及Home、End键对应的ASCII码,通过对键盘输入字符的串口收发测试发现,如果在测试时按下了方向键则串口在每次按键后会连续发送出3字节数据,前两字节所有方向键的数据相同,分别是0x1b,0x5b,第3字节对应不同的按键,上下右左方向键分别对应的值为:0x41、0x42、0x43、0x44,Home和End键对应的值为0x48和0x4b。故要检测键盘是否键入了方向键,需要向串口连续读取三字节的数据,同理,要控制光标向左、向右移动或Home、End也需要连续一次向串口发送3字节数据。

    +-----------------------------------------------------------------------------------------------+

    所以我们只需要通过串口发送相应的指令就OK了,我为了方便将其封装为宏定义的格式:

       1: //######################Add by Dreamxi 彩色打印信息##################start
       2: //使用格式
       3: //cpfcpf(ALLOW_PUT,RED,("+----------------This is Dreamxi Uart cpf test --------------+"));
       4: //              |    |    |-------------------------------------------------------------|
       5: //       是否允许打印  |                                           |
       6: //                   |                                           |
       7: //                 打印颜色                                              |
       8: //                                                            打印内容
       9: #define ALLOW_PUT 1
      10: /*
      11: 前景          背景              颜色
      12: ---------------------------------------
      13: 30                 40              黑色
      14: 31                 41              紅色
      15: 32                 42              綠色
      16: 33                 43              黃色
      17: 34                 44              藍色
      18: 35                 45              紫紅色
      19: 36                 46              青藍色
      20: 37                 47              白色    
      21: */
      22: /*        红         绿   蓝   白   黄   紫红  青蓝 */
      23: enum {RED=0,GRE,BLU,WHI,YEL,ZH,GB};
      24:  
      25: #define cpf(DEBUG_MSG,COR,...) do{\
      26:     if(DEBUG_MSG==1)\
      27:     {\
      28:         if(COR==RED)\
      29:             {\
      30:                 u_printf("\033[1;31;40m");\
      31:                 u_printf(__VA_ARGS__);\
      32:             }\
      33:         else if(COR==GRE)\
      34:             {\
      35:                 u_printf("\033[1;32;40m");\
      36:                 u_printf(__VA_ARGS__);\
      37:             }\
      38:         else if(COR==BLU)\
      39:             {\
      40:                 u_printf("\033[1;34;40m");\
      41:                 u_printf(__VA_ARGS__);\
      42:             }\
      43:         else if(COR==WHI)\
      44:             {\
      45:                 u_printf("\033[1;37;40m");\
      46:                 u_printf(__VA_ARGS__);\
      47:             }\
      48:         else if(COR==YEL)\
      49:             {\
      50:                 u_printf("\033[1;33;40m");\
      51:                 u_printf(__VA_ARGS__);\
      52:             }\
      53:         else if(COR==ZH)\
      54:             {\
      55:                 u_printf("\033[1;35;40m");\
      56:                 u_printf(__VA_ARGS__);\
      57:             }\
      58:         else if(COR==GB)\
      59:             {\
      60:                 u_printf("\033[1;36;40m");\
      61:                 u_printf(__VA_ARGS__);\
      62:             }\
      63:         u_printf("\033[0m\r\n");\
      64:     }\
      65: }while(0)
      66: //######################Add by Dreamxi 彩色打印信息##################end

    使用方法:

       1: cpf(ALLOW_PUT,RED,("+----------------This is Dreamxi Uart cpf test --------------+"));
       2: cpf(ALLOW_PUT,GRE,("+----------------This is Dreamxi Uart cpf test --------------+"));
       3: cpf(ALLOW_PUT,BLU,("+----------------This is Dreamxi Uart cpf test --------------+"));
       4: cpf(ALLOW_PUT,WHI,("+----------------This is Dreamxi Uart cpf test --------------+"));
       5: cpf(ALLOW_PUT,YEL,("+----------------This is Dreamxi Uart cpf test --------------+"));
       6: cpf(ALLOW_PUT,ZH,("+----------------This is Dreamxi Uart cpf test --------------+"));
       7: cpf(ALLOW_PUT,GB,("+----------------This is Dreamxi Uart cpf test --------------+"));

    最后实现的效果图:

    image

  • 相关阅读:
    WebClient, HttpClient, HttpWebRequest ,RestSharp之间的区别与抉择(几种Http请求方法)
    关于c#里面的httpclient的调用
    mvc项目架构分享系列之架构搭建初步 架构搭建初步
    关于在.NET中 DAL+IDAL+Model+BLL+Web
    三层架构(DAL/BLL/UI)和MVC设计模式的关系
    c#开发初学者之mvc及架构分层
    c#串口编程(转)
    【WPF】对话框/消息弹窗
    WPF如何不显示最大化,最小化的按钮
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1103:陶陶摘苹果
  • 原文地址:https://www.cnblogs.com/Dreamxi/p/1903804.html
Copyright © 2011-2022 走看看