本文档是个人博客文档系统的备份版本,作者:小游戏,作者博客:点击访问
在研究串口之前,我们需要看看所有的寄存器
首先是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_SW一是用于切换串口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 T1x定时器1的速度是传统8051的12倍 AUXR = 0x40; ///定时器1为1T模式 //TMOD它是定时器/计数器的工作模式寄存器,用于控制定时器的操作模式。我们设置了模式0 TMOD = 0x00; //定时器1模式0(16位自动重载) //TL定时器低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); }