串口详解


在研究串口前,我们需要看一下所有的寄存器

首先是SCON,主要是用来设置串口的工作方式

详细参数其实不需要知道的非常非常清楚,因为我们一般都是有默认情况的

文档写着麻烦,直接上例程

/***
串口控制发送函数
***/
#include "reg51.h"
#include "intrins.h"
#include "send.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

#define FOSC 11059200L          //系统频率
#define BAUD 9600             //串口波特率

sfr AUXR  = 0x8e;               //辅助寄存器

sfr P_SW1   = 0xA2;             //外设功能切换寄存器1

#define S1_S0 0x40              //P_SW1.6
#define S1_S1 0x80              //P_SW1.7

bit busy;


/*串口初始化*/
void uInit()
{
	//ACC 是一个累加器,主要用来存放数据
	ACC = P_SW1;
    ACC &= ~(S1_S0 | S1_S1);    //S1_S0=0 S1_S1=0
	//P_SW1是一个特殊功能的寄存器,用来将串口1进行切换
    P_SW1 = ACC;                //(P3.0/RxD, P3.1/TxD)
	// 串行控制器SCON为01010000
	//SM0为0 SM1为1 说明工作方式为方式1 8位UART,波特率可变
	//SM2为0 说明不是多机通信
	//REN为1 允许串行接收
	//TB8为0 在方式2或3中表示发送的第9位数据,我们用的是方式1不管
	//RB8为0 在方式2或3中表示接收的第9位数据,我们也不管
	//TI为0 主要用于发送中断请求的标志位
	//RI为0 用于接收中断的标志位
    SCON = 0x50;                //8位可变波特率
	//AUXR是辅助寄存器用来控制定时器的分频
	//01000000 T1x12为1表示定时器1的速度是传统8051的12倍
    AUXR = 0x40;                //定时器1为1T模式
	//TMOD是定时器/计数器的工作模式寄存器,用来控制定时器的操作模式,我们设置的是模式0
    TMOD = 0x00;                //定时器1为模式0(16位自动重载)
	//TL1是定时器的低8位,TH1是定时器的高8位,这个定时器主要是用来控制波特率的
    TL1 = (65536 - (FOSC/4/BAUD));   //设置波特率重装值
    TH1 = (65536 - (FOSC/4/BAUD))>>8;
	//TR1为1表示定时器1的控制为,如果为1就表示开始启动定时器
    TR1 = 1;                    //定时器1开始启动
	//ES主要是串口中断控制为,如果为1表示允许串口中断
    ES = 1;                     //使能串口中断
	//EA表示CPU总的中断允许位,如果为1,那么就表示开放CPU中断
    EA = 1;
 //   SendString("STC15F2K60S2\r\nUart Test !\r\n");
}


/*----------------------------
UART 中断服务程序
interrupt 4表示串口中断
//对于51来说
中断bai0 外部中断0
中断du1 定时器zhi1中断
中断2 外部中断1
中断3 定时器2中断
中断4 串口中断

using解释
用来选择80c51单片机中不同的寄存器组,你也知道R0-R7总共有4组,那么using 后面的数字也就是0-3范围里的一个数了。如果不需要using的话,编译器会自动选择一组寄存器作为绝对寄存器访问的。
using对代码是有一定的影响的。
给你说个简单的例子,你可以想下,
如果定义 
void time0() interrupt 1 using 1
假设,我们又在中断里调用了一个delay();这个delay是起延时作用。
那么,我们就需要确保我们使用的寄存器组是同一组,否则,就会出现混乱。
-----------------------------*/
void Uart() interrupt 4 using 1
{
	// 在串口发生中断的时候RI为1表示有数据接收,我们把这位清零用于下次判断
    if (RI)
    {
        RI = 0;                 //清除RI位
        P0 = SBUF;              //P0显示串口数据
    }
	// TI为0表示发送中断,我们主要用来判断当前是否可以发送数据
    if (TI)
    {
        TI = 0;                 //清除TI位
        busy = 0;               //清忙标志
    }
}

/*----------------------------
发送串口数据
这个函数用来向串口发送数据
----------------------------*/
void SendData(BYTE dat)
{
	// busy判断数据是否发送完毕
    while (busy);               //等待前面的数据发送完成
	// 我们用ACC来存放发送的数据
    ACC = dat;                  //获取校验位P (PSW.0)
	//P表示奇偶的标志位(当ACC1的个数为奇数的时候P为1反之)。TB8是发送的第9位数据,所以这个是用来校验的
    if (P)                      //根据P来设置校验位
    {
        TB8 = 0;                //设置校验位为0
    }
    else
    {
        TB8 = 1;                //设置校验位为1
    }
	// busy表示需要发送数据,当发送完毕时,会清0
    busy = 1;
	// 发需要发送的数据放到寄存器中去
    SBUF = ACC;                 //写数据到UART数据寄存器
}

/*----------------------------
发送字符串,因为字符串是一个字符数组,所以我们这里是通过指针来发送数据
----------------------------*/
void SendString(char *s)
{
    while (*s)                  //检测字符串结束标志
    {
        SendData(*s++);         //发送当前字符
    }
}

主函数调用

//****************************************
// Update to MPU6050 by shinetop
// MCU: STC89C52
// 2012.3.1
// 功能: 显示加速度计和陀螺仪的10位原始数据
//****************************************
// 使用单片机STC89C52
// 晶振:11.0592M
// 显示:串口
// 编译环境 Keil uVision2
//****************************************
#include "reg51.h"
#include "send.h"
typedef unsigned char  uchar;
typedef unsigned short ushort;
typedef unsigned int   uint;


void Delay1000ms();
//*******************************************************************************************************
//主程序
//*******************************************************************************************************
void main()
{ 
	//初始化串口
	uInit();
	while(1){
		Delay1000ms();
		SendString("hello,word");
	}
}


// 延时1秒
void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 43;
	j = 6;
	k = 203;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

文章作者: 小游
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小游 !
  目录