单片机串口通信
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单片机串口通信
关键词:单片机,串口通信
单片机应用中,串口通信是不可缺少的部分。如何编写有效的串口通信程序对程序的结构、可靠性都有很大的影响。串口控制程序一般分为查询和中断两者方式。查询方式适用于简单的应用,简单可靠,但是缺点是需要占用处理器资源,在发送或者接收数据的时候不能做其它的事情,处理器利用率低。中断方式下,在发送或者接受数据的时候处理器还可以做其它的工作,效率较高。
对于稍微复杂的系统来说,中断方式管理串口程序将会更加有效。中断处理方式也可分为几种,其中采用循环缓冲区的方式比较高效。循环缓冲区为定义的一定长度的RAM区间,对于接受数据来说,中断中收到的数据将存入RAM中,然后等待主程序来读取。其中会涉及到数据见的协调问题,写数据的时候不能把还没有读取的数据覆盖掉,读数据的时候应该读取的是缓冲区中最老的数据。当缓冲区已满的时候,写入的新数据应该覆盖掉最老的数据。这些问题的处理可以使用两个指针来实现。
初始化时两个指针均指向RAM区间的底部,如图1所示。当中断中接收到一个数据的时候,将这个数据写入写指针WPTR指向的存储单元,然后调整写指针指向下一个空余的RAM区间,程序上处理就是把写指针加一,如图2所示。同理,写入N个数据后写指针同步更新,如图3所示。
当读数据的时候,首先判断缓冲区中是否有数据,方法是判断读指针和写指针是否相等,如果相等表明没有数据,如图5所示。如果读指针和写指针不等,那么读取缓冲区中的数据,然后调整读指针,当写指针和读指针相等的时候,表明缓冲区中的有效数据已经读取完,此时读指针和写指针相等。
当有数据再次写入的时候,继续紧接着上次写入的地址后写入新的数据,如果数据长度超过缓冲区的长度,写指针重新返回缓冲区的底部重新开始(这是循环缓冲的由来),如图6所示。此时如果有数据读出,读指针做同样的更新。如果没有数据读出,一直有数据写入,可能会出现缓冲区写满的情况,如图7所示。此时如果仍然没有数据读取,继续有数据写入的时候,为了保留新的数据,必须丢弃老的数据,即写指针可能超过读指针,此时,读指针必须和谐指针同步更新,这样才能保证读取的是没有被覆盖的最老的数据,如图8所示。
需要注意的是,读指针在中断过程中也可能被更改,因此,读数据的子程序需要对读指针的更改进行保护,方法是在读数据的时候关闭串行口中断。下面是循环缓冲区接收数据的程序实例。
FT, 尽然连文本都不能上传,代码只好贴出来吧。
/*
* FileName: uart.h
* Description: header file for SerialPort
* Author: SangWei, HUST-CEEE-2004
* Contact: swkyer@, swkyer@
* Date: 2005-09-22
*
* Platform: P89C6102(Philips), KeilC51(ver: 7.20)
*
* (C)All Rights Reserved.
*/
#ifndef __UART_H__
#define __UART_H__
#define UARTBUFFLEN 64 /* 串口缓冲区64个字节*/
void UartInit(void);
void SendChar(unsigned char ch);
unsigned char IsUartReceived(void);
unsigned char ReadChar(unsigned char idata *buf);
#endif /* __UART_H__ */
/*
* FileName: uart.c
* Description: Implementation of SerialPort
* Author: SangWei, HUST-CEEE-2004
* Contact: swkyer@, swkyer@ * Date: 2005-09-22
*
* Platform: P89C6102(Philips), KeilC51(ver: 7.20) *
* (C)All Rights Reserved.
*/
#include
#include "hardware.h"
#include "uart.h"
unsigned char data ramuse;
static unsigned char idata uartbuf;
static unsigned char idata bufwptr, bufrptr;
extern unsigned char xdata uartbuff[UARTBUFFLEN];
/*
* 初始化串口, 波特率9600
*/
void UartInit(void)
{
CLR_DOG;
status = 0;
bufwptr = 0; // 写指针
bufrptr = 0; // 读指针
MAX485CTL = 0; // 接收数据
PCON = 0x00; // 设置串口波特率, 时钟频率30MHZ
T2CON = 0x30; // 定时器2作为波特率发生器
SCON = 0x50; // 模式1
// n = 65536 - [fosc/baud*32]
// n = 65536 - 30000000/(19200*32) = 65536 - 49 = 654 90 = 0xffd2
// n = 65536 - 22118400/(19200*32) = 65536 - 36 = 655 00 = 0xffdc
#ifdef _DEBUG_AT_HOME
RCAP2H = 0xff;
RCAP2L = 0xb8; // baud rate 9600
TH2 = 0xff;
TL2 = 0xb8;
#else
RCAP2H = 0xff;
RCAP2L = 0x9e; // baud rate 9600
TH2 = 0xff;