首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

UART传输实验及心得体会

UART传输实验及心得体会

UART传输实验及心得体会
概述:
串行通信,即是数据一位一位顺序传送。
按照串行数据的时钟控制方式,可以分为同步通信和异步通信两类。
(1)异步通信:数据以一定的协议,把字符组成特定的字符帧传送。发送端和接收端由各自独立的时钟来控制数据的接收和发送,这两个时钟彼此独立,不需要同步。
(2)公共时钟同步:指的是在数据的传输过程中,发送端和接收端共同享用一个时钟源,在同一时钟缓冲器发送的时钟(不一定是同向,也可能接收端和发送端各自定义相位)作用下完成数据的正确发送和接收。

波特率:
波特率等于每秒钟传输的数据位数,如果设置波特率为115200,数据位为8bit,起始位为1bit,结束位为1bit,校验位为1bit;那1s钟不间断可传送的字符(1bit起始位+8bit数据位+1bit校验位+1bit结束位,共11bit)为115200/11=10472;速率约为10kB/ps;假使传送一幅200KB的图片,需要的时间约为20s;往往,主机和从机波特率的设置出来的时钟频率不一定和想要设置的一样。但只要相差不要太大,即一个码元(这里是11bit)的误差不要超过1bit的几%就可以使传送接收正确。具体是几%,和发送和接收的机制有关,需要满足接收端的建立保持时间。同样,传输距离的加长,导致负载电容加大,边沿会变缓而且上升时间变大,速率上不去,也会导致一定的偏差,故RS232串口一般都是短距离传输。

2440波特率的产生
2440A的UART波特率由UART波特率分频寄存器设置;

其中n=0~2,对应每一个UART,CLK为PCLK或者UCLK分频、外部输入时钟获得,详细看寄存器描述。

寄存器简单描述
UART线路控制寄存器ULCONn:
正常模式和红外接收发送模式选择;
校验方式选择:无校验、奇校验、偶校验;
停止位设置;
数据位设置;
UART控制寄存器UCONn:
FCLK分频系数设置;
时钟选择;
发送中断、接收中断触发类型:脉冲或电平;
接收暂停允许;
接收错误中断允许;
巡检模式允许;(多路轮询检测)
发送间隔信号允许;
发送接收模式:中断或查询,DMA;
UART FIOF控制寄存器UFCONn:
发送和接收FIFO长度设置:空,4字节,8字节和16字节;
发送和接收FIFO复位;
FIFO允许;
UART 调制解调器控制寄存器UMCONn:
自动流控制是否有效;(RTS、CTS等可以查RS232的定义)
nRTS 激活或禁止;
UART接收发送状态寄存器UTRSTATn:
发送缓存和移位寄存器是否为空标志;
接收缓存基础其是否为空标志;
UART错误状态寄存器UERSTATn:
是否中断接收;
错误指示:帧错误、奇偶错误、溢出错误;
UART FIFO状态寄存器UFSTATn:
接收及接收FIFO满标志;
发送及接收FIFO的数据数量;
UART调制解调器状态寄存器UMSTATn:
nCTS状态是否变化标志;
CTS激活与否;
UART发送缓存寄存器UTXH:
UART的发送数据;
UART接收缓存寄存器URXH:
UART的接收数据;
UART波特率除数寄存器UBRDIVn:
波特率分频值;

电路图设计

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
}
//发送字符串由发送字符组成
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)
//串口初始化设置
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[i]))
             {
                 if(isupper(string[i]))
                     result = (result<<4) + string[i] - 'A' + 10;
                 else
                     result = (result<<4) + string[i] - 'a' + 10;
             }
             else
                 result = (result<<4) + string[i] - '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[i] != '\0' )
        {
               data = data * 10 ;
               if( string[i]<'0'||string[i]>'9' )
                      return -1 ;
               data = data + ( string[i]-'0' ) ;
               i++ ;            
        }   

        return data ;
}
返回列表