2小时学会编程.docx

上传人:b****7 文档编号:24003835 上传时间:2023-05-23 格式:DOCX 页数:33 大小:39.47KB
下载 相关 举报
2小时学会编程.docx_第1页
第1页 / 共33页
2小时学会编程.docx_第2页
第2页 / 共33页
2小时学会编程.docx_第3页
第3页 / 共33页
2小时学会编程.docx_第4页
第4页 / 共33页
2小时学会编程.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

2小时学会编程.docx

《2小时学会编程.docx》由会员分享,可在线阅读,更多相关《2小时学会编程.docx(33页珍藏版)》请在冰豆网上搜索。

2小时学会编程.docx

2小时学会编程

5.3两小时学会编程

编程就是把你对一件事的想法和思路用机器语言表达出来。

比如你正坐在沙发上,想要倒一杯水喝。

首先你要站起来,然后拿起杯子,再倒水。

编程也是一样的,你要完成一项任务,就要把中间的每一个步骤都分解开来,然后一一解决。

举个例子说吧,让机器人走一个正方形。

正方形是由四条长度相等的直线组成的,所以机器人所走的路径就是:

直走,长度为a;转九十度;直走a;转九十度;直走a;转九十度;直走a,转九十度。

这就是程序。

当然这样写机器并不能理解,怎样让机器读懂你的思路呢。

下面具体介绍一些编程的方法。

 

5.3.1编程的方法

程序有一定的结构。

常见的有顺序结构、选择结构和循环结构。

顺序结构就是先做第一件事,再做第二件事,再做第三件事……拿刚才的例子来说,先走直线,然后转九十度,再走直线……这就是顺序结构。

一开始喝水的例子:

站起,拿杯子,倒水,也是一个顺序结构。

选择结构就是有一个判断条件,当条件成立的时候做时间1,不成立的时候做事件2。

就象过马路一样,如果是红灯就要停下,如果不是红灯就可以走。

停和走就是两个事件,红灯是否亮就是判断条件。

循环结构分为当循环和直到循环两种。

当循环就是当条件p成立时,反复执行A操作,否则跳出循环。

直循环就是先执行A操作,再判断p是否成立,直到p成立时跳出循环。

现在我们就把刚才让机器人走正方形的例子写出来。

让大家有一个比较直观的了解。

其中如果有不理解的函数没有关系,下一节中会作出详细的介绍。

这里只要求大家知道程序编写的过程。

voidmain()/*建立一个主函数*/

{

drive(100,0);/*直走*/

sleep(1.0);/*走1秒,随意控制一定长度*/

drive(50,50);/*左转*/

sleep(0.6);/*转0.6秒,大致九十度*/

drive(100,0);/*直走*/

sleep(1.0);/*走1秒,随意控制一定长度*/

drive(50,50);/*左转*/

sleep(0.6);/*转0.6秒,大致九十度*/

drive(100,0);/*直走*/

sleep(1.0);/*走1秒,随意控制一定长度*/

drive(50,50);/*左转*/

sleep(0.6);/*转0.6秒,大致九十度*/

drive(100,0);/*直走*/

sleep(1.0);/*走1秒,随意控制一定长度*/

drive(50,50);/*左转*/

sleep(0.6);/*转0.6秒,大致九十度*/

stop();/*停止*/

}

这就是一个简单的程序,用的是顺序结构,是不是很容易理解呢?

也许大家会觉得这样做太复杂了,有没有简单一点的方法呢?

当然是有的。

下面这个程序也能让机器人走出直线,看上去就简单多了。

voidmain()/*定义一个主函数*/

{

inti;/*定义一个中间变量*/

for(i=0;i<4;i++)/*只要i小于4就一直循环,即循环执行4次*/

{

drive(100,0);/*直走*/

sleep(1.0);/*走1秒,随意控制一定长度*/

drive(50,50);/*左转*/

sleep(0.6);/*转0.6秒,大致九十度*/

}

stop();/*停止*/

}

这个程序用的是什么结构大家看出来了吗?

对,当循环结构。

所以对于这种每一个步骤所做的工作都一样,又要连续做几次的事件,我们就可以考虑用循环结构来编写程序。

再来介绍一个用选择结构编写的程序。

在控制能力风暴的程序编写中,大部分都是运用这种结构的。

voidmain()

{

inti;

i=ir_detect();/*ir_detect用于检测前方是否有障碍物,有为1*/

if(i=0)

{

drive(100,0);/*前方没有障碍物直走*/

}

else

{

drive(50,50);/*否则左转*/

}

}

是不是和红绿灯的原理很接近呢?

这个程序中还运用了传感器数据的接收,传感器是用来感测周围环境的工具,就象我们的眼睛、鼻子和耳朵一样,它们可是机器人身上必不可少的组成部分,在机器人项目里大家就会体会到传感器的用途了。

上面介绍的这些程序看上去还是很容易理解的吧!

可是这些毕竟只是简单的程序,只要稍微动动脑子就能把事情的各个步骤都分清楚了,如果遇到比较复杂的问题,光是拍拍脑袋可是想不清楚的,这就需要大家把手和脑一起用起来了。

我们要学习画图了。

接下来我们就来认识一下这个对我们编程有很大作用的工具:

结构流程图。

流程图表达的信息就是整个时间发展过程。

在流程图里,我们统一用菱形表示条件,用长方形表示事情的一个个过程、阶段,用箭头表示流程的方向。

光是说比较不容易理解,下面我们就来看一个流程图。

这就是流程图。

先检测光线强弱,接下来判断条件是否成立亮度低于临界值”就是条件,当条件满足时,就右转,不满足就左转;然后显示亮度值。

无论一件事多复杂都可以用流程图来描述,然后只要根据流程图中的步骤用C语言写下来就可以了。

复杂的程序可能包含多个任务,而且每一个任务都比较复杂,如果把那么多任务都在一起,看上去可能会显得很乱。

所以我们再学习一个新的概念:

主程序和子程序。

子程序表达的是每一个分步骤所需完成的任务。

主程序里如果做到这个动作,只要输入子程序的名字就可以了。

下面我们还是来看一下喝水的例子。

为了方便理解我把程序名都用中文代替,程序也只是为了表达子程序是如何调用的,并不是规范的写法。

主函数()(main)

{

站起来;

拿起杯子;

倒水;

}

站起来()

{

站起来的过程;

}

拿杯子()

{

拿杯子的过程;

}

倒水()

{

倒水的过程;

}

明白了吗?

这就是子程序的调用。

以后我们还会再介绍一种子程序的调用方法:

进程的调用。

它们之间是有区别的,以后我们在学习。

介绍了那么多方法,大家一定已经跃跃欲试了吧,现在还不行,我们还缺了一个重要的环节,那就是库函数。

也就是刚才出现在程序中的drive(),sleep(),stop()等函数,只有在知道了它们的使用方法以后,你编写出来的程序才能用来操作机器人。

 

5.3.2常用库函数

电机控制

1、stop()

关闭两个电机。

2、motor(intm,intp)

以功率级别p启动电机m。

功率级别从(-100到+100)。

m=1表示左马达,m=2表示右马达。

例如:

motor(1,50);

让右马达以功率100启动。

2、drive(inta,intb)

同时设定两个电机的速度,a平移速度,b旋转速度。

也可以这样来理解,a-b为左电机转速,a+b为右电机转速。

例如:

drive(100,0);

这时左右电机转速都为100,机器人走直线。

下面我们来看看以上两个函数的运用。

例1、

voidmain()

{

drive(60,30);

sleep(5.0);

stop();

}

大家来考虑一下,drive(60,30),两个电机是怎样运作的?

当运行了5秒钟以后,执行stop()函数,机器人会怎么样呢?

为什么sleep()函数中一定要输入5.0而不是5呢?

例2、这个程序是让机器人走一个圆,大家看一下这个程序和上面的程序有什么区别

voidmain()

{

motor(0,30);

motor(1,90);

sleep(5.0);

stop();

}

有什么发现吗?

对了,这两个程序实现的效果是一样的。

现在请大家再考虑一个问题,drive()函数和motor()函数有什么区别呢?

4、dcmotor3(intflag)flag=1启动电机。

flag=0关闭电机。

Dcmotor3这个电机是用来控制电扇的。

所以flag=1电扇旋转,flag=0电扇停止。

运行一下以下这个函数,大家就能掌握这个函数了。

voidmain()

{

dcmotor3

(1);

sleep(5.0);

dcmotor3(0);

}

风扇转动5秒后自动停止。

传感器输入

1、photo_right()右光敏电阻

photo_left()左光敏电阻

photo_right()和photo_right()的返回值是数字量。

范围从0到255,数值越大说明探测到的光线越暗。

最亮的时候输出值为5。

看看室内和室外的光线有什么区别。

voidmain()

{

intleft;

intright;

while

(1)

{

left=photo_left();

right=photo_right();

printf("left=%d",left);

printf("right=%d",right);

printf(“\n”);

sleep(0.5);

}

}

这里的while

(1),是让传感器不断地检测信号。

pintf(“\n”)是为了刷新屏幕,因为能力风暴的屏幕只有两行,\n是回车的意思,这样下一次显示就仍旧是从第一行输出了。

Sleep(0.5)是让数据在屏幕上停留0.5秒后自动刷新。

屏幕上显示的值表示了房间内的明暗程度,数值会不断变化,表示每个地方的亮度是不同的。

2、analog

(2)麦克风

他的变化范围是0—255。

一般最静时输出值为127,声音有变化时,数值也会有变化。

输入下面这个函数,然后对着麦克风说话,看看屏幕上的值会有什么变化。

voidmain()

{

inti;

while

(1)

{

i=analog

(2);

printf("sound=%d",i);

printf("\n");

sleep(0.5);

}

}

屏幕上显示的值可能会变化不大,这是由于硬件的约束,只可以粗略地表示出声音的轻响程度。

3、ir_detect()红外线传感器,利用红外线反射的时间差来判断障碍物的方位。

返回值,0b00:

没有障碍,0b01:

右边有障碍,0b10:

左边有障碍,0b11:

前方有障碍。

这些数字都是二进制的,在程序编写过程中,可以用上面给出的数字,也可以把它们转化成十进制。

下面的例子就是用十进制编写的。

注意:

这是没有改装时的情况,如果对能力风暴的红外传感器进行改装的话,就不能用上面的方法进行判断了。

试试用手分别遮住左边和右边的红外发射器,看看结果。

记住,一定要用手掌,用手指是没有效果的。

voidmain()

{

inti;

while

(1)

{

ir=ir_detect();/*接受信号*/

if(ir=1)

{

printf("\nright”);

sleep(0.5);

}

if(ir=2)

{

printf("\nleft");

sleep(0.5);

}

}

}

屏幕上会不断显示left和right,表示左边或右边有障碍物。

4、bumper()碰撞传感器检测。

它是由四位二进制数表示的,下面的数字可以告诉你那里受到了碰撞。

左前右前左后右后

0010000110000100

由此可推出

前(左前+右前)后(左后+右后)左(左前+左后)右(右前+右后)

0011110010100101

上面的数字是二进制数,书写时记得要在数字前加0b,表示二进制。

我们来写一个程序,看看碰撞环受到碰撞时,bumper()函数是怎么工作的。

voidmain()

{intbmpr;

printf("\n");

while

(1)

{bmpr=bumper();

printf("BumperTest");

if(bmpr==0)printf("none\n");/*bumper=0,说明没有碰撞*/

else

{if(bmpr==0b1000)printf("\nBackLeft");

else

{if(bmpr==0b0100)printf("\nBackRight");

else

{if(bmpr==0b0010)printf("\nFrontLeft");

else

{if(bmpr==0b0001)printf("\nFrontRight");

}

}

}

}

sleep(0.5);

}

}

输入这个程序后,当你碰机器人碰撞环的时候,屏幕上就会显示是那里受到了碰撞。

大家还可以自己加入对:

前、后、左、右的判断。

声音

1、beep()产生一段0.3秒500赫兹的音频信号。

发声结束后返回。

输入程序听听看。

voidmain()

{

beep();

}

程序运行时你会听到3秒钟的蜂鸣声。

2、tone(floatfrequency,floatlength)产生一个秒长为length,音调为frequency赫兹的音频信号。

3、set_beeper_pitch(floatfrequency)设置音频频率为frequencyHz。

4、beeper_on()打开喇叭

beeper_off()关闭喇叭。

以上三个函数可以通过下面这个函数来帮助了解。

voidmain()

{

tone(500.0,2.0);

set_beeper_pitch(1000.0);

beeper_on();

sleep(5.0);

beeper_off();

}

你会先听到两秒钟较低的声音,再听到五秒钟较高的声音。

进程调度

1、start_process(function-call(...),[TICKS],[STACK-SIZE])

创建新进程。

star_process取得一个进程标识,创建一个进程。

两个可选参数:

进程的时间片数和栈大小。

返回一个整数,新进程的进程ID。

2、kill_process(intpid)撤消进程。

进程是用来控制函数的执行的,如果大家不理解,没有关系,在下面介绍多任务的那一小节中会有介绍。

浮点运算

sin(floatangle)返回角的正弦。

角以弧度为单位。

cos(floatangle)返回角的余弦。

角以弧度为单位。

tan(floatangle)返回角的正切。

角以弧度为单位。

atan(floatangle)返回角的余切。

角以弧度为单位。

sqrt(floatnum)返回num的均方根。

log10(floatnum)返回num的以10为底的对数。

log(floatnum)返回num的自然对数。

exp10(floatnum)返回10的num次方。

exp(floatnum)返回e的num次方。

a^(float)返回a的b次方。

这些函数是帮助大家进行数学运算的,使用起来非常方便,就象按计算器一样。

我们来看看下面这个函数的运行结果。

不妨和计算器算出的结果进行一下比较。

voidmain()

{

sin(0.5);

tan(0.5);

sqrt(9.0);

3.0^(2.0);

}

以上就是常见的库函数,熟悉了他们以后,就可以让机器人作简单的动作了。

试试让机器人跳个舞吧。

如果不知道怎么办,可以下载一下交互式C语言自带的dance.c,看看机器人是怎么运动的,考虑一下。

5.3.3多任务

交互式C语言支持多任务。

什么是多任务呢?

我们不妨想像一下,支持多任务的语言,就像一个有交通警的十字路口。

十字路口有东南西北四个方向,交通警让东边先过一辆,再让南边走一辆,然后西边走一辆,在北边走一辆。

然后重复。

看上去就像四条路上的车辆在一起运动一样。

不采用进程调用的程序,就好象我们在第一节中介绍的子程序调用,它是怎么工作的呢?

子程序的调用,就像一个没有警察官的十字路口,各路车辆自由行驶,最终大家都是可以通过路口的,但是这个过程显得比较混乱,没有秩序。

在程序的执行中,有可能是做完A再做B,也有可能是做一半A就开始做B,没有规律。

对于同步性要求不是很高的程序可以使用子程序调用的方式,但对于同步性要求很高的程序就一定要使用进程。

比如:

机器人寻找火源,他一边要防止自己撞到墙上,一边要搜索那里有火,两个过程必须同时进行,这时就要用到进程的调用了。

对于程序来说呢,看上去就像是好几个程序同时执行。

其实在电脑中的执行是有先后顺序的,先做A的一部分,再做B的一部分,然后是C的一部分……只是时间间隔很短,看不出来而已。

在上一章中我们曾经看到过一个库函数,start_process()和kill_process(),这两个函数就是帮助实现多任务的。

start_process()用于启动一个程序,它的格式是这样的:

start_process(function-call(...),[TICKS],[STACK-SIZE])

TICKS和STACK-SIZE是两个参数,分别表示:

进程的时间片数和栈大小。

现阶段硬要去理解他的意义不大。

一般我们在使用这个函数时只要知道在start_process()的括号里放入你需要执行的子程序。

如果有多个子程序需要同时进行,只要连续写几个start_process(…)就可以了。

另一个函数kill_process(),用于取消一个进程,也就是让一个程序停止执行。

它的格式是这样的:

kill_process(intpid)

这个函数的使用要和start_process()结合起来。

我们来看一个例子:

voidmain()

{

intpid;

pid=start_process(check_sensor());

sleep(1.0);-

kill_process(pid);

}

这个例子中check_sensor(),这个程序执行了1秒后终止。

这就是kill_process(),的用法。

为了让大家更深地对多任务进行了解,我们在机器人项目一节中会举一个台球碰撞的例子

到这里,大家就已经学会了多个任务的的执行。

程序的编写过程基本就是这些内容了,接下来就要让机器人来执行你编写的程序了。

在把程序下载到机器人上去之前,还有一个必不可少的环节,那就是程序的调试。

5.3.4程序的调试方法

所谓程序的调试就是对程序的查错和排错。

程序编写过程中的错误有很多种,有语法错误,逻辑错误等,要想成功调试,首先要知道常见的错误有哪些,如何解决。

下面列举几种常见的错误,供初学者参考。

1、忘记定义变量。

例如:

voidmain()

{

while

(1)

{

ir=ir_dectect();

printf("\nir=%d",ir);

sleep(0.5);

}

}

C语言要求对每一个变量先定义后使用,如果没有定义变量,程序下载时会出现这样的话“未说明的变量ir”。

应在函数体的开头加“intir”。

2、输入输出的数据类型与所用格式说明符不一致。

例如:

voidmain()

{

drive(100,0);

sleep

(1);

}

下载这个命令时会出现这样的话“参数不兼容(要求是,给的是)”。

杂这个程序中sleep()函数的参数要求是实型,而1是整型,要把1改成1.0。

3、括号不配对

例如:

voidmain()

{

intir;

while

(1)

{ir=ir_detect();

printf("\nir=%d",ir);

sleep(0.5);

}

这个程序编译时会出现这样一句话,“语法错误在符号""附近。

出现这句话的原因是:

有两个左括号却只有一个右括号。

应该改成

voidmain()

{

intir;

while

(1)

{ir=ir_detect();

printf("\nir=%d",ir);

sleep(0.5);}

}

4、在应该加括号的地方忘记了加括号。

例如:

for(i=0;i<4;i++)

drive(100,0);

sleep(1.0);

这里在for后面本来应该有括号,保证程序的循环,现在没有括号,程序只执行一次就结束了。

应改为

for(i=0;i<4;i++)

{

drive(100,0);

sleep(1.0);

}

5、在不该加分号的地方加了分号,该加的地方缺省了。

例如:

if(i=1);

if是条件语句,不需要加分号。

drive(100,0)

drive()是命令函数,后面要加分号。

以上这些是初学者最容易犯的错误,注意了这些错误以后,我们就可以来说说调试了。

调试程序一般应经过以下几个步骤:

1、自己检查。

在写好一个程序以后,不要匆匆忙忙上机,而应对纸面上的程序进行人工检查。

这一步是十分重要的,它能发现大家由于疏忽而造成的多数错误。

为了更有效地进行人工检查,所编的程序应尽量做到以下几点:

(1)尽量多加注释,帮助理解每段程序的作用。

注释就是前面大家经常见到的/**/这种形式。

两个星号中间的语句就是注释语句,在C语言中被注释掉的语句是不参加编译的。

有时也把需要修改的程序用星号注释掉这样如果修改后仍不正确,还有原稿可以参考。

(2)尽量多用子程序,主程序要尽量简短。

这样既易于阅读也便于调试。

2、在人工检查无误后,就可以上机调试了。

在编译时出现的语法错误,可以根据提示的信息具体找出程序中错误的位置和类型。

有时提示错误的行并不一定就是出错误的行,错误可能在上下一行中出现。

3、在改正语法错误后就可以执行程序了,有时候明明没有错误了,执行出来的结果还是不是自己要求的那样,这是怎么回事呢?

出现这种情况很可能是因为在程序的计算过程中有错误。

比如:

本来应该是a+b,结果你输入时成了a-b。

在语法上确实没有错误,但结果可就差得很远了。

4、最后一种错误就是逻辑错误,那可是你一开始就犯的错误了。

出现这种问题时,你就需要拿出原来的流程图,看一下思路是不是正确,判断条件是不是找错了,与和

或的关系是不是错了……。

如果觉得整段程序看起来太复杂,不妨在每段子程序里多加几个“printf”,分段看看程序执行中哪一步出了问题。

总之,程序调试是一项细致深入的工作,需要下功夫、动脑子、善于多积累经验。

而且需要极好的耐心,千万不能遇到问题就失去信心,慢慢来,你一定能够做好的。

5.3.4机器人项目

讲了那么多编程的有关知识,现在我们开始自己动动手吧。

做一个有趣的试验,帮助大家巩固一下前面学到的知识。

让你的机器人可以跟着你走,如果撞上了你,它会停一停;如果看不见你了,它也会停下来。

先来想一下这个程序分成几个部分,应该用什么结构和方法来编写?

我们来分析一下。

机器人的行走路线是这样的。

撞到障碍物,看不到东西:

停;左边有人:

往左走;右边有人:

往右走;前方有人:

往前走。

下面我们来看一下程序。

voidmain()

{

i

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 理化生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1