免费样片申请(暂时无用,不说了,很简单)
作业讲解
1-5点亮灯过简单,不说了
6:尝试让第一个发光管闪烁
闪烁,就是亮,灭,再亮,再灭这样一个循环的过程,就是写程序控制某一个IO口先输出低电平,再输出高电平,再输出低电平,如此循环,没变化一个状态要持续一个时间(即为延时)。简单的延时就用一个while或者for循环就可以。
1 #include<reg52.h>
2 sbit p1_1=P1^0;
3 unsigned int a;
4 void main()
5 {
6 a=50000;
7 p1_1=0;
8 while(a--);
9 a=50000;
10 p1_1=1;
11 while(a--);
12 }
定义一个unsigned int(无符号整型)类型的变量a,其范围为0-65535,若超出这个值,就会取余,例如70000,那么就会取70000-65535后的值。
这里选中这两个,这样如果一直插着单片机,然后更改代码并编译的话,会自动下载进单片机。
你可能会按照上面的方法,但这样是不对的,不标准。因为正常执行c语言代码时,从进入main函数开始,执行完main内部的代码就结束了,但这里却又重新再执行了,因为单片机会一直重复执行main函数,但有时会出错。
正确的写法
1 #include<reg52.h>
2 sbit p1_1=P1^0;
3 unsigned int a;
4 void main()
5 {
6 while(1)
7 {
8 a=50000;
9 p1_1=0;
10 while(a--);
11 a=50000;
12 p1_1=1;
13 while(a--);
14 }
15 }
在main函数内部再写一个while(1),将需要循环执行的代码放入while(1)的花括号内,这样单片机就会一直循环while(1)内部的内容而不出错了。
要学会软件调试
点击这个放大镜一样的东西就是打开调试了,调试前要先编译。再次点击就关闭。
黄色箭头指着的就是下一条要执行的语句
这个是复位,点击后让调试重头开始。
全速执行。
停止全速执行,只有在开启全速执行后它才会变成红色,才能使用。
进入函数内部。
执行下一调语句。
点击Peripheral(硬件)
Interrupt:中断
I/O-Ports:IO口
Serial:串行端口
Timer:定时器
这里选择我们现在用到的IO口的P1口Port 1
可以看到P1上电后为oxFF,即上电后所有IO口为高电平(IO口上电后为1,其余寄存器上电后为0,上电后会自动复位,所以这里软件的复位就可以当做上电),对应的后面8位都打了√,如果√没了,对应的一位就变成了0。操作单片机就是对内部的寄存器(P1)进行操作。
点击View,选上call stack window
看到,执行过的语句变成绿色,没执行的是灰色,这里while(a--)要想执行完需要单步执行(即一次执行一句)50000次,要点50000次,很慢,所以我们可以设置断点。
断点就是前面出现了红色,有的版本是红色的圆,设置断点的方法就是在需要的语句前方灰色处用鼠标单击。
现在我们说一下上面的全速执行,全速执行就是一直执行,而且执行的很快,不需要你一下一下的点,但是你不知道执行到哪里了,所以我们要用到断点,这里我们不想点击50000次,所以我们在while(a--)后面那条语句设置断点,再开启全速执行,那么程序就会全速执行到断点的位置然后停止,不会执行断点那条语句。
这里执行完全速后,a变为了65535(也是满,unsigned int类型的最大值,满和空是一个概念),意思是减空了,从原本的50000,减到0后再减一次就是65535了。
硬件调试(在线调试)(仿真芯片) 你没买,先不用看
仿真芯片有利于你领悟程序具体是怎么执行的
点开设置
点到debug这一栏。
原本是use Simulator,现在我们点击右边的Use,选择keil Monitor-51 Driver,再点击Settings设置
选择com口,下载程序用的com几,这里就选com几,然后点击ok。
之后这里全部打钩,再确定。
仿真时必须先接通电源
然后点击debug调试
下方会显示连接到了(Connected to Monitor-51)
然后就按刚才方法调试即可,不同的是这里调试时,单片机也会跟着一步一步走。
这种调试你可以知道每一条指令什么时候执行,每一种变量如何变化的。
结束调制时先按下单片机上的复位按钮,再点debug结束
接下来学习如何设置比较准确的延时时间
首先,要知道,实验板的晶振频率是11.0592MHz,计算机单片机的运行速度是由其决定的
下面的内容只需要知道一个机器周期是12个时钟周期,一个时钟周期是震荡源的周期。
在调节时间的时候,需要把keil中的晶振频率改为和单片机的晶振频率相同
下面打开调试状态
会看到当程序运行到这里时是0.00042209s,先运行到灯亮
0.00042752s,然后我们运行到它灭之前看看中间有多少时间,这就是我们要的延时时间,这里要设置断点,不然while(a--)我们要手动50000次....
时间变为了0.48893555s,离500ms近了,我们微调下,把a变为51000再运行到这里就差不多了。下面的也改。
下面我们看看如果不设置11.0592MHz晶振频率,用默认的24MHz会怎么样
频率24大约是11的2倍,那么时间也差不多是1/2。
但是这里只是模拟,对单片机没有影响,单片机还是用它本身的11.0592来计算的,不过这样你就算不准了。
接下来学习子函数(以后写程序都是写在函数里,然后main全是调用)
首先介绍一下宏定义define,就相当于起一个新的名字,用法#define new_name old_name
1 #include<reg51.h>
2 #define uint unsigned int//宏定义
3 #define uchar unsigned char
4
5 void delay();//声明函数
6 sbit D1=P1^0;
7 void main()
8 {
9 while(1)
10 {
11 D1=0;
12 delay();
13 D1=1;
14 delay();
15 }
16 }
17
18 void delay()//定义函数,大约是500ms的延时,
19 {
20 uint x,y;
21 for(x=100;x>0;x--)
22 {
23 for(y=600;y>0;y--)
24 {
25
26 }
27 }
28 }
这里for循环还有上面出现的while循环,当没有内部语句时,可以省略{},直接写分号
1 void delay(uint n)
2 {
3 uint x,y;
4 for(x=n;x>0;x--)
5 {
6 for(y=600;y>0;y--);
7 }
8 }
其它自己看懂,不再赘述了
带参数的子函数
1 #include<reg51.h>
2 #define uint unsigned int
3 #define uchar unsigned char
4
5 void delay(uint n);
6 //void delay(uint );这里声明也可以写成这样(不写n),但建议写上面那种,方便,上面那种只需要在函数定义那里复制过来就可以了,不会出错。
7 sbit D1=P1^0;
8 void main()
9 {
10 while(1)
11 {
12 D1=0;
13 delay(100);
14 D1=1;
15 delay(100);
16 }
17 }
18
19 void delay(uint n)
20 {
21 uint x,y;
22 for(x=n;x>0;x--)
23 {
24 for(y=600;y>0;y--)
25 {
26
27 }
28 }
29 }
函数定义和函数声明的参数叫做形参(形式参数),函数调用时给的数值是实参(实际参数),因为函数定义时函数是不执行的,而只有调用时,函数才执行,其中的参数会使用你传的参数,也就是实参。
接下来我们用stc-isp来生成延时函数
打开后点击红框内的三角箭头,找到软件延时计算器
先选择晶振频率,再设置延时的时间,再选择指令集STC-Y1,然后生成c代码,最后复制就可以了
1 #include<reg51.h>
2 #define uint unsigned int
3 #define uchar unsigned char
4
5 void Delay1ms();
6 void delay(uint n);
7 sbit D1=P1^0;
8 void main()
9 {
10 while(1)
11 {
12 D1=0;
13 delay(200);
14 D1=1;
15 delay(200);
16 }
17 }
18
19 void delay(uint n)
20 {
21 while(n--)
22 {
23 Delay1ms();
24 }
25 }
26 void Delay1ms() //@12.000MHz
27 {
28 unsigned char i, j;
29
30 i = 2;
31 j = 239;
32 do
33 {
34 while (--j);
35 } while (--i);
36 }
定义一个延时1ms的函数,然后再定义一个带参数的函数,调用延时1ms的函数n次,就产生了延时n ms的函数了
接下来是流水灯
找到C51文件夹中Hlp文件夹下的c51帮助文档,在Reference里能看到库函数,都是写好的可以直接调用的函数
这里我们要用到_crol_
点开后可以看到介绍和例子,需要用到头文件intrins.h,将变量c循环左移b位,返回移动后的结果。a=0xA5(1010 0101),循环左移一位变成(0100 1011),循环左移第二位(1001 0110),循环左移第三位(0010 1101)即0x2D,循环左移一次就是整体左移一次,把最高位的放到最低位。
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uint unsigned int
5 #define uchar unsigned char
6
7 uchar temp;//为什么用uchar而不用uint?
8
9 void Delay1ms();
10 void delay(uint n);
11
12 void main()
13 {
14 temp=0xfe;
15 P1=temp;//因为uchar有8位,而uint有16位,每组IO口也是8位,所以如果我们要用uchar
16 while(1)//先让P1=0xfe(1111 1110)
17 {
18 delay(300);//延时300ms
19 temp=_crol_(temp,1);//改变temp的值
20 P1=temp;//改变P1的值
21 }
22 }
23
24 void delay(uint n)
25 {
26 while(n--)
27 {
28 Delay1ms();
29 }
30 }
31 void Delay1ms() //@12.000MHz
32 {
33 unsigned char i, j;
34
35 i = 2;
36 j = 239;
37 do
38 {
39 while (--j);
40 } while (--i);
41 }
其实temp这里多余,只是想让你知道定义变量要注意的地方,比如为什么不用unsigned int而用unsigned char
1 void main()
2 {
3 P1=0xfe;
4 while(1)//先让P1=0xfe(1111 1110)
5 {
6 delay(300);//延时300ms
7 P1=_crol_(temp,1);//改变P1的值
8
9 }
10 }
main可以直接改成这样
课后作业
补充一下蜂鸣器
蜂鸣器原理图
(我的板子是第二种)(继电器也挺重要,但暂时不说了)
FM就是P2^3口,然后接一个电阻,这里用了一个三极管,用了它的开关作用(它还有放大作用),(蜂鸣器内阻很小(忽略)),当给P2^3低电平时,ce就导通了,就有从VCC流经蜂鸣器然后经过ce的电流。
因此蜂鸣器的使用也很简单,0就响,1就停止。
1 #include<reg51.h>
2
3 sbit beep=P2^3;
4
5 void main()
6 {
7
8 while(1)
9 {
10 beep=0;
11 }
12 }
这样就响了
接下里是响、停循环进行
1 #include<reg51.h>
2
3 #define uint unsigned int
4 #define uchar unsigned char
5
6 sbit beep=P2^3;
7
8 void Delay1ms();
9 void delay(uint n);
10
11 void main()
12 {
13
14 while(1)
15 {
16 beep=0;
17 delay(300);
18 beep=1;
19 delay(300);
20 }
21 }
22
23 void delay(uint n)
24 {
25 while(n--)
26 {
27 Delay1ms();
28 }
29 }
30 void Delay1ms() //@12.000MHz
31 {
32 unsigned char i, j;
33
34 i = 2;
35 j = 239;
36 do
37 {
38 while (--j);
39 } while (--i);
40 }
这里在提一下前面说到的~(取反),原本是0,取反就是1,原本是1,取反就是0,用这个会很简单。
1 #include<reg51.h>
2
3 #define uint unsigned int
4 #define uchar unsigned char
5
6 sbit beep=P2^3;
7
8 void Delay1ms();
9 void delay(uint n);
10
11 void main()
12 {
13
14 while(1)
15 {
16 beep=~beep;
17 delay(300);
18 }
19 }
20
21 void delay(uint n)
22 {
23 while(n--)
24 {
25 Delay1ms();
26 }
27 }
28 void Delay1ms() //@12.000MHz
29 {
30 unsigned char i, j;
31
32 i = 2;
33 j = 239;
34 do
35 {
36 while (--j);
37 } while (--i);
38 }
评论(0)
您还未登录,请登录后发表或查看评论