Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1253847
  • 博文数量: 160
  • 博客积分: 4132
  • 博客等级: 中校
  • 技术积分: 2086
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-06 21:56
文章分类

全部博文(160)

文章存档

2012年(25)

2011年(120)

2010年(15)

分类: LINUX

2012-03-22 20:44:16

帮人做毕设 查到的东西留个底儿:


  Mini2440有三个串口,USRT0,UART1,UART3。 
对串口的操作有三种:串口初始化,串口接收,串口发送 
1 串口初始化 
1)串口初始化函数 
void Uart_Init(int pclk,int baud) 

    int i; 
    if(pclk == 0) 
    pclk    = PCLK; 
    rUFCON0 = 0x0;   //UART channel 0 FIFO control register, FIFO disable 
    rUFCON1 = 0x0;   //UART channel 1 FIFO control register, FIFO disable 
    rUFCON2 = 0x0;   //UART channel 2 FIFO control register, FIFO disable 
    rUMCON0 = 0x0;   //UART chaneel 0 MODEM control register, AFC disable 
    rUMCON1 = 0x0;   //UART chaneel 1 MODEM control register, AFC disable 
//UART0 
    rULCON0 = 0x3;   //Line control register : Normal,No parity,1 stop,8 bits 
     //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0] 
     // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode 
     //     0          1       0    ,     0          1        0           0     ,       01          01 
     //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling 
    rUCON0  = 0x245;   // Control register 
    rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );   //Baud rate divisior register 0 
//UART1 
    rULCON1 = 0x3; 
    rUCON1  = 0x245; 
    rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 ); 
//UART2 
    rULCON2 = 0x3; 
    rUCON2  = 0x245; 
    rUBRDIV2=( (int)(pclk/16./baud+0.5) -1 );     

    for(i=0;i<100;i++); 

l       串口时钟的设置 
pclk    = PCLK;使用PCLK作为串口的时钟。 
l       寄存器进行了设置 
主要是对三种寄存器进行了设置 
rUFCONn (n=0,1,2) —— 串口FIFO控制寄存器 
              rUMCONn (n=0,1)——串口调制控制寄存器 
rULCONn (n=0,1,2)——串口线性控制寄存器 
              rUCONn(n=0,1,2)——串口控制寄存器 
              rUBRDIVn(n=0,1,2)——串口Tx,Rx收发速率的设定 
2)串口的选择 
void Uart_Select(int ch) 

    whichUart = ch; 

2 串口发送 
串口发送数据通过判断rUTRSTATn (n=0,1,2)的第2位是不是为1来判断发送缓存是否为空。 
1)          串口发送字节   
void Uart_SendByte(int data) 

    if(whichUart==0) 
    { 
        if(data=='/n') 
        { 
            while(!(rUTRSTAT0 & 0x2)); 
           // Delay(1);                 //because the slow response of hyper_terminal 
            WrUTXH0('/r'); 
        } 
        while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty. 
      //  Delay(1); 
        WrUTXH0(data); 
    } 
    else if(whichUart==1) 
    { 
        if(data=='/n') 
        { 
            while(!(rUTRSTAT1 & 0x2)); 
            //Delay(1);                 //because the slow response of hyper_terminal 
            rUTXH1 = '/r'; 
        } 
        while(!(rUTRSTAT1 & 0x2));   //Wait until THR is empty. 
        //Delay(1); 
        rUTXH1 = data; 
    }   
    else if(whichUart==2) 
    { 
        if(data=='/n') 
        { 
            while(!(rUTRSTAT2 & 0x2)); 
            //Delay(1);                 //because the slow response of hyper_terminal 
            rUTXH2 = '/r'; 
        } 
        while(!(rUTRSTAT2 & 0x2));   //Wait until THR is empty. 
        //Delay(1); 
        rUTXH2 = data; 
    }       
}         
首先是串口通道的选择;然后判断THR是否为空,直到等到发送缓存为空,退出while循环;再要发送的字节data放到发送缓存中。如果发送的数据是回车的话,直接发送转义字符/r,当然也要等到THR为空才可以发送。 
2)          串口发送字符串 
void Uart_SendString(char *pt) 

    while(*pt) 
        Uart_SendByte(*pt++); 

把字符串看作是字符数组,字符指针*pt来指代字符数组的首地址,读取指针指向的字符,这样就可以把发送的的字符串逐个进行字节发送了。 
2 串口接收 
串口接收通过判断rUTRSTATn (n=0,1,2)的第1位是不是为1来判断发送缓存是否为空。 
1)串口等待接收状态 
void Uart_TxEmpty(int ch) 

    if(ch==0) 
        while(!(rUTRSTAT0 & 0x4)); //Wait until tx shifter is empty. 
    else if(ch==1) 
        while(!(rUTRSTAT1 & 0x4)); //Wait until tx shifter is empty. 
         
    else if(ch==2) 
        while(!(rUTRSTAT2 & 0x4)); //Wait until tx shifter is empty. 

寄存器rUTRSTATn & 0x4   (n=0,1,2)来判断tx shifter是不是为空 
3)          接收字符 
char Uart_Getch(void) 

    if(whichUart==0) 
    {       
        while(!(rUTRSTAT0 & 0x1)); //Receive data ready 
        return RdURXH0(); 
    } 
    else if(whichUart==1) 
    {       
        while(!(rUTRSTAT1 & 0x1)); //Receive data ready 
        return RdURXH1(); 
    } 
    else if(whichUart==2) 
    { 
        while(!(rUTRSTAT2 & 0x1)); //Receive data ready 
        return RdURXH2(); 
    } 
     
    return 0 ; 

寄存器rUTRSTATn & 0x1  (n=0,1,2)来判断Receive data ready?并把接收到的数据写到接收缓存里面。 
4)          接收字符串 
void Uart_GetString(char *string) 

    char *string2 = string; 
    char c; 
    while((c = Uart_Getch())!='/r') 
    { 
        if(c=='/b') 
        { 
            if( (int)string2 < (int)string ) 
            { 
                Uart_Printf("/b /b"); 
                string--; 
            } 
        } 
        else 
        { 
            *string++ = c; 
            Uart_SendByte(c); 
        } 
    } 
    *string='/0'; 
    Uart_SendByte('/n'); 

char Uart_GetKey(void) 

    if(whichUart==0) 
    {       
        if(rUTRSTAT0 & 0x1)    //Receive data ready 
            return RdURXH0(); 
        else 
            return 0; 
    } 
    else if(whichUart==1) 
    { 
        if(rUTRSTAT1 & 0x1)    //Receive data ready 
            return RdURXH1(); 
        else 
            return 0; 
    } 
    else if(whichUart==2) 
    {       
        if(rUTRSTAT2 & 0x1)    //Receive data ready 
            return RdURXH2(); 
        else 
            return 0; 
    }     

      return 0 ; 

寄存器rUTRSTATn & 0x1       (n=0,1,2) 
来判断Receive data ready?并把接收到的数据写到接收缓存里面。否则返回空。与getchar类似,并且也是返回字符类型。 

5)          接收整形数字 
函数返回类型:整形 
int Uart_GetIntNum(void) 

    char str[30]; 
    char *string = str; 
    int base     = 10; 
    int minus    = 0; 
    int result   = 0; 
    int lastIndex;     
    int i; 
     
    Uart_GetString(string); 
     
    if(string[0]=='-') 
    { 
        minus = 1; 
        string++; 
    } 
     
    if(string[0]=='0' && (string[1]=='x' || string[1]=='X')) 
    { 
        base    = 16; 
        string += 2; 
    } 
    lastIndex = strlen(string) - 1; 
    if(lastIndex<0) 
        return -1; 
    if(string[lastIndex]=='h' || string[lastIndex]=='H' ) 
    { 
        base = 16; 
        string[lastIndex] = 0; 
        lastIndex--; 
    } 

    if(base==10) 
    { 
        result = atoi(string); 
        result = minus ? (-1*result):result; 
    } 
    else 
    { 
        for(i=0;i<=lastIndex;i++) 
        { 
            if(isalpha(string)) 
            { 
                if(isupper(string)) 
                    result = (result<<4) + string - 'A' + 10; 
                else 
                    result = (result<<4) + string - 'a' + 10; 
            } 
            else 
                result = (result<<4) + string - '0'; 
        } 
        result = minus ? (-1*result):result; 
    } 
    return result; 

首先以字符串的形式接收数据Uart_GetString(string); 
然后通过判断是不是以‘-’开头来确定是不是负数,是负数则minus=1;再通过以0x,oX开头或者以H,h结尾来判断是不是16进制,否则为10进制;如果是10进制,则通过atoi把字符串转化为数字,并加上正负,如果是16进制,判断是不是字母,再判断大小写字母分别进行转换。16进制也支持正负号。 
6)          接收10进制的数 
int Uart_GetIntNum_GJ(void) 

    char string[16] ; 
    char *p_string = string ; 
    char c; 
    int i = 0 ; 
    int data = 0 ; 

    while(   ( c = Uart_Getch()) != '/r'  ) 
    { 
           if(c=='/b')       p_string--; 
           else           *p_string++=c; 
           
           Uart_SendByte( c ) ; 
    } 

    *p_string = '/0'; 

      i = 0 ; 
      while( string != '/0' ) 
      { 
           data = data * 10 ; 
           if( string<'0'||string>'9' ) 
                 return -1 ; 
           data = data + ( string-'0' ) ; 
           i++ ;           
      }     
       
      return data ; 

  只转化10进制的数字。首先用getchar接收单个字符存储在string中,然后把string转换为整型的data。并返回整形的data。 

3串口打印 
//If you don't use vsprintf(), the code size is reduced very much. 
void Uart_Printf(char *fmt,...) 

    va_list ap; 
    char string[256]; 
    va_start(ap,fmt); 
    vsprintf(string,fmt,ap); 
    Uart_SendString(string); 
    va_end(ap); 

va_list完成可变参数的操作 
具体实现如下 
n       由于无法列出传递函数的所有实参的类型和数目时,用省略号指定参数表 
void Uart_Printf(char *fmt,...) 
n       函数参数的传递原理 
函数参数是以数据结构:栈的形式存取,从右至左入栈. 
n       获取省略号指定的参数 
在函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。 
va_list ap; 
   char string[256]; 
va_start(ap,fmt); 
    vsprintf(string,fmt,ap); 
    Uart_SendString(string); 
    va_end(ap); 
va_start使ap指向第一个可选参数。va_end把ap指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。 
vsprintf(string,fmt,ap);实现向字符数组中写指定格式的内容

=============================================================================
=============================================================================

硬件 mini2440核心板,自已画的底板,另外一块带串口的单片机学习板(挂着DS18B20),学习板连续输出DS18B20的温度值,波特率19200。

在一个文件夹里新建一个文件,我的是voltage_set.c(以后用来调压)

 

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define FALSE -1
#define TRUE  1
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, //
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300,
38400, 19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
 int i;
 int status;
 struct termios Opt;
 tcgetattr(fd, &Opt);
 for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
 {
  if (speed == name_arr[i])
  {
   tcflush(fd, TCIOFLUSH);
   cfsetispeed(&Opt, speed_arr[i]); 
   cfsetospeed(&Opt, speed_arr[i]);
   status = tcsetattr(fd, TCSANOW, &Opt); 
   if (status != 0)
    perror("tcsetattr fd1");
   return;
  }
  tcflush(fd,TCIOFLUSH); //í¬éÏ
 }
}

int set_Parity(int fd,int databits,int stopbits,int parity)
{
 struct termios options; //¶¨òåò»¸ö½á11
 if ( tcgetattr( fd,&options) != 0) //ê×Ïè¶áè¡Ïμí3ĬèÏéèÖÃoptionsÖD,±ØDë
 {
  perror("SetupSerial 1");
  return(FALSE);
 }
 options.c_cflag &= ~CSIZE; //ÕaêÇéèÖÃc_cflagÑ¡Ïî2»°′λêy¾YλÑúÂë
 switch (databits)
 {
 case 7:
  options.c_cflag |= CS7; //éèÖÃc_cflagÑ¡Ïîêy¾YλÎa7λ
  break;
 case 8:
  options.c_cflag |= CS8; //éèÖÃc_cflagÑ¡Ïîêy¾YλÎa8λ
  break;
 default:
  fprintf(stderr,"Unsupported data size\n"); //ÆäËûμĶ¼2»Ö§3Ö
  return (FALSE);
 }
 switch (parity) //éèÖÃÆæżD£Ñ飬c_cflagoíc_iflagóDD§
 {
 case 'n':
 case 'N':
  options.c_cflag &= ~PARENB;
  options.c_iflag &= ~INPCK;
  break;
 case 'o':
 case 'O': options.c_cflag |= (PARODD | PARENB);
  options.c_iflag |= INPCK;
  break;
 case 'e':
 case 'E':
  options.c_cflag |= PARENB;
  options.c_cflag &= ~PARODD;
  options.c_iflag |= INPCK;
  break;
 default:
  fprintf(stderr,"Unsupported parity\n");
  return (FALSE);
 }
 
 switch (stopbits)
 {
 case 1:
  options.c_cflag &= ~CSTOPB;
  break;
 case 2:
  options.c_cflag |= CSTOPB;
  break;
 default:
  fprintf(stderr,"Unsupported stop bits\n");
  return (FALSE);
 }
 
 if (parity != 'n')
  options.c_iflag |= INPCK;
 
 
 options.c_cc[VTIME] = 150; // 15 seconds
 options.c_cc[VMIN] = 0;
 
 tcflush(fd,TCIFLUSH);
 if (tcsetattr(fd,TCSANOW,&options) != 0)
 {
  perror("SetupSerial 3");
  return (FALSE);
 }
 return (TRUE);
}

int OpenDev(char *Dev)
{
    int fd = open( Dev, O_RDWR ); //| O_NOCTTY | O_NDELAYÕaÖÖ·½ê½¿′openoˉêy
    if (-1 == fd)
    {
  perror("Can't Open Serial Port");
  return -1;
    }
    else
  return fd;
}

int main(int argc, char **argv)
{
    int fd;
    int nread;
    char buff[512];
    char *dev ="/dev/ttySAC1";
    fd = OpenDev(dev);
    if (fd>0)
    {
 printf("Open Serial succeed\n");
 set_speed(fd,19200);
    }
    else
    {
  printf("Can't Open Serial Port!\n");
  exit(0);
    }
    if (set_Parity(fd,8,1,'N')== FALSE)
    {
  printf("Set Parity Error\n");
  exit(1);
    }
 
    while(1)
    {
 int i;
// char buff1[2]={0x5a,0x5a};
// write(fd,buff1,1);
 while((nread = read(fd,buff,512))>0)
 {
  printf("\nLen %d\n",nread);
  buff[nread+1]='\0';
  for(i=0;i   printf("0x%x",buff[i]);
  printf("\n");
 }
    }
    //close(fd);
    //exit(0);
}

 

完了之后arm-linux-gcc -o voltage_set voltage_set.c

生成voltage_set

下载到mini2440核心板中

执行#./voltage_set

把学习板的地与核心板的地相连,学习板的TX与核心板的RX2相连就可以看到温度值了,当然,我用16进制显示在超级终端上,关掉程序用ctrl+c



======================================================================================
======================================================================================
inux串口C程序,基于mini2440与TX2440A5小时前

  弄了好多天这个串口程序了,昨天晚上终于好了,现在把过程给贴出来 

  环境:Asinaux linux 2.6(其它系统也可以) 

  硬件环境:mini2440(linux2.6.29)或TX2440A(2.6.31) 

  编译器:arm-linux-gcc4.1.2 

  先献上程序:main.c 

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  #include  

  /******************************************************* 

  * 功 能:初始化串口 

  * 程序名称:int uart_init(int arg, int baud) 

  * 参 数:arg: 串口号 baud: 波特率 

  * 返 回 值:成功:串口打开句柄 失败:返回 -1 

  * 创 建 人:ZB 

  * 创建日期:07.05.08 

  * 版本更新 

  *******************************************************/ 

  int uart_init(int arg, int baud) 

  { 

  int fd; 

  char port[20]; 

  struct termios Opt; 

  int uartbiit[50]={B115200,B9600,B19200,B4800,B2400,B1200}; 

  sprintf(port,"/dev/s3c2410_serial%d",arg); /*2.6.31内核的串口设备文件是/dev/s3c2410_serialX(X=0 1 2 

  或3), 在mini2440中/dev/ttySACX(X=0 1 2或3)不再是ttyS0,ttyS1,ttyS2*/ 

  printf("port %s \n", port); 

  fd = open(port, O_RDWR); //打开串口 

  if (fd<0) 

  { 

  return -1; //没有打开返回 

  } 

  tcgetattr(fd,&Opt); //初始化 

  tcflush(fd,TCIFLUSH); 

  cfsetispeed(&Opt,uartbiit[baud]); //设置波特率 

  cfsetospeed(&Opt,uartbiit[baud]); 

  Opt.c_cflag |= CS8; //设置数据位 

  Opt.c_cflag &= ~PARENB; 

  Opt.c_oflag &= ~(OPOST); 

  Opt.c_cflag &= ~CSTOPB; 

  Opt.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN); 

  Opt.c_iflag &= ~(INPCK|BRKINT|ICRNL|ISTRIP|IXON); 

  Opt.c_cc[VMIN] = 0; 

  Opt.c_cc[VTIME] = 0; 

  if (tcsetattr(fd,TCSANOW,&Opt) != 0) //装载初始化参数 

  { 

  perror("SetupSerial!\n"); 

  close(fd); 

  return -1; 

  } 

  return(fd); 

  } 

  int main() 

  { 

  int fd, len = 0, i=0; 

  char buf[20]; 

  if((fd = uart_init(1, 0)) <0) //打开串口0,波特率为115200; 

  { 

  printf("Open uart err \n"); 

  return -1; 

  } 

  sprintf(buf, "Hello world !\n"); //输出内容 

  for(;;) 

  { 

  sprintf(buf, "%d", i++); 

  len = write(fd, buf, 1); //写串口 

  printf("Open uart err \n"); //为测试是不是运行到这里设的输出 

  if(len > 0) 

  { 

  read(fd, buf, sizeof(buf)); //读串口数据 

  printf("buf %s\n", buf); //输出读到的数据 

  } 

  usleep(100000); 

  } 

  return 0; 

  } 

  此时再编译下载到开发板运行,用windows串口和板子的串口连在一起,看一下是不是接收到数据了,是一直发的,并且一直累加, 

  以下是输出内容: 

  port /dev/s3c2410_serial1 

  Open uart err 

  buf 0 

  Open uart err 

  buf 1 

  Open uart err 

  buf 2 

  Open uart err 

  buf 3 

  Open uart err 

  buf 4 

  Open uart err 

  buf 5 

  Open uart err 

  buf 6 

  Open uart err 

  buf 7 

  Open uart err 

  buf 8 

  Open uart err 

  buf 9 

  Open uart err 

  buf 10 

  Open uart err 

  buf 11 

  Open uart err 

  buf 12 

  Open uart err 

  buf 13 

  Open uart err 

  buf 14 

  Open uart err 

  buf 15 

  Open uart err 

  buf 16 

  Open uart err 

  buf 17 

  Open uart err 

  buf 18 

  Open uart err 

  buf 19 

  Open uart err 

  buf 20 

  Open uart err 

  buf 21 

  Open uart err 

  buf 22 

  Open uart err 

  buf 23 

  Open uart err 

  buf 24 

  Open uart err 

  buf 25 

  Open uart err 

  buf 26 

  Open uart err 

  buf 27 

  Open uart err 

  buf 28 

  Open uart err 

  buf 29 

  Open uart err 

  buf 30 

  Open uart err 

  buf 31 

  Open uart err 

  buf 32 

  Open uart err 

  buf 33 

  Open uart err 

  buf 34 

  Open uart err 

  buf 35 

  Open uart err 

  buf 36 

  有用的话大家可以交流一下的,我QQ115424242或786298427 

阅读(3223) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~