| 
 | 
 
UART实验程序设计及分析 
UART实验程序设计及分析 
 
void Uart_Printf(char *fmt,...) 
 
{ 
 
  
 
    va_list ap;             //声明一个va_list, 
 
    char string[256]; 
 
    va_start(ap,fmt);       //然后用va_start函数来获取参数列表中的参数 
 
       /* 函数名: vsprintf  功能: 送格式化输出到串中 
 
        返回值: 正常情况下返回生成字串的长度 
 
       (除去\0),错误情况返回负值         
 
       用 法: int vsprintf(char *string, char *format, va_list param);    
 
       // 将param 按格式format写入字符串string中    
 
       注: 该函数会出现内存溢出情况, 
 
       建议使用vsnprintf   */ 
 
    vsprintf(string,fmt,ap); 
 
    Uart_SendString(string); 
 
    va_end(ap);           //把ap指向NULL 
 
} 
 
  
 
http://blog.sina.com.cn/s/blog_642c9bdd0100llov.html 
 
//发送字符串由发送字符组成 
 
void Uart_SendString(char *pt) 
 
{ 
 
    while(*pt) 
 
        Uart_SendByte(*pt++); 
 
} 
 
  
 
void Uart_SendByte(int data) 
 
{ 
 
    if(whichUart==0)          //选择第几个串口 
 
    { 
 
        if(data=='\n')        //当发送的是换行回车符时做的动作 
 
        { 
 
            while(!(rUTRSTAT0 & 0x2)); 
 
            WrUTXH0('\r'); 
 
        } 
 
//等待原来的数据已经发送结束再把数据写进发送缓冲寄存器 
 
        while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty. 
 
        WrUTXH0(data); 
 
    }      
 
}               
 
其中:#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000023)=(unsigned char)(ch) 
 
寄存器定义。 
 
WrUTXH0('\r');就是把'\r'写到寄存器[0x50000023]里 
 
  
 
<tbody><tr><td width="670px"><div>RdURXH0(),WrUTXH0(),找不到函数的原型,后来在寄存器定义里面看到了。如下: 
<p>#define rUTXH0  (*(volatile unsigned char *)0x1d00020)<br>#define rUTXH1  (*(volatile unsigned char *)0x1d04020)<br>#define rURXH0  (*(volatile unsigned char *)0x1d00024)<br>#define rURXH1  (*(volatile unsigned char *)0x1d04024)<br>#define WrUTXH0(ch) (*(volatile unsigned char *)0x1d00020)=(unsigned char)(ch)<br>#define WrUTXH1(ch) (*(volatile unsigned char *)0x1d04020)=(unsigned char)(ch)<br>#define RdURXH0() (*(volatile unsigned char *)0x1d00024)<br>#define RdURXH1() (*(volatile unsigned char *)0x1d04024)<br>#define UTXH0  (0x1d00020)    //byte_access address by BDMA<br>#define UTXH1  (0x1d04020)<br>#define URXH0  (0x1d00024)<br>#define URXH1  (0x1d04024)</p> 
<p>      WrUTXH0('\r'),即把'\r'写到寄存器[0x1d00020]里面,而寄存器[0x50000027]是UART0的发送寄存器,也就是换行。而rUTXH0,也是UART的发送保持寄存器,若要做WrUTXH0('\r')相同的效果,则需把相应的命令值赋给rUTXH0:即:rUTXH0=“\r”。</p> 
</div></td></tr></tbody></table> 
 
  
 
http://www.360doc.com/content/11/0112/17/4591140_86020062.shtml 
 
#define A    (* (volatile unsigned *)   0x48000000 )</span></div> 
<div><br>对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的“端口”的概念。</div> 
<div>如果是内存映射,那就方便的多了。</div> 
<div>举个例子,比如向寄存器A(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了:</div> 
<div>#define A (*(volatile unsigned *) 0x48000000 )<br>...<br>     A = 0x01;<br>...</div> 
<div>这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。</div> 
<div>volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改变。</div> 
<div>volatile 限定编译器不对这个指针的指向的存储单元进行优化, 即不用通用寄存器暂时代替这个指针的指向的存储单元,而是每次取值都直接到指针的指向的存储单元取值.volatile 主要用于变量会异步改变的情下,主要有三个方面:</div> 
<div>1.cpu外设寄存器</div> 
<div>2.中断和主循环都会用到的全局变量</div> 
<div>3.操作系统中的线程间都会用到的公共变量.</div> 
<div> </div> 
<div>上述表达式拆开来分析:</div> 
<div>首先(volatile unsigned *) 0x48000000的意思是把0x48000000强制转换成volatile unsigned类型的指针,即对指针的操作的范围是从0x48000000开始的4个字节(int型),暂记为p。那么就有:</div> 
<div>#define A   *p,即A为P指针指向位置的内容了。这里就是通过内存寻址访问到寄存器A,可以读/写操作!</div> 
 
//串口初始化设置 
 
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 
 
    rUCON0  = 0x245;   // Control register  interrupt request mode, trigger level use PCLK 
 
    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++); 
 
} 
 
同理,接收数据的程序如下: 
 
//判断接收是否空 
 
void Uart_TxEmpty(int ch) 
 
{ 
 
    if(ch==0) 
 
        while(!(rUTRSTAT0 & 0x4)); //Wait until tx shifter is empty. 
 
} 
 
  
 
char Uart_Getch(void) 
 
{ 
 
    if(whichUart==0) 
 
    {       
 
        while(!(rUTRSTAT0 & 0x1)); //Receive data ready 
 
        return RdURXH0(); 
 
} 
 
} 
 
  
 
//此函数供RTC 调用,和Uart_Getch的区别在于没while的死循环 
 
char Uart_GetKey(void) 
 
{ 
 
    if(whichUart==0) 
 
    {       
 
        if(rUTRSTAT0 & 0x1)    //Receive data ready 
 
            return RdURXH0(); 
 
        else 
 
            return 0; 
 
} 
 
} 
 
  
 
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'); 
 
} 
 
  
 
//把发送的字符变为数字,识别负号, 
 
//和十六进制。还可以进一步完善   以下两个函数是处理数据 
 
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; 
 
} 
 
  
 
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 ; 
 
} |   
 
 
 
 |