飞鸟量天高

 

基于51单片机的Uart串口通信协议

1.串口通信协议

  嵌入式开发中,UART串口通信协议是我们常用的通信协议(UART、I2C、SPI等)之一,全称叫做通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),是异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输,它能将要传输的资料在串行通信与并行通信之间加以转换,能够灵活地与外部设备进行全双工数据交换。

 

1)起始位

  当未有数据发送时,数据线处于逻辑“1”状态;先发出一个逻辑“0”信号,表示开始传输字符。

2)数据位

  紧接着起始位之后。资料位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。

3)奇偶校验位

  资料为加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验资料传送的正确性。

4)停止位

  它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。

5)空闲位或起始位

  处于逻辑“1”状态,表示当前线路上没有资料传送,进入空闲状态。

  处于逻辑“0”状态,表示开始传送下一数据段。

6)波特率

  表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标,它用单位时间内载波调制状态改变的次数来表示。

  常用的波特率有:9600、115200……

  时间间隔计算:1秒除以波特率得出的时间,例如,波特率为9600的时间间隔为1s / 9600(波特率) = 104us。

7)接口

       接口通过两个引脚从外部连接到其它设备。任何 USART 双向通信均需要 至少两个引脚:接收数据输入引脚 (RX) 和发送数据引脚输出 (TX):
  RX:接收数据输入引脚就是串行数据输入引脚。过采样技术可区分有效输入数据和噪声,从而用于恢复数据。
  TX:发送数据输出引脚。如果关闭发送器,该输出引脚模式由其 I/O 端口配置决定。如果使 能了发送器但没有待发送的数据,则 TX 引脚处于高电平。在单线和智能卡模式下,该 I/O 用于发送和接收数据。

 2.发送函数

  这里的发送指的是51单片机发送数据到串口,单片机的TX接串口的RX。

  首先要根据你单片机的晶振频率,调试出一个104us的延时函数,用于时序控制。

  

 void Delay_104us(void)
{
    uint x=58;
	while(x-- !=0)
	{
		_nop_();
	}
}

  这个延时是基于下图所示的频率

                                         

 

  然后是发送函数

 

/************串口发送函数,Tx_Data为要发送的数据***********/
void Uart_Tx(uchar Tx_Data)
 {
	uchar uData=Tx_Data;	 
	uint i=0;

	/************拉低单片机的TX引脚104us,作为开始信号***********/
	UART_TX=0;
	Delay_104us();
	/************根据一字节数据每一个比特位的不同,TX拉高或拉低,保持104us,作为数据信号***********/
	for(i=0;i<8;i++)
	{
		UART_TX= uData & 0x01;
		Delay_104us();
		uData=uData>>1;

	}
	/************拉高单片机的TX引脚104us,作为结束信号***********/
	UART_TX=1;
	Delay_104us();
}

 3.接收函数 

  这里的接收指的是51单片机接收串口所发的数据,单片机的RX接串口的TX。

  这里还要调试出一个52us的延时。

  

void Delay_52us(void)
{
    uint x=28;
	while(x-- !=0)
	{
		_nop_();
	}
}

  接收函数

 /************串口接收函数,返回值为接收到的数据***********/
uchar Uart_Rx(void)
{
    uchar R_Data = 0x00,i;
    /************判断单片机的RX引脚是否拉低,有没有开始信号***********/    
    if( UART_RX== 0)
    {
    /************如果有,再过52us判断一次,这是防抖操作***********/    
        Delay_52us();
        if(UART_RX == 0)
      {
         /************如果是真的,就没过104us判断一次RX的电平变化,记录每一位数据***********/    
            Delay_104us();
            for(i=0;i<8;i++)
            {
                R_Data=R_Data>>1;
                if(UART_RX == 1)
                {
                    R_Data=R_Data|0x80;
                }                
                Delay_104us();                
            }            
        }
         /************判断单片机的RX引脚是否拉高,有没有结束信号,如果有就返回和重新用串口发送接收到的数据***********/    
        Delay_104us();
        if(UART_RX == 1)
        {
            Uart_Tx(R_Data);
            return R_Data;      
        
        }
    }
   
    return 0;

}

4.其他

(1)引脚定义

这里面的TX和RX引脚是自定义的,只要能够拉高,拉低,延时就行,下面是我定义的,

#define UART_TX P17
#define UART_RX P15

(2)发送汉字 

  每一个汉字都是由两个字节作为地址,在字库里索引出来的,发送就是发送汉字的地址,方法如下。

void Uart_String(uchar *Tx_String)
{
	while(*Tx_String)
	{
		Uart_Tx(*Tx_String++);
	}
} 

5.检验

  首先接好杜邦线,单片机的TX,RX接串口的RX,TX,还有GND线要接,VCC线可以不接。

        在主函数的while(1)循环里调用Uart_Tx(0x34),发送0x34,注意把串口助手的波特率调为9600。

 

   在主函数的while(1)循环里调用Uart_Rx(),单片机接收串口发送的数据

 

 

  在主函数的while(1)循环里调用Uart_String(),发送汉字,注意要把HEX显示去掉,不然就是16进制数了

 

 

 

 

  

 

posted on 2020-11-06 14:28  飞鸟量天高  阅读(1151)  评论(0编辑  收藏  举报

导航