PWM调速+循迹__智能小车程序

合集下载

pwm调速循迹避障小车的总结与体会

pwm调速循迹避障小车的总结与体会

PWM调速循迹避障小车是一种基于单片机控制系统的智能小车,具有很高的实用价值和教学意义。

在实际应用中,PWM调速循迹避障小车可以应用于智能家居、智能物流等领域,为人们的生活和工作带来便利。

在设计和制造PWM调速循迹避障小车的过程中,我们经历了许多挑战和收获了许多成果。

在此,我将共享我对PWM调速循迹避障小车的总结与体会。

一、总结1. PWM调速原理PWM即脉冲宽度调制,是一种用来调节模拟电路的技术。

在PWM 调速循迹避障小车中,我们通过改变电机工作周期内的通电时间来控制电机的转速,从而实现小车的速度调节。

2. 循迹原理循迹是指小车根据预设的路径行驶,通常使用红外线传感器、摄像头等设备来实现。

在PWM调速循迹避障小车中,我们利用红外线传感器来检测小车周围的环境,根据检测结果来调整小车的行驶方向,实现循迹功能。

3. 避障原理避障是指小车在行驶过程中遇到障碍物时,能够及时停车或绕行,避免发生碰撞。

在PWM调速循迹避障小车中,我们通过超声波传感器等设备来检测前方障碍物的距离,根据检测结果来控制小车的行驶,实现避障功能。

4. 控制系统PWM调速循迹避障小车的控制系统由单片机、传感器、驱动电路和执行机构等部分组成。

通过单片机对传感器检测结果的分析和处理,再通过驱动电路和执行机构的协调工作,实现对小车的调速、循迹和避障控制。

二、体会1. 技术挑战在设计和制造PWM调速循迹避障小车的过程中,我们遇到了许多技术挑战,比如传感器的精度和稳定性、控制算法的优化等。

通过不断的尝试和改进,我们最终克服了这些挑战,成功实现了小车的功能。

2. 团队合作制造PWM调速循迹避障小车是一个涉及多个领域知识的复杂任务,需要团队成员之间的合作和协调。

在这个过程中,我们学会了有效的交流和合作,培养了团队精神,提高了解决问题的能力。

3. 实践意义通过制造PWM调速循迹避障小车,我们不仅加深了对相关知识的理解,还锻炼了动手能力和解决实际问题的能力。

智能循迹避障小车完整程序(亲测好使)

智能循迹避障小车完整程序(亲测好使)

智能循迹避障小车完整程序(亲测好使)/*******************************************//利用51定时器产生PWM波来调节电机速度//速度变化范围从0-100可调//使用三路做寻迹使用,哪一路检测在黑线哪一路为//高电平//没检测到黑线表示有反射对应输出低电平信号*********************************************/#include<>#define uint unsigned int#define uchar unsigned char/*电机四个接口定义*/sbit in1=P0^0;sbit in2=P0^1;sbit in3=P0^2;sbit in4=P0^3;/*计时器*/uchar j,k,i,a,A1,A2,second,minge,minshi;sbit dula=P2^6;sbit wela=P2^7;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};uchar code table2[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc,0xb9,0xde,0xf9,0xf1};void delay(uchar i){for(j=i;j>0;j--)for(k=110;k>0;k--);}void display(uchar sh_c,uchar g_c,uchar min_ge,uchar min_shi) {dula=1;P0=table[sh_c];dula=0;P0=0xff;wela=1;P0=0xfb;wela=0;delay(5);dula=1;P0=table[g_c];dula=0;P0=0xff;wela=1;P0=0xf7;wela=0;delay(5);dula=1;P0=table[min_shi];dula=0;P0=0xff;wela=1;P0=0xfe;wela=0;delay(5);dula=1;P0=table2[min_ge];dula=0;P0=0xff;wela=1;P0=0xfd;wela=0;delay(5);}/*左、中、右三路循迹传感器接口定义*/ sbit zuo=P1^0; sbit zhong=P1^1;sbit you=P1^2;/*避障接口定义*/sbit bz_zuo=P1^3;sbit bz_zhong=P1^4;sbit bz_you=P1^5;uchar count = 0;/*利用定时器0定时中断,产生PWM波*/ void Init_timer() {TH0 = (65535-10)/256;TL0 = (65535-10)%256;TMOD = 0x01;TR0 = 1;ET0 = 1;EA = 1;}/*左轮速度调节程序*/void zuolun(uchar speed){if(count <= speed) //count计数变量{in1 = 1;in2 = 0;}else{in1 = 0;in2 = 1;}}void youlun(uchar speed) //同上{if(count<= speed){in3 = 1;in4 = 0;}else{in3 = 0;in4 = 1;}}void Inline() //检测黑线信号{uchar temp;temp =P1;switch(temp){case 0x01:zuolun(0); youlun(90);break; //左侧循迹传感器压线,小车向左前修正case 0x02:zuolun(100);youlun(100);break; //中间循迹传感器压线,保持直走此处两值使电机速度保持相同case 0x04:zuolun(90); youlun(0);break; //右侧循迹传感器压线,小车向右前修正case 0x08:zuolun(90); youlun(0);break; //左侧避障传感器有信号小车右转case 0x10:zuolun(90); youlun(0);break; //中间避障传感器有信号小车左转case 0x20:zuolun(90); youlun(0);break; //右侧避障传感器有信号小车左转}/*if(zuo==1){zuolun(10);youlun(50);}else if(zhong==1){zuolun(99);youlun(99);}else if(you==1){zuolun(50);youlun(10);} */}void main() //主函数{Init_timer(); //调用函数while(1){Inline();minge=0;minshi=0;second++;if(second==60)second=0,minge++;A1=second/10;A2=second%10;if(minge==10)minge=0,minshi++;for(a=200;a>0;a--){display(A1,A2,minge,minshi);};}}void Timer0_int()interrupt 1 //定时器中断计数{TH0 = (65535-10)/256;TL0 = (65535-10)%256;count ++;if(count >= 100){count = 0;}}。

循迹小车程序(三路循迹)

循迹小车程序(三路循迹)

#include "reg51.h"typedef unsigned int uint;typedef unsigned char uchar;sbit p2_0 = P2^0; //开关sbit p2_1 = P2^1; //红外检测sbit p2_2 = P2^2;sbit p2_3 = P2^3;sbit p1_0 = P1^0; //电机驱动sbit p1_1 = P1^1;sbit p1_2 = P1^2;sbit p1_3 = P1^3;sbit pwm1 = P1^4; //pwm调速sbit pwm2 = P1^5;unsigned char timer1;/******************************************************************** ************ 函数名 : Time1Config* 函数功能 : 设置定时器* 输入 : 无* 输出 : 无********************************************************************* **********/void Time1Config(){TMOD|= 0x10; //设置定时计数器工作方式1为定时器//--定时器赋初始值,12MHZ下定时0.5ms--//TH1 = 0xFE;TL1 = 0x0C;ET1 = 1; //开启定时器1中断EA = 1;TR1 = 1; //开启定时器}/************************************************ 延时函数总共延时1ms乘以count************************************************/ void DelayX1ms(uint count){uint j;while(count--!=0){for(j=0;j<72;j++);}}/************************************************ 电机转动函数定义************************************************/ void ZhiXing( ){p1_0=0;p1_1=0;p1_2=0;p1_3=0;DelayX1ms(10);p1_0=0;p1_1=1;p1_2=0;p1_3=1;DelayX1ms(15);}void ZuoZhuan( ){pwm1=0;pwm2=0;DelayX1ms(10); p1_0=0;p1_1=1;p1_2=1;p1_3=0;DelayX1ms(20); }void YouZhuan( ){pwm1=0;pwm2=0;DelayX1ms(10);p1_0=1;p1_1=0;p1_2=0;p1_3=1;DelayX1ms(20); }void HouTui( ){p1_0=0;p1_1=0;p1_2=0;p1_3=0;DelayX1ms(6); p1_0=1;p1_1=0;p1_2=1;p1_3=0;DelayX1ms(20);}/************************************************ 主函数************************************************/ void main( ){Time1Config();while(1){if( p2_1==0 && p2_2==0 && p2_3==1){YouZhuan( );}else if(p2_1==1 && p2_2==0 && p2_3==0){ZuoZhuan( );}else{ZhiXing( );}}}/******************************************************************** ************ 函数名 : Time1* 函数功能 : 定时器1的中断函数* 输入 : 无* 输出 : 无********************************************************************* **********/void Time1(void) interrupt 3 //3 为定时器1的中断号 1 定时器0的中断号 0 外部中断1 2 外部中断2 4 串口中断{timer1++;if(timer1>100) //PWM周期为100*0.5ms{timer1=0;}if(timer1 < 85) //改变30这个值可以改变直流电机的速度{pwm1=1;pwm2=1;}else{pwm1=0;pwm2=0;}TH1 = 0xFE; //重新赋初值TL1 = 0x0C;}。

pwm调速控制小车循迹壁障c程序

pwm调速控制小车循迹壁障c程序

pwm调速控制小车循迹壁障c程序#include< reg51.h >#define uchar unsigned char#define uint unsigned int#define MOTOR_C P1 //P1口作为电机的控制口。

//#define SIGNAL P3 //P3口的低两位为循迹传感器输入口。

#define SHELVES 10 //速度总档数。

#define BACK 0xfa //后退。

#define FORWARD 0xf5 //前进。

sbit senserr = P3^2; //(右)循迹。

sbit senserl = P3^3; //(左)循迹。

sbit hwf = P3^0; //(前)红外壁障传感器入口。

sbit hwb = P3^1; //(后)红外壁障传感器入口。

sbit PWM_R = P1^0; //右电机PWM输入口。

sbit PWM_L = P1^2; //左电机PWM输入口。

sbit PWM_HR = P1^1; //(后退)右电机。

sbit PWM_HL = P1^3; //(后退)左电机。

void timer0_init( void ); //定时器0初始化函数。

void timer1_init( void ); //定时器1初始化函数。

void right( void ); //前进右转弯函数。

void left( void ); //前进左转弯函数。

void forward( void ); //前进函数。

void hright(void); //后退右转函数。

void hleft(void); //后退左转函数。

void back(void); //后退函数。

uchar percent_l = 0; //(前进)左轮占空比。

uchar percent_r = 0; //(前进)右轮占空比。

uchar percent_hl = 0; //(后退)左轮占空比。

51单片机智能小车按键调速前进程序源代码、电路原理图和电路器件表

51单片机智能小车按键调速前进程序源代码、电路原理图和电路器件表

51单片机智能小车按键调速前进程序源代码、电路原理图、电路器件表智能小车PWM调速是通过设置pwmval_left_init的和pwmval_right_init这2个变量的值来实现的,需要通过修改程序代码中这2个变量的值,这2个变量的值设置好后,在程序运行的过程中是不能修改的。

而智能小车的按键调速通过按键达到修改这2个变量的值,从而达到对智能小车调速的目的。

每按下K3按键一次,变量pwmval_left_init和pwmval_right_init减1,智能小车减速。

每按下K4按键一次,变量pwmval_left_init和pwmval_right_init加1,智能小车加速。

具体实现方法见下文的程序源代码。

下文主要提供了智能小车按键调速前进完整程序原代码、电路原理图以及电路器件表。

智能小车核心板原理图STC15W4K56S4智能小车核心板器件(BOM)表实物图060306030603PIN插针PIN2x1406030603直插LQFP7x7-48 STC15W4K56S4智能小车核心板正面STC15W4K56S4智能小车核心板背面智能小车驱动板原理图51单片机(STC15W4K56S4)智能小车驱动板器件(BOM)表实物图直插直插直插直插直插直插直插直插直插直插PIN与PIN之间的间隔2.54mm插电池盒PIN与PIN间隔2.54mm,插电机3PIN插针,针与针间隔2.54mm插舵机红色插针和黑色插针3.3V红色插针、GND黑色插针PIN红色插针和黑色插针5V PIN红色插针和黑色插针VINPIN与PIN之间的间隔2.54mm 插MQ2模块针与针间隔2.54mm插GP2Y1014AU模块针与针间隔2.54mm语音播报实验时,串口4插语音播报模块针与针间隔2.54mmIO扩展用,没有必要不要焊接针与针间隔2.54mm插DHT11模块用4PIN插针,针与针间隔2.54mm用杜邦线连接超声波模块针与针间隔2.54mm插蓝牙模块(要原厂原装的)用8PIN插针,针与针间隔2.54mm杜邦线连接红外循迹避障模块用4PIN插针,针与针间隔2.54mm用杜邦线连接测速模块针与针间隔2.54mm插5V的LCD1602液晶MPU6050不要焊接。

循迹小车三路的程序

循迹小车三路的程序
sbit IN3=P2^4;
sbit PWM2=P2^1;
sbit IN4=P2^5;
sbit ZUO=P1^0;
sbit ZHONG=P1^1//此处是传感器YOU20 管脚位声明
sbit YOU=P1^2;
int count1=0;//用于定时计数的两个全局变量位声明
int count2=0;
TL0=(65536-1000)%256;
count1++;
if(count1>=1000)//周期是1s
count1=0;
}
void time1()interrupt 3
{
TH0=(65536-1000)/256;//定时1ms
TL0=(65536-1000)%256;
count2++;
{
right_turn1(count1,500,count2,200);
}
if(ZUO==1&&YOU==1)/*左右轮均检测黑线,小车继续前进*/
/*(此处用来处理"8"字型路线交叉处小车如何前进的问题)*/
{
advance(count1,500,count2,500);
}
}
}
{
forward_turn1();
forward_turn2();
speed1(ct1,sd1);
speed2(ct2,sd2);
}
void right_turn1(int ct1,int sd1,int ct2,int sd2)//小车右转
{
forward_turn1();

循迹小车程序代码(带解释说明)

循迹小车程序代码(带解释说明)

int Left_motor_go=6; //左电机前进(IN1)int Left_motor_back=7; //左电机后退(IN2)int Right_motor_go=9; // 右电机前进(IN3)int Right_motor_back=10; // 右电机后退(IN4)const int SensorRight = 3; //右循迹红外传感器(P3.2 OUT1)const int SensorLeft = 4; //左循迹红外传感器(P3.3 OUT2)int SL; //左循迹红外传感器状态int SR; //右循迹红外传感器状态void setup(){//初始化电机驱动IO为输出方式pinMode(Left_motor_go,OUTPUT); // PIN 8 (PWM)pinMode(Left_motor_back,OUTPUT); // PIN 9 (PWM)pinMode(Right_motor_go,OUTPUT);// PIN 10 (PWM)pinMode(Right_motor_back,OUTPUT);// PIN 11 (PWM)pinMode(SensorRight, INPUT); //定义右循迹红外传感器为输入pinMode(SensorLeft, INPUT); //定义左循迹红外传感器为输入}//=======================智能小车的基本动作========================= //void run(int time) // 前进void run(){digitalWrite(Right_motor_go,HIGH); // 右电机前进digitalWrite(Right_motor_back,LOW);analogWrite(Right_motor_go,20);//PWM比例0~255调速,左右轮差异略增减analogWrite(Right_motor_back,0);digitalWrite(Left_motor_go,LOW); // 左电机前进digitalWrite(Left_motor_back,HIGH);analogWrite(Left_motor_go,0);//PWM比例0~255调速,左右轮差异略增减analogWrite(Left_motor_back,127 );//delay(time * 100); //执行时间,可以调整}//void brake(int time) //刹车,停车void brake(){digitalWrite(Right_motor_go,LOW);digitalWrite(Right_motor_back,LOW);digitalWrite(Left_motor_go,LOW);digitalWrite(Left_motor_back,LOW);//delay(time * 100);//执行时间,可以调整}//void left(int time) //左转(左轮不动,右轮前进) void left(){digitalWrite(Right_motor_go,HIGH);// 右电机前进digitalWrite(Right_motor_back,LOW);analogWrite(Right_motor_go,1);analogWrite(Right_motor_back,0);//PWM比例0~255调速digitalWrite(Left_motor_go,LOW); //左轮后退digitalWrite(Left_motor_back,LOW);analogWrite(Left_motor_go,0);analogWrite(Left_motor_back,0);//PWM比例0~255调速//delay(time * 100);//执行时间,可以调整}void right(){digitalWrite(Right_motor_go,LOW); //右电机后退digitalWrite(Right_motor_back,LOW);analogWrite(Right_motor_back,0);//PWM比例0~255调速digitalWrite(Left_motor_go,LOW);//左电机前进digitalWrite(Left_motor_back,HIGH);analogWrite(Left_motor_go,0);analogWrite(Left_motor_back,127);//delay(time * 100);//执行时间,可以调整}void back(int time){digitalWrite(Right_motor_go,LOW); //右轮后退digitalWrite(Right_motor_back,HIGH);analogWrite(Right_motor_go,0);analogWrite(Right_motor_back,60);//PWM比例0~255调速digitalWrite(Left_motor_go,HIGH); //左轮后退digitalWrite(Left_motor_back,LOW);analogWrite(Left_motor_go,60);analogWrite(Left_motor_back,0);//PWM比例0~255调速delay(time * 100); //执行时间,可以调整}//==========================================================void loop(){//有信号为LOW 没有信号为HIGH 检测到黑线输出高检测到白色区域输出低SR = digitalRead(SensorRight);//有信号表明在白色区域,车子底板上L1亮;没信号表明压在黑线上,车子底板上L1灭SL = digitalRead(SensorLeft);//有信号表明在白色区域,车子底板上L2亮;没信号表明压在黑线上,车子底板上L2灭if (SL == LOW&&SR==LOW)run(); //调用前进函数else if (SL == HIGH & SR == LOW)// 左循迹红外传感器,检测到信号,车子向右偏离轨道,向左转left();else if (SR == HIGH & SL == LOW) // 右循迹红外传感器,检测到信号,车子向左偏离轨道,向右转right();else // 都是黑色, 停止brake();}。

课程设计报告循迹小车的设计

课程设计报告循迹小车的设计

循迹小车的设计摘要智能循迹是基于自动引导机器人系统,用以实现小车自动识别路线,以及选择正确的路线。

智能循迹小车是一个运用传感器、单片机、电机驱动及自动控制等技术来实现按照预先设定的模式下,不受人为管理时能够自动实现循迹导航的高新科技。

该技术已经应用于汽车制造业、仓储业,食品加工业等多个行业。

本设计是基于单片机控制的电动小车,小车能够识别地上黑色轨迹线,实现循迹行走,包括电源模块、单片机模块、循迹模块、电机驱动模块。

其中单片机模块作为控制器模块以STC89C52单片机为控制核心,用单片机产生PWM波,控制小车速度。

利用红外光电传感器RPR220型光电对管对路面黑色轨迹进行检测,并将路面检测信号反馈给单片机。

单片机对采集到的信号进行分析判断,及时控制由芯片L298N驱动的电机以调整小车转向,从而使小车能够沿着黑色轨迹自动行驶,实现小车自动寻迹的目的。

在此基础利用E18-D80NK 3-80cm可调红外避障传感器进行小车的避障扩展,还选用PT2262/PT2272组成的无线遥控模块对小车进行无线遥控。

本设计不仅给出了硬件设计流程、完整的硬件电路图和控制程序,还用PROTEUS实现了小车电机控制仿真。

关键词:自动循迹;单片机;Proteus仿真Design on Automated Guided VehicleAbstractIntelligent tracking is based on automatic guided robot system, used to make the car line, and choosing the right route. Automated Guided Vehicle is a use of sensor, microcontroller, motor drive and automatic control technology to achieve according to the preset mode, without human management can achieve automatic tracking navigation technology. This technology has been applied in the automobile manufacturing industry, warehousing industry, food processing industry and other industries.The design is based on SCM control electric trolley, trolley can be identified on the black line, achieve the tracking of walking, including driving module power supply module, microcontroller module, tracking module, motor. The MCU module as the controller module with STC89C52 as control core, using microcontroller PWM wave, control car speed. The tube is used for tracing the use of infrared photoelectric sensor RPR220 type photoelectric, and road test signals back to the scm. Analysis and judgment of the collected signal microcontroller, timely control of motor driven by the chip L298N to adjust the car steering, so that the car can travel along the black path automatically, realize the purpose of automatic tracing. Based on E18-D80NK 3-80cm tunable infrared sensors for obstacle avoidance of car obstacle avoidance, also use wireless remote control module composed of PT2262/PT2272 for wireless remote control car.This design not only gives the hardware circuit diagram and program control hardware design flow, complete, we also use PROTEUS to achieve the car motor control simulation.Key words:tracking,microcontroller, Proteus simulation西华大学课程设计目录摘要 (Ⅰ)ABSTRACT (Ⅱ)1 绪论 (1)1.1智能循迹小车概述 (1)1.1.1循迹小车的发展历程回顾 (1)1.1.2 智能循迹分类 (2)1.1.3 智能循迹小车的应用 (3)1.2 智能循迹小车研究中的关键技术 (4)2 自动循迹小车系统方案设计 (5)2.1 自动循迹小车基本原理 (5)2.2 总体方案设计 (5)2.2.1 系统总体方案的设计 (5)2.2.2 方案选择与论证 (5)3 硬件电路的设计 (8)3.1 自动循迹小车硬件设计.................................. 错误!未定义书签。

循迹小车程序

循迹小车程序

附录程序目录一、前言------------------------------------------------------------二、小车功能------------------------------------------------------三、元器件选择--------------------------------------------------四、I/O分配及硬件连接简图---------------------------------五、相关模块、算法---------------------------------------------六、系统框图------------------------------------------------------七、调试过程------------------------------------------------------八、小车图片资料---------------------------------------------------九、讲座所感------------------------------------------------------十、实习总结------------------------------------------------------一、前言感谢生产实习能给我们这次实现自己想法的机会,虽然实验条件异常简陋、资金投入非常有限,总体感觉我的队友们灰常灰常给力啊,我感觉我是抱到大腿了--王威,夏青、峰哥,团队气氛非常好,大家一起讨论,一起分工研究模块,最后一起解决问题调试程序,而且是不同的组合在不同阶段解决了不同的问题,大家精诚合作,各显身手,在奋战中给大三学年画上了圆满的句号。

之前我们本来商量是不是可以拿往年电子设计大赛的题目过来做,如果难度太大就算只实现一部分功能也算是成功完成了,结果研究一天后发现电子设计大赛的题目需要很长时间的知识积累啊,基本上都是准备一个月以上然后开工的,后来王威提议要不我们做个小车吧,超声波测距实现自动物体追踪,控制核心采用单片机,传感器采用广泛用于避障与测距的超声波传感器,前进与后退用普通伺服电机与电机驱动模块实现。

51单片机产生PWM控制小车速度的两种方法

51单片机产生PWM控制小车速度的两种方法

51单片机产生PWM控制小车速度的两种方法首先你的先知道什么是PWM。

PWM是一种脉宽调制技术。

简单的说就是在一个周期内高电平所占用的时间,通过改变脉冲的周期可以调频,改变脉冲的宽度或占空比可以调节驱动上的电压。

将产生的PWM信号接到L298N的ENA和ENB端调节不同的占空比从而调节速度第一种方法用单片机的定时器模拟出PWM。

假如你用定时器延时100ms,在50ms之前某一个引脚为低电平,50ms之后该引脚为高电平,这样高电平占用的时间为1/2,此时该引脚就会产生50%的占空比信号。

程序如下:#include<reg52.h>unsigned chartimer1;sbit PWM=P1^1;void system_Ini(){TMOD|= 0x11;TH1 = 0xfe; //11.0592TL1 = 0x33;TR1 =1;IE=0x8A;}main(){ system_Ini() ;定时器初始化while(1){ if(timer1>100) timer1=0;if(timer1<=30) pwm=0;//产生30%的占空比else PWM=1;}}另一种方法就是利用简单的延时产生PWM方波信号#include<reg52.h>unsigned char count=0;sbit PWM_1=PI^1;//利用P1^1产生PWMvoid mian(){while(1)for(count=0;count<=100;count++) //让单片机记100个数{If(count<=50){ PWM_1=1;}//前一半时间为高电平elsePWM_1=0//后一半时间为低电平这样就产生了50%的占空比}PWM不仅能够控制小车速度还可以控制小灯的亮灭程度,朋友们可以去试试。

水平有限,如果觉得对您有用请您推荐您的朋友关注我们,还请大神们轻喷。

智能小车的循迹避障行驶说明书

智能小车的循迹避障行驶说明书

智能小车的循迹避障行驶目录摘要 (III)Abstract (IV)第一章绪论 (1)1.1 课题背景 (1)1.2 研究目的及意义 (1)1.3 本设计完成的工作 (2)第二章总体设计方案 (3)2.1 方案选择及论证 (4)4446662.2 最终方案 (7)第三章硬件设计 (8)3.1 主控器STC89C52 (8)3.2 单片机复位电路设计 (10)3.3 单片机时钟电路设计 (10)3.4 避障模块 (10)3.5 电源设计 (11)3.6 电机驱动模块 (12)3.7 红外循迹模块 (13)3.8 小车车体总体设计 (15)第四章软件设计 (16)4.1 主程序流程图 (16)第五章系统的安装与调试 (18)5.1 系统的安装 (18)5.2 电路的调试 (19) (20)205.3 测试结果与分析 (20)结论 (21)参考文献 (22)致谢........................................................ 错误!未定义书签。

附录1 整机电路原理图.. (22)附录2 部分源程序 (23)智能小车的循迹避障行驶摘要在现代化的生产生活中,智能机器人已经渐渐普及到国防、工业、交通、生活等各个领域。

为了使生产更加有效率更加安全,使生活更加方便、轻松,智能机器人起到了越来越重要的作用。

智能小车属于智能机器人的一种,同样能给生产生活带来极大的便利。

它能够自己判断路面情况,并将各种信息反馈给单片机。

所用到的学科有自动控制原理、传感器技术、计算机和信息技术等多门学科。

智能车能够在一定程度上解放人的双手、减小工作强度从而改善人们的生活,提高生产的质量和效率。

能够自动循迹和避绕障碍物行驶则是智能小车需要的最基本的功能。

小车之所以能够自动避开障碍物并进行循迹是因为它可以感测引导线和行进路上的障碍物,因此这里采用超声波测距模块和红外传感器来实现这些功能。

本文先介绍了选题的背景及发展前景,描述了智能车在生产和生活中发展和应用的情况;接着对硬件部分所用器件的原理和特点进行了介绍;然后对软件设计和机械部分进行说明;在文章的最后就整个过程的体会及智能机器人的发展进行了总结和展望。

智能循迹避障小车方案设计书

智能循迹避障小车方案设计书

智能循迹避障小车摘要:本设计是一种基于单片机控制的简易自动寻迹小车系统,包括小车系统构成软硬件设计方法。

小车以STC89C52单片机为控制核心, 用L298N驱动小车的两个直流电动机,用单片机产生PWM波,控制小车速度。

利用红外对管对路面黑色轨迹和障碍物进行检测,并将路面检测信号反馈给单片机。

单片机对采集到的信号予以分析判断,及时控制驱动直流电机以调整小车转向,从而使小车能够避开障碍物沿着黑色轨迹自动行驶,实现小车自动寻迹的目的。

关键词:智能小车;STC89C52单片机;L298N;红外对管Intelligent tracking and obstacle-avoid carLi Bo,QiXiao-long(Electrical Engineering College, Longdong University, Qingyang745000, Gansu, China) Abstract:This design is a kind of automatic tracing based on single-chip microputer control system used, including trolley systems hardware and software design method. Car STC89C52 single chip microputer to control the core, L298N driving two DC motors for car, monolithic integrated circuit PWM wave, controlling car speed. Using infra-red tube black track and detect obstacles on pavement and pavement detection signal back to the MCU. MCU on the collected signals analysis, control drive DC motors to adjust the car turning in a timely manner, so as to enable the car to avoid the obstacles along the black path automatically, achieve the purpose of car automatic tracing.Keywords: Smart Car; STC89C52 MCU; L298N;Infrared Emitting Diode1.引言32.方案设计与论证32.1 主控系统32.2 电机驱动模块42.3 循迹模块52.4 避障模块62.5 机械系统72.6电源模块73.硬件设计73.1总体设计73.2驱动电路(参考文献[4])83.3信号检测模块93.4主控电路104.软件设计114.2电机驱动程序114.3循迹模块12P0_0=!P0_0;13P0_1=!P0_1;144.4避障模块145.制作安装与调试185.1 PCB的设计制作与安装18 结束语18参考文献191.引言随着机械自动化的不断发展,人们在生活的各个方面都希望能够利用自动化的操作来提高工作效率,使生产发展能够得到不断的提高。

51单片机智能小车PWM调速前进程序源代码、电路原理图和器件表

51单片机智能小车PWM调速前进程序源代码、电路原理图和器件表

51单片机智能小车PWM调速前进程序源代码、电路原理图、电路器件表从控制电路角度划分,智能小车电路板分为核心板和驱动板。

核心板上的处理器的芯片型号是:STC15W4K56S4,这是一款51单片机。

驱动板上有电源电路、电机驱动电路以及一些功能模块接口。

智能小车前进只要控制智能小车四个轮子向前转动就可以了。

智能小车四个轮子由四个直流减速电机驱动。

直流减速电机驱动芯片采用L293D,一片电机驱动芯片L293D可以驱动两个直流减速电机,智能小车用到4个直流减速电机,需要用到两片L293D电机驱动芯片。

但有时候我们需要控制智能小车的速度,不希望智能小车全速前进。

比如在“智能小车循迹实验”中,如果智能小车速度过快,来不及反应做出方向的调整,智能小车会很容易跑离轨迹,这样就需要调整控制智能小车的速度了。

那么怎么样实现智能小车前进速度的调节呢?调节智能小车的速度,实际上是调节电机的运转速度,PWM调速是目前电机的主流调速方式。

智能小车采用脉宽调制(PWM)的办法来控制电机的转速,从而控制智能小车的速度。

在此种情况下,电池电源并非连续地向直流电机供电,而是在一个特定的频率下为直流电机提供电能。

不同占空比的方波信号,调节对直流电机的通断电,能起到对直流电机调速作用。

这是因为电机实际上是一个大电感,它有阻碍输入电流和电压突变的能力,因此脉冲输入信号被平均分配到作用时间上。

这样,改变L293D使能端EN1和EN2上输入方波的占空比就能改变加在电机两端的电压大小,从而改变了直流电机转速。

智能小车PWM调速前进程序如下:首先,定义了2个变量,这2个变量用于设置智能小车的速度。

unsigned char pwmval_left_init=6; //调节此值可以调节小车的速度。

unsigned char pwmval_right_init=6; //调节此值可以调节小车的速度。

通过以下函数初始化定时器0,每1毫秒中断一次。

void Timer0_Init(void) //定时器0初始化{TMOD=0x01;TH0=0xf8;TL0=0xcd;TR0=1;ET0=1;EA=1;}下面我们看定时器0的中断处理函数。

智能寻迹避障小车电机调速控制程序设计分析

智能寻迹避障小车电机调速控制程序设计分析

1.1.3 单片机的定时器原理
在工业检测、控制中,很多场合都要用到计 数或者定时功能。例如对外部脉冲进行计数、产 生精确的定时时间、作串行口的波特率发声器等 ,AT89C51单片机内部有两个可编程的定时器/ 计数器,以满足这方面的需要。它们具有两种工 作模式(计数器模式、定时器模式)和四种工作 方式(方式0、方式1、方式2、方式3),其控制 字均在相应的特殊功能寄存器(SFR)中,通过 对它的SFR的编程,可以方便的选择工作模数和 工作方式。
1.1.3 单片机的定时器原理
当设置为计数工作模式时,通过引脚T0( P3.4)和T1(P3.5)对外部脉冲信号计数,当输 入脉冲信号产生由1到0的下降沿时,定时器的 值加1. 不管时定时还是计数工作模式,定时器T0或 T1在对内部时钟或外部事件计数时,都不占用 CUP时间,除非定时器/计数器溢出,才可能中 断CPU的当前操作,计数器的计满溢出信号就 是定时/计数器的输出,该信号使TCON的某位 (TF0或TF1位)置1,作为定时器/计数器的溢 出中断标志,定时器/计数器的内部结构框图 如图3所示。
1.1.3 单片机的定时器原理
7 0
T1
P3.5(T1)
7 0 7 0
T0
P3.4(T0)
7 0
TH1
TL1
TH0
TL0
微 处 理 器
内部总线
TCON
TMOD
图3 定时器/计数器结构框图
1.1.3 单片机的定时器原理
1、定时/计数器有关的特殊功能寄存器 (1)计数寄存器TH和TL 定时器/计数器T/C0和T/C1都是16位寄存器 ,由TH高8位和TL低8位构成,在特殊功能寄存器 (sfr)中,对应T/C0为TH0和TL0,对应T/C1为TH1 和TL1,定时器/计数器T/C0和T/C1的初值分别通 过TH0/TL0和TH1/TL1来设置,加法计数器是计满 溢出时才申请中断,所以在给定时器/计数器赋初 值时,不能直接输入所需的计数值, 而应输入的 是计数器计数的最大值与这一计数值的差值, 设 最大值为 M, 计数值为N, 初值为X, 则X的计算 方法如下:

智能循迹小车详细源代码程序(MSP430,PID)

智能循迹小车详细源代码程序(MSP430,PID)
80 }
81 LEFTOUT=Period/100*speed;
82 }
83 void MotorRight(int speed,int direction)
84 {
85 if(speed>max_speed)speed=max_speed;
86
72 {
73 EnableLeftNeg;
74 UnenableLeftPos;
75 }
76 else if(direction==foreward)//正转
77 {
78 EnableLeftPos;
79 UnenableLeftNeg;
17 #define LEFTOUT TACCR1
18 #define RIGHTOUT TACCR2
19 #define SensorIn P5IN
20 #define F 5000//5000hz
21 #define Period (8000000/F)
64 {
65 LEFTOUT=0;
66 RIGHTOUT=0;
67 }
68 void MotorLeft(int speed,int direction)
69 {
70 if(speed>max_speed)speed=max_speed;
71 if(direction==backward)//反转
183 TACCTL2|=OUTMOD_7;//
184 LEFTOUT=0;
185 RIGHTOUT=0;
186 }
187
188 float abs(float a)
189 {

基于STM32智能循迹避障小车(设计报告)

基于STM32智能循迹避障小车(设计报告)

基于STM32智能循迹避障小车(设计报告)具有丰富的外设和存储器资源,能够满足本设计的需求。

在硬件方面,采用了红外对管和超声波传感器来检测道路上的轨迹和障碍物,并通过PWM调速来控制电动小车的速度。

在软件方面,采用MDK(keil)软件进行编程,实现对小车的自动循迹和避障,快慢速行驶,以及自动停车等功能。

设计方案本设计方案主要分为硬件设计和软件设计两个部分。

硬件设计部分主要包括电路原理图的设计和PCB的制作。

在电路原理图的设计中,需要将stm32芯片、红外对管、超声波传感器、电机驱动模块等元器件进行连接。

在PCB的制作中,需要将电路原理图转化为PCB布局图,并进行钻孔、贴片等工艺流程,最终得到完整的电路板。

软件设计部分主要包括程序的编写和调试。

在程序的编写中,需要先进行芯片的初始化设置,然后分别编写循迹、避障、速度控制等功能的代码,并将其整合到主函数中。

在调试过程中,需要通过串口调试工具来进行数据的监测和分析,以确保程序的正确性和稳定性。

实验结果经过多次实验测试,本设计方案实现了对电动小车的自动循迹和避障,快慢速行驶,以及自动停车等功能。

在循迹和避障方面,红外对管和超声波传感器的检测精度较高,能够准确地控制小车的运动方向和速度;在速度控制方面,PWM调速的方式能够实现小车的快慢速行驶,且速度控制精度较高;在自动停车方面,通过超声波传感器检测到障碍物后,能够自动停车,确保了小车的安全性。

结论本设计方案采用stm32为控制核心,利用红外对管和超声波传感器实现对电动小车的自动循迹和避障,快慢速行驶,以及自动停车等功能。

在硬件方面,电路结构简单,可靠性能高;在软件方面,采用MDK(keil)软件进行编程,实现了程序的稳定性和正确性。

实验测试结果表明,本设计方案能够满足题目的要求,具有一定的实用性和推广价值。

内核采用ARM32位Cortex-M3 CPU,最高工作频率为72MHz,1.25DMIPS/MHz,具有单周期乘法和硬件除法功能。

智能循迹小车程序代码(4路)

智能循迹小车程序代码(4路)

智能循迹小车程序代码(4路)/************************************************************** **************硬件连接P1_4接驱动模块ENA使能端输入PWM信号调节速度P1_5接驱动模块ENB使能端输入PWM信号调节速度P1_0 P1_1接IN1 IN2 当 P1_0=1,P1_1=0; 时左电机正转驱动蓝色输出端OUT1 OUT2接左电机P1_0 P1_1接IN1 IN2 当 P1_0=0,P1_1=1; 时左电机反转P1_2 P1_3接IN3 IN4 当 P1_2=1,P1_3=0; 时右电机正转驱动蓝色输出端OUT3 OUT4接右电机P1_2 P1_3接IN3 IN4 当 P1_2=0,P1_3=1; 时右电机反转P1_0接四路寻迹模块接口第一路输出信号即中控板上面标记为OUT1P1_1接四路寻迹模块接口第二路输出信号即中控板上面标记为OUT2P1_2接四路寻迹模块接口第三路输出信号即中控板上面标记为OUT3P1_3接四路寻迹模块接口第四路输出信号即中控板上面标记为OUT4八路寻迹传感器有信号(白线为0 没有信号黑线为1*************************************************************** *************/#include#define Right_moto_pwm P1_4 //接驱动模块ENA使能端输入PWM信号调节速度#define Left_moto_pwm P1_5 //接驱动模块ENB使能端输入PWM信号调节速度#define Left_1_led P2_0 //四路寻迹模块接口第一路#define Left_2_led P2_1 //四路寻迹模块接口第二路#define Right_1_led P2_2 //四路寻迹模块接口第三路#define Right_2_led P2_3 //四路寻迹模块接口第四路#define Left_moto_go {P1_0=0,P1_1=1;} //左电机前进#define Left_moto_back {P1_0=1,P1_1=0;} //左电机后退#define Left_moto_stop {P1_0=1,P1_1=1;} //左电机停转#define Right_moto_go {P1_2=0,P1_3=1;} //右电机前转#define Right_moto_back {P1_2=1,P1_3=0;} //右电机后退#define Right_moto_stop {P1_2=1,P1_3=1;} //右电机停转#define uchar unsigned char#define uint unsigned intuchar pwm_val_left =0;uchar push_val_left =0; //左电机占空比N/10uchar pwm_val_right =0;uchar push_val_right=0; //右电机占空比N/10bit Right_moto_stp=1;bit Left_moto_stp =1;/************************************************************** **********/void run(void) //前进函数{push_val_left =13; //PWM 调节参数1-20 1为最慢20是最快改这个值可以改变其速度push_val_right =15; //PWM 调节参数1-20 1为最慢20是最快改这个值可以改变其速度Left_moto_go ; //左电机前进Right_moto_go ; //右电机前进}/************************************************************** **********/void left(void) //左转函数{push_val_left =8;push_val_right =9;Right_moto_go; //右电机继续Left_moto_stop; //左电机停走}/************************************************************** **********/void right(void) //右转函数{push_val_left =8;push_val_right =9;Right_moto_stop; //右电机停走Left_moto_go; //左电机继续}void Delayms(uint x){uchar i;while(x--)for(i=0;i<120;i++);}void stop(void){Right_moto_stop; //右电机停走Left_moto_stop; //左电机停走Delayms(3000);run();Delayms(100);}/*************************PWM调制电机转速********************************/void pwm_out_left_moto(void) //左电机调速,调节push_val_left的值改变电机转速,占空比{if(Left_moto_stp){if(pwm_val_left<=push_val_left)Left_moto_pwm=1;elseLeft_moto_pwm=0; if(pwm_val_left>=20)pwm_val_left=0;}elseLeft_moto_pwm=0;}void pwm_out_right_moto(void) //右电机调速,调节push_val_left的值改变电机转速,占空比{if(Right_moto_stp){if(pwm_val_right<=push_val_right)Right_moto_pwm=1;elseRight_moto_pwm=0;if(pwm_val_right>=20)pwm_val_right=0;}elseRight_moto_pwm=0;}/***************************************************/void xunji(){switch(P2&0x0f){case 0x00: // 全部没有压线直走run(); break;case 0x01: // 右压线左转left(); break;case 0x02: // 右压线左转left(); break;case 0x04: // 左压线转右right(); break; case 0x08: // 左压线右转right();break;case 0x0f:stop();break;default:run(); break;}}/***********TIMER0中断服务子函数产生PWM信号**********/ void timer0()interrupt 1 using 2{TH0=0XF8; //2Ms定时TL0=0X30;pwm_val_left++;pwm_val_right++;pwm_out_left_moto();pwm_out_right_moto();}/***************************************************/void main(void){TMOD=0X01;TH0= 0XF8; //2ms定时TL0= 0X30;TR0= 1;ET0= 1;EA = 1;while(1) /*无限循环*/ {xunji(); }}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

//T0产生双路PWM信号,L298N为直流电机调速,接L298N时相应的管脚上最好接上10K 的上拉电阻。

/* 晶振采用12M,产生的PWM的频率约为100Hz */#include<reg51.h>#include<math.h>#define uchar unsigned char#define uint unsigned intsbit en1=P3^4; /* L298的Enable A */sbit en2=P3^5; /* L298的Enable B */sbit s1=P1^0; /* L298的Input 1 */sbit s2=P1^1; /* L298的Input 2 */sbit s3=P1^3; /* L298的Input 3 */sbit s4=P1^2; /* L298的Input 4 */sbit R=P2^0;sbit C=P2^1;sbit L=P2^2;sbit key=P1^4;uchar t=0; /* 中断计数器*/uchar m1=0; /* 电机1速度值*/uchar m2=0; /* 电机2速度值*/uchar tmp1,tmp2; /* 电机当前速度值*//* 电机控制函数index-电机号(1,2); speed-电机速度(0-100) */void motor(uchar index, char speed){if(speed<=100){if(index==1) /* 电机1的处理*/{m1=abs(speed); /* 取速度的绝对值*/s1=1;s2=0;}if(index==2) /* 电机2的处理*/{m2=abs(speed); /* 电机2的速度控制*/s3=1;s4=0;}}}void Back(void){s1=0;s2=1;s3=1;s4=0;}void GO(void){s1=1;s2=0;s3=1;s4=0;}void TL(void){s1=1;s2=0;s3=0;s4=1;}void TR(void){s1=0;s2=1;s3=1;s4=0;}void STOP(void){s1=1;s2=1;s3=1;s4=1;}/*void delay(uint j) /* 简易延时函数*/ {for(j;j>0;j--);} */void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void main(){uchar i=0,j=0;TMOD=0x02; /* 设定T0的工作模式为2 ,8位自动重置定时器,每过几个机器周期,计数器加一*/TH0=0x9B; /* 装入定时器的初值,计数100次溢出*/TL0=0x9B; /*装入时间常数*/EA=1; /* 开中断*/ET0=1; /* 定时器0允许中断*/TR0=1; /* 启动定时器0 */while(1){if(key==1){/* 电机实际控制演示*/if(i<=100) // 正转加速{motor(1,i);motor(2,i);delay(5000);i++;}else{GO();}}else{EA=0;while(1){if((L|C|R)==0)STOP();if(L&R)GO();if(L==0){while(C){TL();}}if(R==0){while(C){TR();}}}}}}void timer0() interrupt 1 /* T0中断服务程序*/{if(t==0) /* 1个PWM周期完成后才会接受新数值*/{ tmp1=m1;tmp2=m2;}if(t<tmp1) en1=1; else en1=0; /* 产生电机1的PWM信号*/ if(t<tmp2) en2=1; else en2=0; /* 产生电机2的PWM信号*/ t++;if(t>=100) t=0; /* 1个PWM信号由100次中断产生*/}#include<intrins.h>#include<AT89X52.h>/****************************************************************************** **\** 宏定义区**\****************************************************************************** **//*------------------------------- LCD模块------------------------------------*/#defineLCD_RW P2_6 //读写控制端#defineLCD_RS P2_7 //数据命令选择端#defineLCD_E P2_5 //执行使能端#defineLCD_Data P1 //P1口#defineWrite 0x00 //低电平写入#defineRead 0x01 //高电平读出#defineData 0x01 //高电平选择数据#defineCmd 0x00 //低电平选择命令#defineEnable 0x00 //跃变到低电平时执行命令#defineDisable 0x01#defineTrue 0x01#defineFalse 0x00#defineLCD_Init 0x38 //初始化模式#defineLCD_DispCtr 0x0C //开显示及光标设置#defineLCD_CloseCtr 0x08 //关显示#defineLCD_CLS 0x01 //清屏幕#defineLCD_EnterSet 0x06 //显示光标#defineBusy P1_7 //忙信号/*-------------------------- 测速/测距/测时模块-------------------------------*/#defineCircleLength 0.132 //小车转一轮的长度为.132m/*-------------------------------- 控速模块-----------------------------------*/#defineP03 P0_3 //后电机#defineP04 P0_4 //后电机#defineP01 P0_1 //前电机#defineP02 P0_2 //前电机#defineP31 P0_5 //控制液晶背光#defineP33 P3_3/*------------------------------ 菜单选择模块---------------------------------*/#defineLine 0x00 //0代表直线模式#defineCurve 0x01 //1代表S型模式#defineNormal 0x00 //0 代表正常速度#defineLow 0x01 //1 代表低速#defineHigh 0x02 //2 代表高速/****************************************************************************** ***\** 全局函数声明区**\****************************************************************************** ***//*------------------------------- LCD模块-------------------------------------*/voidLCDInit(void); //LCD初始化voidSetWriteCmd(void); //设置写命令模式voidSetReadCmd(void); //设置读命令模式voidSetWriteData(void); //设置写数据模式voidWriteCmd(charcmd); //写命令voidWriteData(charddata); //写数据voidExecuteCmd(void); //执行命令voidSetXY(charx,chary); //定位显示地址voidDisplaySingleChar(charx,chary,charcchar); //显示单个字符voidDisplayString(charx,chary,char*str); //显示一段字符串voidDelay(unsignedinttime); //延时主程序voidDelayUs(unsignedinttime); //延时子程序bit IsBusy(void); //判断忙标志函数voidDisplayTime(void); //显示时间voidDisplayAVGSpeed(void); //显示平均速度voidDisplayDistance(void); //显示路程/*-------------------------- 测速/测距/测时模块-------------------------------*/voidINTInit(void); //所有中断初始化voidSpeedINT(void); //测速中断voidComputeTime(void);voidComputeSpeedANDDistance(void); //计算速度和距离/*-------------------------------- 控速模块-----------------------------------*/voidCtrSpeedINT(void); //控速中断voidTime0INT(void);voidTime1INT(void); //控速单位时间中断voidClock0_Init(void); //时钟中断初始化voidClock1_Init(void); //时钟中断初始化voidCtrSpeed(void);/****************************************************************************** **\** 全局变量区**\****************************************************************************** **/float SpeedCount=0; //测速计数脉冲float Speed=0.0;float Distance=0.0;char Time1INTCount=0; //T1中断时间计时float PassTime=0.00; //小车行走的时间short IsT0INT=1;bit IsT1INT; //判断T1是否已经响应中断short IsT0INT2=1;char Thx[5]={0xf4,0xf4,0xc5,0xf4,0xff}; //3ms,3ms,15ms,3ms char Tlx[5]={0x48,0x48,0x68,0x48,0xff};char Thx0=0xd8;char Tlx0=0xf0;char Thx1=0xb1; //20mschar Tlx1=0xe0;short Round=0;short Back=0;short Back0=0;bit Backid;bit Stop=0;char Area0=0;char Area1=0; //区域变量char LowSpeedArea1StartTime;char LowSpeedArea1EndTime;char HighSpeedAreaEndTime;char LowSpeedArea2EndTime;char LowSpeedArea1PassTime=0; //第一个低速区通过时间char HighSpeedAreaPassTime=0; //高速区通过时间char LowSpeedArea2PassTime=0; //第二个低速区通过时间char ReadyToGo=4; //倒计时char flag;bit Roundid=0;char Nocurve=0;char ChangeFlag;char Mode;bit Running;bit SelectedAll; //模式和速度是否选择完毕标志bit IsSelectingMode; //模式选择标志bit IsSelectingSpeed; //速度选择标志bit ModeSelected; //已经被选择的模式标志char SelectedMode=10; //模式选择是否完毕标志bit Next; //Next键标志bit SpeedSelected; //已经被选中的速度方案标志char SelectedSpeed; //速度选择是否完毕标志bit ChoosingDisplay; //人工选择菜单开始标志bit SelectedShow; //显示选择标志bit SelectedReturn; //返回选择标志bit Selected; //确定/返回键选择标志bit ReturnSelection; //返回键启用标志bit A VGSpeedShow; //平均速度显示标志bit TotalDistanceShow; //总路程显示标志bit ReturnMain; //返回主菜单标志bit AutoDisplay; //自动显示标志bit GoToChoosingDisplay; //人工选择标志bit AutoMode=0;char PassLineID=0;char PassLine=0;float PrepareDistance;float FirstDistance;float SecondDistance;float ThirdDistance;int FirstHigh;int SecondHigh;int ThirdHigh;float Rate=1.25; //5ms时的速度float Count=4; //时间的倍数/****************************************************************************** **\** 全局函数实现区**\****************************************************************************** **//*-------------------------------- 主函数------------------------------------*/voidmain(){P01=0;P02=0;P03=0;P04=0;P31=1; //单片机复位,背光开Delay(40); //延时等待LCD启动LCDInit(); //初始化LCDDisplayString(0x0,0," Starting... ");DisplayString(0x0,1,"DesignedBy202");Delay(300);WriteCmd(LCD_CLS);EA=1; //开总中断EX0=1; //开INT0中断IT0=1; //INTO边沿触发EX1=1; //开INT1中断IT1=1; //INT1边沿触发SelectedAll=False; //开始模式和速度选择/*------------------------------ 模式选择---------------------------------*/DisplayString(0x0,0,"ChooseTheMode");DisplayString(0x0,1,"youwant. ");Delay(50);WriteCmd(LCD_CLS);IsSelectingMode=True;while(1){WriteCmd(LCD_CLS);DisplayString(0x0,0," LineMode ");DisplayString(0x0,1,"Next Yes");Delay(300); //延时消除抖动while(1) //不断检测中断,直到按确定键或是NEXT键{if(Next==True) //如果按Next键则直接跳出break;if(ModeSelected==True) //如果按确定键则设置模式为Line并跳出{SelectedMode=Line;break;} //如果什么键都没有按下,那么一直显示等待}if(ModeSelected==True) //按下了确定键,退出模式选择{IsSelectingMode=False;break;}if(Next==True) //按下了Next键,显示下一个菜单项{Next=False;WriteCmd(LCD_CLS);DisplayString(0x0,0," CurveMode ");DisplayString(0x0,1,"Next Yes");Delay(300); //延时消除抖动while(1) //不断检测中断,直到按确定键或是Next键{if(Next==True) //如果再一次按下Next键,则跳出break;if(ModeSelected==True) //如果按下确定键,则设置模式为Curve,并跳出{SelectedMode=Curve;break;}}}if(ModeSelected==True) //按下了确定键,退出模式选择{IsSelectingMode=False;break;}if(Next==True) //再一次按下了Next键,则循环模式选择{Next=False;WriteCmd(LCD_CLS);DisplayString(0x0,0," AutoMode ");DisplayString(0x0,1,"Next Yes");Delay(300); //延时消除抖动while(1){if(Next==True)break;if(ModeSelected==True){AutoMode=1;break;}}}if(ModeSelected==True){IsSelectingMode=False;break;}if(Next==True){Next=False;continue;}}Delay(50);WriteCmd(LCD_CLS);/*------------------------------ 速度选择---------------------------------*/ if(SelectedMode==Line&&AutoMode==0){DisplayString(0x0,0," NowChoosea ");DisplayString(0x0,1," kindofSpeed");Delay(50);WriteCmd(LCD_CLS);IsSelectingSpeed=True;while(1){WriteCmd(LCD_CLS);DisplayString(0x0,0,"NormalSpeed ");DisplayString(0x0,1,"Next Yes");Delay(300); //延时消除抖动while(1){if(Next==True) //如果按Next键则直接跳出break;if(SpeedSelected==True) //如果按确定键则设置速度为Normal并跳出{Thx[0]=0xec;Tlx[0]=0x78; //5msThx[1]=0xf0;Tlx[1]=0x60; //4msThx[2]=0x8a;Tlx[2]=0xd0; //30msThx[3]=0xf4;Tlx[3]=0x48; //3msSelectedSpeed=Normal;break;} //如果什么键都没有按下,那么一直显示等待}if(SpeedSelected==True) //按下了确定键,退出速度选择{IsSelectingSpeed=False;break;}if(Next==True){Next=False;WriteCmd(LCD_CLS);DisplayString(0x0,0," Low Speed ");DisplayString(0x0,1,"Next Yes");Delay(300); //延时消除抖动while(1){if(Next==True) //如果再一次按下Next键,则跳出break;if(SpeedSelected==True) //如果按下确定键,则设置速度为Low,并跳出{SelectedSpeed=Low; //这里没有速度设置,因为默认速度就是Lowbreak;}}}if(SpeedSelected==True) //按下了确定键,退出速度选择{IsSelectingSpeed=False;break;}if(Next==True){Next=False;WriteCmd(LCD_CLS);DisplayString(0x0,0," High Speed ");DisplayString(0x0,1,"Next Yes");Delay(300); //延时消除抖动while(1){if(Next==True) //如果再一次按下Next键,则跳出break;if(SpeedSelected==True) //如果按下确定键,则设置速度为High,并跳出{Thx[0]=0xe0;Tlx[0]=0xc0;//8msThx[1]=0xe0;Tlx[1]=0xc0; //8msThx[2]=0x63;Tlx[2]=0xc0; //40msThx[3]=0xec;Tlx[3]=0x78; //5msSelectedSpeed=High;break;}}}if(SpeedSelected==True) //按下了确定键,退出速度选择{IsSelectingSpeed=False;break;}if(Next==True) //再一次按下了Next键,则循环速度选择{Next=False;continue;}}SelectedAll=True; //标志模式选择和速度选择完毕Running=True;Delay(50);WriteCmd(LCD_CLS);/*------------------------- 显示所选择的模式和速度方案-------------------------*/ if(SelectedMode==Line){DisplayString(0x0,0,"ChoosenModeis");DisplayString(0x0,1," Line ");Delay(50);WriteCmd(LCD_CLS);}if(SelectedMode==Curve){DisplayString(0x0,0,"ChoosenModeis");DisplayString(0x0,1," Curve ");Delay(50);WriteCmd(LCD_CLS);}if(AutoMode==1){DisplayString(0x0,0,"ChoosenModeis");DisplayString(0x0,1," AutoMode ");Delay(50);WriteCmd(LCD_CLS);}if(SelectedMode==Line){if(SelectedSpeed==Normal){DisplayString(0x0,0,"ChoosenSpeedis");DisplayString(0x0,1," Normal ");Delay(50);WriteCmd(LCD_CLS);}if(SelectedSpeed==Low){DisplayString(0x0,0,"ChoosenSpeedis");DisplayString(0x0,1," Low ");Delay(50);WriteCmd(LCD_CLS);if(SelectedSpeed==High){DisplayString(0x0,0,"ChoosenSpeedis"); DisplayString(0x0,1," High ");Delay(50);WriteCmd(LCD_CLS);}}INTInit(); //初始化所有中断DisplayString(0x0,0,"LeftTimesToGo"); while(ReadyToGo--){DisplaySingleChar(0x7,1,ReadyToGo+0x30); DisplaySingleChar(0x09,1,'s');Delay(300);}WriteCmd(LCD_CLS);DisplayString(0x05,0,"Go");Delay(100);WriteCmd(LCD_CLS);DisplayString(0x0,0," Living... "); DisplayString(0x0,1,"Designedby202");if(SelectedMode==Line&&AutoMode==0) flag=Area0;elseflag=1;while(flag<5){if(AutoMode==1) //自动模式{switch(PassLineID){case0 :{if(IsT0INT==1){P01=P02=P04=0;P03=1;}else{P01=P02=P03=P04=0;}}break;case1 :{P01=P02=P03=0;P04=1;}break;case2 :{P01=P02=P04=0;P03=1;default:break;}}else{if(SelectedMode==Line) //直线模式{flag=Area0;if(IsT0INT==1){P03=1;P04=0;P01=P02=0;}else{P03=0;P04=0;P01=P02=0;}}else{ //S型模式if((Nocurve<2)&&Round!=0&&(Back0>0)&&Back!=0) {if(Backid==1){P01=1;P02=0;P03=0;P04=1;}else{P01=0;P02=1;P03=0;P04=1;}Back=1;}else{if(Round==0){if(IsT0INT2==1){P01=0;P02=0;P03=1;P04=0;}else{P01=0;P02=0;P03=0;P04=0;}}else{if(P33==0){if(IsT0INT2==1){P01=0;P02=0;P03=1;P04=0;}else{P01=0;P02=0;P03=0;P04=0;}}else{if(Round%2){if(IsT0INT2==1){P01=1;P02=0;P03=1;P04=0;Backid=1;}else{P01=1;P02=0;P03=0;P04=0;}}else{if(IsT0INT2==1){P01=0;P02=1;P03=1;P04=0;Backid=0;}else{P01=0;P02=1;P03=0;P04=0;}}}}}}}if(IsT1INT==1){IsT1INT=0;ComputeTime();ComputeSpeedANDDistance();}}//补中断路程,加上最后一次中断缺失的路程ComputeSpeedANDDistance();P04=1;P03=0;P01=P02=0;Delay(90);P03=0;P04=0; //行程结束,小车停止P31=1; //行程结束,背光开ET0=0x0; //关T0中断ET1=0x0; //关T1中断EX1=0x01; //开INT1中断Running=False;AutoDisplay=True; //默认情况下直线模式会自动显示各个区域经过的时间WriteCmd(LCD_CLS);if(SelectedMode==Line) //直线模式才显示{while(1){if(GoToChoosingDisplay==True)Delay(200);WriteCmd(LCD_CLS);Delay(200);DisplayString(0,0,"LowSpeedArea1");DisplayString(0,1,"Costed");DisplaySingleChar(0x0C,1,'s');LowSpeedArea1PassTime=LowSpeedArea1EndTime-LowSpeedArea1StartTime; DisplaySingleChar(0x0A,1,LowSpeedArea1PassTime%10+0x30);if(LowSpeedArea1PassTime>9) //通过第一个低速区的时间超过sDisplaySingleChar(0x0B,1,LowSpeedArea1PassTime/10+0x30);if(GoToChoosingDisplay==True)break;Delay(200);WriteCmd(LCD_CLS);Delay(200);DisplayString(0,0,"HighSpeedArea");DisplayString(0,1,"Costed");DisplaySingleChar(0x0C,1,'s');HighSpeedAreaPassTime=HighSpeedAreaEndTime-LowSpeedArea1EndTime; DisplaySingleChar(0x0A,1,HighSpeedAreaPassTime%10+0x30);if(HighSpeedAreaPassTime>9) //通过高速区的时间超过sDisplaySingleChar(0x0B,1,HighSpeedAreaPassTime/10+0x30);if(GoToChoosingDisplay==True)break;Delay(200);WriteCmd(LCD_CLS);Delay(200);DisplayString(0,0,"LowSpeedArea2");DisplayString(0,1,"Costed");DisplaySingleChar(0x0C,1,'s');LowSpeedArea2PassTime=LowSpeedArea2EndTime-HighSpeedAreaEndTime; DisplaySingleChar(0x0A,1,LowSpeedArea2PassTime%10+0x30);if(LowSpeedArea2PassTime>9) //通过第二个低速区的时间超过sDisplaySingleChar(0x0B,1,LowSpeedArea2PassTime/10+0x30);}}AutoDisplay=False;/*---------------- 菜单选择你想要看的内容--总时间、总路程以及平均速度--------------*/ ChoosingDisplay=True;WriteCmd(LCD_CLS);/*首先显示主菜单,然后显示第一个选项*/DisplayString(0x0,0,"NowChoosewhat");DisplayString(0x0,1,"youwanttosee");Delay(100);while(1){WriteCmd(LCD_CLS);DisplayString(0x0,0," CostedTime ");DisplayString(0x0,1,"Next Show");Delay(250); //延时消除抖动/*------------------------------------第一次按键--------------------------------------*/ /*不断检测确定键和Next键*/while(1){if(Next==True)break;if(SelectedShow==True)break;}/*按下了确定键,显示第一个选项的内容*/if(SelectedShow==True){SelectedShow=False;SelectedReturn=False;Selected=False;WriteCmd(LCD_CLS);DisplayString(0,0,"CostedTimeis");DisplayTime();DisplayString(0x0A,1,"s");ReturnSelection=True; //按下了确定键,那么这个时候开启返回键的功能A VGSpeedShow=False;Delay(250); //延时消除抖动}/**按下了Next键,则显示第二个选项*/if(Next==True) //按下Next键,显示A VGSpeed菜单项{Next=False;WriteCmd(LCD_CLS);DisplayString(0x0,0," A VGSpeed ");DisplayString(0x0,1,"Next Show");ReturnMain=False;ReturnSelection=False; //按下了Next键,那么这个时候关闭返回键的功能A VGSpeedShow=True; //表明A VGSpeed选项已经显示过了Delay(250); //延时消除抖动}/*------------------------------------第二次按键--------------------------------------*/ /*显示第一个选项的内容后又不断检测返回键(确定键)和Next键*/ while(1){if(Next==True)break;if(Selected==True)break;}if(Next==True){Next=False;ReturnMain=False;ReturnSelection=False; //按下了Next键,那么这个时候关闭返回键的功能if(A VGSpeedShow==False) //还没有显示A VGSpeed选项,显示它{ //即第一次选择了确定键WriteCmd(LCD_CLS);DisplayString(0x0,0," A VGSpeed ");DisplayString(0x0,1,"Next Show");TotalDistanceShow=False; //显示了AVGSpeed,则表明TotalDistance还没有显示Delay(250); //延时消除抖动}if(A VGSpeedShow==True) //已经显示过A VGSpeed选项了,则显示下一个选项{ //即第一次选择了Next键WriteCmd(LCD_CLS);DisplayString(0x0,0,"TotalDistance");DisplayString(0x0,1,"Next Show");TotalDistanceShow=True; //表明显示了TotalDistance选项Delay(250); //延时消除抖动}}if(Selected==True) //按下了确定键或返回键{SelectedShow=False;SelectedReturn=False;Selected=False;if(ReturnSelection==True) //第一次选择了确定键,故这次按下的是返回键ReturnMain=True;if(ReturnSelection==False){WriteCmd(LCD_CLS);DisplayString(0,0,"TheA VGSpeedis");DisplayA VGSpeed();DisplayString(0x0A,1,"m/s");ReturnSelection=True; //按下了确定键,那么这个时候开启返回键的功能Delay(250); //延时消除抖动}TotalDistanceShow=False;}if(ReturnMain==True) //按下了返回键,返回主菜单{ReturnMain=False;continue;}/*------------------------------------第三次按键--------------------------------------*/ /*如果没有返回主菜单,则继续检测Next键和确定键*/while(1){if(Next==True)break;if(SelectedShow==True)break;}/*按下Next键,显示下一个选项*/if(Next==True){Next=False;ReturnMain=False;ReturnSelection=False; //按下了Next键,那么这个时候关闭返回键的功能if(TotalDistanceShow==True)ReturnMain=True;if(TotalDistanceShow==False) //还没有显示TotalDistance选项,显示它{WriteCmd(LCD_CLS);DisplayString(0x0,0,"TotalDistance");DisplayString(0x0,1,"Next Show");TotalDistanceShow=True;Delay(250); //延时消除抖动}}if(Selected==True) //按下了确定键或返回键{SelectedShow=False;SelectedReturn=False;Selected=False;if(ReturnSelection==True) //按下的是返回键ReturnMain=True;if(ReturnSelection==False){if(TotalDistanceShow==False) //表明A VGSpeed选项的内容还没有显示{WriteCmd(LCD_CLS);DisplayString(0,0,"TheA VGSpeedis");DisplayA VGSpeed();DisplayString(0x0A,1,"m/s");ReturnSelection=True;Delay(250); //延时消除抖动}if(TotalDistanceShow==True){WriteCmd(LCD_CLS);DisplayString(0,0,"TotalDistance");DisplayDistance();DisplayString(0x0A,1,"m");ReturnSelection=True; //按下了确定键,那么这个时候开启返回键的功能Delay(250); //延时消除抖动}}}if(ReturnMain==True) //按下了返回键,返回主菜单{ReturnMain=False;continue;}/*------------------------------------第四次按键--------------------------------------*/ while(1){if(Next==True)break;if(SelectedShow==True)}if(Next==True) //所有菜单项已经显示完毕,返回主菜单{Next=False;ReturnMain=False;ReturnSelection=False;if(TotalDistanceShow==False){WriteCmd(LCD_CLS);DisplayString(0x0,0,"TotalDistance");DisplayString(0x0,1,"Next Show");TotalDistanceShow=True;Delay(250); //延时消除抖动}}if(SelectedShow==True){SelectedShow=False;SelectedReturn=False;Selected=False;if(ReturnSelection==True) //按下的是返回键ReturnMain=True;if(ReturnSelection==False){if(TotalDistanceShow==True){WriteCmd(LCD_CLS);DisplayString(0,0,"TotalDistance");DisplayDistance();DisplayString(0x0A,1,"m");ReturnSelection=True;//按下了确定键,那么这个时候开启返回键的功能Delay(250); //延时消除抖动}}}if(ReturnMain==True) //按下了返回键,返回主菜单{ReturnMain=False;continue;}/*------------------------------------第五次按键--------------------------------------*/{if(Next==True)break;if(SelectedShow==True)break;}if(Next==True) //所有菜单项已经显示完毕,返回主菜单{Next=False;ReturnMain=False;ReturnSelection=False;if(TotalDistanceShow==True) //最后一个选项已经显示完毕,返回主菜单{ReturnMain=True;}}if(SelectedShow==True){SelectedShow=False;SelectedReturn=False;Selected=False;if(ReturnSelection==True) //按下的是返回键ReturnMain=True;if(ReturnSelection==False){if(TotalDistanceShow==True){WriteCmd(LCD_CLS);DisplayString(0,0,"TotalDistance");DisplayDistance();DisplayString(0x0A,1,"m");ReturnSelection=True; //按下了确定键,那么这个时候开启返回键的功能Delay(250); //延时消除抖动}}}/*------------------------------------第六次按键--------------------------------------*/ while(1){if(Next==True)if(SelectedShow==True)break;}if(Next==True){Next=False;ReturnMain=False;ReturnSelection=False;}if(SelectedShow==True){SelectedShow=False;SelectedReturn=False;Selected=False;}continue;}while(1);}/****************************************************************************** **********\** LCD驱动模块**\****************************************************************************** **********//*--------------------------------- LCD初始化函数--------------------------------------*/voidLCDInit(void){//三次显示模式设置LCD_Data=0;LCD_E=Disable;Delay(5);WriteCmd(LCD_Init);Delay(5);WriteCmd(LCD_Init);Delay(5);WriteCmd(LCD_Init);WriteCmd(LCD_Init); //初始化WriteCmd(LCD_CloseCtr); //关显示WriteCmd(LCD_CLS); //清屏幕WriteCmd(LCD_EnterSet); //光标移动设置WriteCmd(LCD_DispCtr); //显示开以及光标设置}/*--------------------------------- LCD模式设置函数--------------------------------------*\SetWriteCmd() 设置LCD为写命令模式SetReadCmd() 设置LCD为读命令模式SetWriteData() 设置LCD为写数据模式\*----------------------------------------------------------------------------------------*/ voidSetWriteCmd(void){LCD_RW=Write;LCD_RS=Cmd;}voidSetReadCmd(void){LCD_RW=Read;LCD_RS=Cmd;}voidSetWriteData(void){LCD_RW=Write;LCD_RS=Data;}/*--------------------------------- LCD功能执行函数--------------------------------------*\ WriteCmd() 写命令WriteData() 写数据ExecuteCmd() 执行命令SetXY() 显示定位DisplaySingleChar() 显示单个字符DisplayString() 显示一串字符IsBusy() 忙标志检测\*----------------------------------------------------------------------------------------*/ voidWriteCmd(charcmd){while(IsBusy());LCD_Data=cmd;SetWriteCmd();ExecuteCmd();}voidWriteData(charddata){while(IsBusy());LCD_Data=ddata;SetWriteData();ExecuteCmd();}voidExecuteCmd(void){LCD_E=Enable;LCD_E=Disable;}voidSetXY(charx,chary){if(y)x|=0x40;x|=0x80;Delay(5);WriteCmd(x);}voidDisplaySingleChar(charx,chary,charcchar){SetXY(x,y);WriteData(cchar);}voidDisplayString(charx,chary,char*str){while(*str){Delay(5);DisplaySingleChar(x++,y,*str);str++;}}bitIsBusy(void){LCD_Data=0xFF;SetReadCmd();ExecuteCmd();return(bit)(P1&0x80);}/*------------------------------------- 延时函数-------------------------------------*/ voidDelay(unsignedinttime){unsignedinttimeCounter=0;for(timeCounter=time;timeCounter>0;timeCounter--)DelayUs(255);}voidDelayUs(unsignedinttime){unsignedinttimeCounter=0;for(timeCounter=0;timeCounter<time;timeCounter++)_nop_();}/****************************************************************************** *************\** LCD显示模块**\****************************************************************************** *************/voidComputeTime(void){if(Area0<5)PassTime+=0.5;}voidComputeSpeedANDDistance(void){Speed=SpeedCount/4*CircleLength; //计算瞬时速度Distance+=Speed; //计算距离SpeedCount=0;}/*------------------------------------- 显示时间----------------------------------------*/ voidDisplayTime(void){charPassTime1=0x30;charPassTime2=0x30;charPassTime3=0x30;charPassTime4=0x30;if((int)PassTime*100<100) //时间未够1s{PassTime1+=0;PassTime2+=(int)(PassTime*100)/10;PassTime3+=(int)(PassTime*100)%10;}elseif((int)(PassTime*100)>100 &&(int)(PassTime*100)<1000)//够1s而未够10s{PassTime1+=(int)(PassTime*100)/100;PassTime2+=(int)(PassTime*100)/10%10;PassTime3+=(int)(PassTime*100)%10;}else{PassTime1+=(int)(PassTime*100)/1000;PassTime2+=(int)(PassTime*100)/100%10;PassTime3+=(int)(PassTime*100)/10%10;PassTime4+=(int)(PassTime*100)%10;}if((int)(PassTime*100)<1000){DisplaySingleChar(0x05,1,PassTime1);DisplaySingleChar(0x06,1,'.');DisplaySingleChar(0x07,1,PassTime2);DisplaySingleChar(0x08,1,PassTime3);}else{DisplaySingleChar(0x04,1,PassTime1);DisplaySingleChar(0x05,1,PassTime2);DisplaySingleChar(0x06,1,'.');DisplaySingleChar(0x07,1,PassTime3);DisplaySingleChar(0x08,1,PassTime4);}}/*------------------------------------ 显示平均速度----------------------------------------*/ voidDisplayAVGSpeed(void){intSpeed1=0x30; //初始化为0的ASCII码intSpeed2=0x30;intSpeed3=0x30;if((int)(Distance/PassTime*100)<100){Speed1+=0;Speed2+=(int)(Distance/PassTime*100)/10;Speed3+=(int)(Distance/PassTime*100)%10;}else{Speed1+=(int)(Distance/PassTime*100)/100;Speed2+=(int)(Distance/PassTime*100)/10%10;Speed3+=(int)(Distance/PassTime*100)%10;}DisplaySingleChar(0x05,1,Speed1);DisplaySingleChar(0x06,1,'.');DisplaySingleChar(0x07,1,Speed2);DisplaySingleChar(0x08,1,Speed3);}/*------------------------------------- 显示路程----------------------------------------*/ voidDisplayDistance(void){intDistance1=0x30;intDistance2=0x30;intDistance3=0x30;intDistance4=0x30;if((int)(Distance*100)<100){Distance1+=0;Distance2+=(int)(Distance*100)/10;Distance3+=(int)(Distance*100)%10;}elseif((int)(Distance*100)>100 &&(int)(Distance*100)<1000){Distance1+=(int)(Distance*100)/100;Distance2+=(int)(Distance*100)/10%10;Distance3+=(int)(Distance*100)%10;}else{Distance1+=(int)(Distance*100)/1000;Distance2+=(int)(Distance*100)/100%10;Distance3+=(int)(Distance*100)/10%10;Distance4+=(int)(Distance*100)%10;}if((int)(Distance*100)<1000){DisplaySingleChar(0x05,1,Distance1);DisplaySingleChar(0x06,1,'.');DisplaySingleChar(0x07,1,Distance2);DisplaySingleChar(0x08,1,Distance3);}else{DisplaySingleChar(0x04,1,Distance1);DisplaySingleChar(0x05,1,Distance2);DisplaySingleChar(0x06,1,'.');DisplaySingleChar(0x07,1,Distance3);DisplaySingleChar(0x08,1,Distance4);}}/*------------------------------------- 中断初始化-------------------------------------*/ voidINTInit(void){EA=1; //开总中断IT0=1; //INTO边沿触发PX0=1; //INTO优先级为高级EX1=1; //开INT1中断。

相关文档
最新文档