集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1018|回复: 1

UART实验程序设计及分析

[复制链接]
fpga_feixiang 发表于 2019-8-23 11:12:34 | 显示全部楼层 |阅读模式
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&nbsp;&nbsp;(*(volatile unsigned char *)0x1d00020)<br>#define rUTXH1&nbsp;&nbsp;(*(volatile unsigned char *)0x1d04020)<br>#define rURXH0&nbsp;&nbsp;(*(volatile unsigned char *)0x1d00024)<br>#define rURXH1&nbsp;&nbsp;(*(volatile unsigned char *)0x1d04024)<br>#define WrUTXH0(ch)&nbsp;(*(volatile unsigned char *)0x1d00020)=(unsigned char)(ch)<br>#define WrUTXH1(ch)&nbsp;(*(volatile unsigned char *)0x1d04020)=(unsigned char)(ch)<br>#define RdURXH0()&nbsp;(*(volatile unsigned char *)0x1d00024)<br>#define RdURXH1()&nbsp;(*(volatile unsigned char *)0x1d04024)<br>#define UTXH0&nbsp;&nbsp;(0x1d00020)&nbsp;&nbsp;&nbsp; //byte_access address by BDMA<br>#define UTXH1&nbsp;&nbsp;(0x1d04020)<br>#define URXH0&nbsp;&nbsp;(0x1d00024)<br>#define URXH1&nbsp;&nbsp;(0x1d04024)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WrUTXH0('\r'),即把'\r'写到寄存器[0x1d00020]里面,而寄存器[0x50000027]是UART0的发送寄存器,也就是换行。而rUTXH0,也是UART的发送保持寄存器,若要做WrUTXH0('\r')相同的效果,则需把相应的命令值赋给rUTXH0:即:rUTXH0=&#8220;\r&#8221;。</p>
</div></td></tr></tbody></table>



http://www.360doc.com/content/11/0112/17/4591140_86020062.shtml

#define A&nbsp;&nbsp;&nbsp; (* (volatile unsigned *)&nbsp;&nbsp; 0x48000000 )</span></div>
<div><br>对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的&#8220;端口&#8221;的概念。</div>
<div>如果是内存映射,那就方便的多了。</div>
<div>举个例子,比如向寄存器A(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了:</div>
<div>#define A (*(volatile unsigned *) 0x48000000 )<br>...<br>&nbsp;&nbsp;&nbsp;&nbsp; A = 0x01;<br>...</div>
<div>这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。</div>
<div>volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种&#8220;意想不到地改变&#8221;,不是由程序去改变,而是由硬件去改变。</div>
<div>volatile 限定编译器不对这个指针的指向的存储单元进行优化, 即不用通用寄存器暂时代替这个指针的指向的存储单元,而是每次取值都直接到指针的指向的存储单元取值.volatile 主要用于变量会异步改变的情下,主要有三个方面:</div>
<div>1.cpu外设寄存器</div>
<div>2.中断和主循环都会用到的全局变量</div>
<div>3.操作系统中的线程间都会用到的公共变量.</div>
<div>&nbsp;</div>
<div>上述表达式拆开来分析:</div>
<div>首先(volatile unsigned *) 0x48000000的意思是把0x48000000强制转换成volatile unsigned类型的指针,即对指针的操作的范围是从0x48000000开始的4个字节(int型),暂记为p。那么就有:</div>
<div>#define A&nbsp;&nbsp; *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 ;

}
zxopenhl 发表于 2019-8-23 16:38:21 | 显示全部楼层
UART实验程序设计及分析
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|集成电路技术分享 ( 京ICP备20003123号-1 )

GMT+8, 2024-4-26 09:26 , Processed in 0.064631 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表