1.设计要求

  利用串口技术,控制数码管、LED、小车的启停

2.设计概述

        本实验所用芯片为STC89C52,所用硬件是由华清远见基于STC89C52开发的智能小车,该小车具有流水灯模块、蜂鸣器模块、独立键盘模块、矩阵键盘模块等。本实验使用串口技术远程控制小车,串口传输数据格式为   L/G/C  + 指令 + ‘ ;’。如,控制小车数码管显示1314,则通过串口发送‘G1314;’;控制小车启动则通过串口发送‘CY;’控制小车停止则通过串口发送‘CN;’;控制led灯开启则发送‘LY;’;控制LED灯关闭则发送‘LN;’。

3.原理图以及线路连接


J10-EN1接C52-P1.4                        //EN1为左电机的使能端,只有当EN1为1时,左电机才能启动
J10-EN2接C52-P1.5                        //EN2为右电机的使能端,只有当EN2为1时,右电机才能启动
J10-IN1接C52-P1.2                         //IN1控制左电机反转,当IN1为1,IN2为0时,左电机反转
J10-IN2接C52-P1.3                        //IN2控制左电机正转,当IN2为1,IN1为0时,左电机正转
J10-IN3接C52-P1.6                        //IN3控制右电机正转,当IN3为1,IN4为0时,左电机正转
J10-IN4接C52-P1.7                        //IN4控制右电机反转,当IN4为1,IN3为0时,左电机反转

4.软件设计

串口通信设置

1.配置SCON寄存器的SM0和SM1位,使串口以模式1的方式工作。      SM0 = 0,SM1 = 1

2.配置SCON寄存器的REN位,使能串口接收(REN = 1)

3.配置PCON寄存器的SMOD位,使波特率不加倍(SMOD = 0)

4.配置定时器1的相关寄存器,使定时器工作在模式2,且TH1 = TL1 = 0xfd

5.配置IE寄存器,开启串口中断

6.编写串口中断服务函数,在函数中对中断请求标志位TI和RI清零

模式0:同步通信

模式1:异步通信,8位数据位,波特率可变(常用)

模式2:异步通信,9位数据位,波特率固定

模式3:异步通信,9位数据位,波特率可变

波特率通过定时器1配置 当单片机为12T模式且SMOD位为0时

波特率 = 系统时钟/12/32/(256 – TH1)

假设我们要得到9600的波特率 那么

TH1 = 256 – 11059200/12/32/9600 = 256-3=253

然后启动定时器1即可(不用开定时器1中断)

void uartInit()
{
   SM0 = 0;
   SM1 = 1;//配置串口工作在模式1
   REN = 1;//使能接收

   PCON &= ~(1<<7);//使SMOD = 0;

   ES = 1;//开启串口中断
   EA = 1;//开总中断
}

void timer1Init()
{
	TMOD = 0x20;//配置定时器1工作在模式2
	TH1 = TL1 = 0XFD;//配置波特率为9600
	ET1 = 0;//禁止timer1中断
	TR1 = 1;//启动定时器1	
}

接收信息处理

(数码管相关知识在计数器中有详细解释,小车的fornt函数等在寻迹小车中有详细解释)

串口开始运行后开始逐个字符向C52的SBUF寄存器发送,然后逐个处理数据

字符串的第一个数据设置为模式选择位,即通过向SBUF发送G/L/C选择控制小车的不同功能

在G模式下:G后面的字符串表示要在数码管显示的数字,以;结束字符串,由于数码管数字显示是动态显示,所以需要在主函数中不断显示,否则在没有信息传输时会只显示最后一位数字。

在L/C模式下:L/C后面的字符Y/N表示开/关,以;结束。

void uart1() interrupt 4
{
	char temp = 0;
	/*	接收到数据后将数据传给temp,将RI置0,等待下一次接收	*/
	if(RI)							 
	{
		temp = SBUF;
		RI = 0;
		/*	如果模式选择位没有选择,则选择模式,L控制led灯开关;G控制数码管开关;C控制小车开关*/
		if(mflag == 0)
		{
			mflag = temp;
		}
		else
		{
			switch(mflag)
			{
				/*	模式G下,逐个输入数字,以';'结束*/
				case 'G':
					if(temp != ';')
					{
							t = t*10+(temp-48);	 //接收到的是字符,字符数字-48则为数值
					}
					if(temp == ';')
						{
							flag = 1;
							mflag = 0;
							p = t;
							t = 0;
						}
					break;
				/*	模式L,输入Y开启LED灯,N关闭LED灯,;结束输入*/
				case 'L':
						if(temp == 'Y')
							P1 = 0x00;
						if(temp == 'N')
							P1 = 0xFF;
						if(temp == ';')
							mflag =0;
							break;
				/* 	模式C下,输入Y小车前进,输入N停止,;结束*/
				case 'C':
					if(temp == 'Y')
						fornt();
					if(temp == 'N')
						stop();
					if(temp == ';')
					{
						mflag = 0;
					}
					break;
				default:break;
			}
		}
	}
	if(TI)
	{
	 TI = 0;
	 txflag = 0;
	}			
}