- UID
- 864567
|
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 ;
} |
|