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进制数了