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

posted on 2010-12-12 16:55  Dreamxi  阅读(1432)  评论(0编辑  收藏  举报