郭天祥的10天学会51单片机_第二节
申请样片:美信公司,www.maxim-ic.com,右上角有简体中文,在右边直接购买标题的下面有申请样品,点击后新页面下打开工业控制,在数据资料中找DS12CR887,在右上角的型号搜索栏中填入DS12CR887点击搜索,新网页打开后在右边有数据资料可以下载,在该页面的下面找样品与定购信息,找到DS12CR887,点击超级链接,打开新页面,在新页面下的下面下载DS12CR887-5+,点击样品,在新页面下填写资料,点击提交;一周申请一次
AD公司,www.analog.com也可以申请样品
TI公司,www.ti.com,可以一个月申请一次
While (表达式)
{语句(内部也可为空)}
特点:先判断表达式,后执行语句。
原则:若表达式不是0,即为真,那么执行语句。否则跳出while 语句。
写程序时头脑中要形成一种时序的概念,写程序控制单片机,让单片机控制外围器件,单片机按照指令的从上而下的顺序一条一条执行
一般单片机的程序要先进入一个大循环
Tab键是语句行右移,Shift+Tab是左移
While(1)就是始终进行循环
两个原则:一是大循环用While(1)加大括号,在大括号中进行总程序的循环;二是如果要程序停止在某一行,用While(1)加分号(;),程序永远不会往下执行
软件仿真:工具栏上的打印机按钮右边的按钮Start,点击后进入调试模式,
工具栏上出现的按钮,第一个按钮,RST外形的按钮是复位CPU,作用是功能复位,将指针指到程序的开始;第二个按钮,Run按钮,全速执行;第三个按钮,Halt按钮,停止按钮;第四个按钮,Step into按钮,进入函数体内部(进入子函数常用),单步执行,一条一条走;第五个按钮,Step over按钮,一次执行一个语句;黄色箭头指向当前语句,再点一下Step over按钮即执行这句程序,每执行一条指令,内部所有寄存器都会发生变化,这里可以打开菜单栏的Peripherals(硬件)下面的按钮(中断,IO端口,串行端口,定时器),这里打开IO端口的Port1(P1口),再打开菜单栏的View下面的Watch & Call Stack Window,这里选择Watch & Call Stack Window面板上的Watch#1页面,这里点击Name下面的框(或者按F2),输入要查看的变量,再回车,可以在变量上右键单击选择16进制或10进制,单步Step over一下,发现P1口的第零位勾没了,即表示为零,Watch#1页面的a的值也变了,可以设置断点,双击某一行即设置断点,再双击取消,这里在第二个a=50000处设置断点,即上一句whie(a--)执行完就停下,断点的作用是在全速执行程序时,当要执行断点所在的指令的时候程序就停下来,这里a是65535,表示a已经全减空了,全减空是0,再减一下就是65535,再点下全速Run程序又停在断点处,说明程序又进行一次循环,又到了断点处
使用仿真芯片,安装好仿真芯片89E516RD,再在Keil中进行设置,单击工具栏的Option for target按钮进行设置,点击Debug页,点击右边的Use Keil Monitor-51 Driver的Settings,选择COM口,点击OK即可,下面的可打钩的都打钩,然后确定,用仿真芯片和普通的使用单片机不一样,要先打开单片机的电源,点击按钮Start进行调试,左侧的信息框出现Connected to Monitor-51 V3.4,进行单步Step over调试,第二步看见发光二极管亮,这里走的慢,设置断点在第二个a=50000处,然后全速Run,程序走的断点处,再点二步就走到p1_1=1处即发光二极管熄灭,去掉断点全速执行发光二极管就正常执行闪烁;使用仿真芯片可以知道每一条指令如何执行,每一个变量如何变化;结束调试,先按下单片机上的复位按钮,再按下Keil软件中的按钮Start结束调试
看一下变量的情况,可以把该变量值改小点,然后调试
让发光二极管每隔500ms闪烁,单片机上右下角的复位键左侧是晶振,11.0592MHZ,单击工具栏的Option for target按钮进行设置,点击Target页,对Xtal晶振频率进行设置
在需用软件调节时间时可以将这里的晶振调节成和单片机板的晶振同样大小,这里改成11.0592
查看延时的时间,在调试状态下,左侧有sec(秒),单位是秒,程序单步走时间也在走,在发光二极管灭之前设置断点,即在p1_1=1处设置断点,全速运行一下,再看时间,这里用了488ms,我们再微调到500ms,先结束调试,再修改程序,然后编译,再调试;微妙级的可以忽略(开始调试前,sec是几百微妙,可以忽略);这里发光二极管依然是500ms闪烁,因为发光二极管的是由单片机的硬件决定的,硬件没有变化,单片机内部晶振还是11.0592MHZ,减慢或加快闪烁速度仍要通过程序来控制
仿真时间时要,单击工具栏的Option for target按钮进行设置,点击Target页,对Xtal晶振频率进行设置
#include<reg52.h>
sbit p1_1=P1^0;
unsigned int a;
void main()
{
while(1)
{
a=51000;
p1_1=0;
while(a--);
a=51000;
p1_1=1;
while(a--);
}
}
在第一个a=51000处设置一个断点,全速运行,到下面的断点第二个p1_1=1处,时间是490ms,再全速运行,到第一个a=51000处的断点,运行时间是1.107s,即运行完发光二极管灭后的时间是1.107s
每次修改完都要编译一下再调试,否则只会调试到上次程序的状态
在项目中,完全是调用子程序,主程序中完全是调用子程序
For循环如果有大括号可以不加分号,循环嵌套在最后的循环结尾处加一个分号表示该嵌套包含在上一个嵌套的里面,此时如果再写一个循环就和上面的循环没有关系了
宏定义时要把要定义的变量名写在前面,类型写在后面,结尾不用加分号
子函数在调用时要在主函数前声明,因为要为子函数分配空间,如果不分配空间,在调用时主函数会找不到子函数
调试时,要在要调试的语句的下一句设置断点,因为要看执行完该语句后的状态
在声明带参数的子函数时,要声明子函数内参数的类型,可以写参数名,也可以不写参数名,如果有多个参数,写上类型后用逗号隔开
#include<reg52.h>
#define uint unsigned int //unsigned int为正数,所以不用考虑变量为负
#define uchar unsigned char
sbit D1=P1^0;
//void delay();
void delay(uint);
void main()
{
while(1)
{
D1=0;
delay(100);
//delay();
D1=1;
delay(100);
//delay();
}
}
/*void delay()
{
uint x,y;
for(x=100;x>0;x--)
for(y=600;y>0;y--);
}*/
void delay(uint z)
{
uint x,y;
//uchar y;
for(x=z;x>0;x--)
for(y=600;y>0;y--);
}
51帮助文档在Keil文件下面的C51文件下面的HLP文件下面的C51lib.Chm
_crol_函数是循环左移函数,上面标有#include <intrins.h>,说明使用时要添加该头文件
下面又标示,unsigned char _crol_ (unsigned char c, /* character to rotate left */
unsigned char b); /* bit positions to rotate */
表示该函数返回值是unsigned char,参数中第一个是表示要移位的变量,第二个是要移动的位数
去除当前工程的文件,右键点击要删除的文件,选择Remove File
流水灯程序:
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
uchar temp,num,num1;//因为P1口是八位的,如果定义成int型可能会出错,所以要定义成char型
sbit beep=P2^3;
void delay(uint);
void main()
{
temp=0xfe;
P1=temp;
while(1)
{
temp=_crol_ (temp,1);
delay(100);
P1=temp;
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
蜂鸣器在TX-1C型单片机实验板原理图中单片机右边锁存器下面,FM旁边电阻上面的18表示18欧姆,FM连接单片机的P2^3口;三极管有电流放大功能,三极管是压控流型的,电压控制电流的放大倍数,这里用的是三极管的开关功能,PNP型,图中的箭头应该标在下面,
三极管有三极,从左至右从上到下依次是b(基极)c(集电极)e,箭头一般在b和e之间,由e指向b(如果是NPN型也是如此,从左至右从上到下依次是bce,箭头一般在b和e之间,但箭头是由b指向e);当基极b给低电平,集电极c;蜂鸣器里面内阻极小,里面有线圈贴合铁片,接Vcc,线圈通电吸合铁片产生振动发出声音,而基极b给低电平,由c向b正向导通,PN节之间有压降,正向导通,有压降所以将c和e之间连通,即当给b低电平时相当于将c和e之间连通,反之如果b高电平,和c之间没有压降c和e之间不会导通;总结一下,给b低电平蜂鸣器响,给b高电平蜂鸣器不响
接触式继电器,开始a和b连通,当线圈给电产生磁场,把a和b的线圈吸过去,让b和c连通,见下图,继电器线圈上面连接Vcc,下面连接三极管,三极管连接单片机的P2^3口
驱动继电器方法同蜂鸣器,P2^3口给低电平,继电器工作;继电器要反向接一个发光二极管,作用是突然关闭继电器时,线圈中产生逆向感应电流,电流会反向流过,由d到e,这里接二极管电流就会流向二极管,而不会流向三极管导致bc之间的PN结击穿
课后练习:
第一个发光管以间隔200ms闪烁:
我的方法:
#include<reg52.h>
#define uint unsigned int//unsigned int为正数,所以不用考虑变量为负
#define uchar unsigned char
sbit D1=P1^0;
void delay()
{
uint i,j;
for(i=115;i>0;i--)
for(j=200;j>0;j--);
}
void main()
{
while(1)
{
D1=0;
delay();
D1=1;
delay();
}
}
课件方法:这里把频率调成11.0592MHZ
#include<reg52.h> //52单片机头文件
#define uint unsigned int //宏定义
#define uchar unsigned char //宏定义
sbit led1=P1^0; //单片机管脚位声明
void delay(uint z) //延时函数,z的取值为这个函数的延时ms数,如delay(200);大约延时200ms.
{ //delay(500);大约延时500ms.
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void main() //主函数
{
while(1) //大循环
{
led1=0; //点亮小灯
delay(200); //延时200毫秒
led1=1; //熄灭小灯
delay(200); //延时200毫秒
}
}
8个发光管由上至下间隔1s流动,其中每个管亮500ms,灭500ms,亮时蜂鸣器响,灭时关闭蜂鸣器,一直重复下去。
我的方法:第一步是让第一个发光二极管亮500ms,灭500ms,亮时蜂鸣器响,灭时关闭蜂鸣器,再做流水灯
再改动完程序,编译完,用STC软件时要先打开一下程序文件,然后再Download程序
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit beep=P2^3;
void delay(uint);
void main()
{
uchar temp;
temp=0xfe;
while(1)
{
P1=temp;
beep=0;
delay(500);
P1=0xff;
beep=1;
delay(500);
temp=_crol_(temp,1);
}
}
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
8个发光管来回流动,每个管亮100ms,流动时让蜂鸣器发出"滴滴"声。
变量的定义要一起定义在函数体的前面,否则会出错
来回流动的意思是从第一个发光二极管流到第八个发光二极管后再从第八个发光二极管流到第一个发光二极管
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit beep=P2^3;
void delay(uint);
void main()
{
uchar temp,a;
while(1)
{
temp=0xfe;
for(a=8;a>0;a--)
{
P1=temp;
beep=0;
delay(100);
P1=0xff;
beep=1;
delay(100);
temp=_crol_(temp,1);
}
temp=0x7f;
for(a=8;a>0;a--)
{
P1=temp;
beep=0;
delay(100);
P1=0xff;
beep=1;
delay(100);
temp=_cror_(temp,1);
}
}
}
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
用8个发光管演示出8位二进制数累加过程:
^ ~ (按位异或 按位取反)
我的方法:
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
void delay(uint);
void main()
{
uint a,temp;
while(1)
{
a=0x00;
for(temp=256;temp>0;temp--)
{
a++;
P1=~a;
delay(200);
}
}
}
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
课件的方法:把计数值直接定义成uchar型,uchar型范围是0~255,而计数个数是256,正好是0到255共256个数,就不用循环了
#include<reg52.h> //52单片机头文件
#include <intrins.h> //包含有左右循环移位子函数的库
#define uint unsigned int //宏定义
#define uchar unsigned char //宏定义
void delay(uint z) //延时函数,z的取值为这个函数的延时ms数,如delay(200);大约延时200ms.
{ //delay(500);大约延时500ms.
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void main() //主函数
{
uchar a;
while(1) //大循环
{
a++;
P1=~a;
delay(200);
}
}
8个发光管间隔200ms由上至下,再由下至上,再重复一次,然后全部熄灭再以300ms间隔全部闪烁5次。重复此过程:
我的方法:先做8个发光管间隔200ms由上至下,再由下至上,再重复一次,再做然后全部熄灭再以300ms间隔全部闪烁5次
做一部分就看下硬件状况,调节一下,然后再做下一部分,如果有一部分不好使,可以注释掉其它程序,单独调试这部分,也可以单建立工程,单提出来这部分程序进行调试
我的错误片段:因为
void main()
{
uint a;
uchar temp;
while(1)
{
for(temp=2;temp>0; temp--)//总循环跳不出来
{
a=0xfe;
for(temp=8;temp>0;temp--)
{
P1=a;
delay(200);
a=_crol_(a,1);
}
a=0x7f;
for(temp=8;temp>0;temp--)//从这里出来temp的值变化了,再到总循环处,对总循环的temp造成影响,导致总循环跳不出来
{
P1=a;
delay(200);
a=_cror_(a,1);
}
}
a=0xfe;
for(temp=8;temp>0;temp--)
{
P1=a;
delay(200);
a=_crol_(a,1);
}
a=0x7f;
for(temp=8;temp>0;temp--)
{
P1=a;
delay(200);
a=_cror_(a,1);
}
a=0xff;
P1=a;
for(temp=5;temp>0;temp--)
{
delay(300);
a=0x00;
P1=a;
delay(300);
a=0xff;
P1=a;
}
}
}
正确的程序:
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void main()
{
uint a;
uchar temp,untemp;
while(1)
{
for(untemp=2;untemp>0;untemp--)
{
a=0xfe;
for(temp=8;temp>0;temp--)
{
P1=a;
delay(200);
a=_crol_(a,1);
}
a=0x7f;
for(temp=8;temp>0;temp--)
{
P1=a;
delay(200);
a=_cror_(a,1);
}
}
P1=0xff;
for(temp=10;temp>0;temp--)
{
delay(300);
P1=~P1;
}
}
}
间隔300ms第一次一个管亮流动一次,第二次两个管亮流动,依次到8个管亮,然后重复整个过程:
课件的方法:
+ - * / (加 减 乘 除)
> >= < <= (大于 大于等于 小于 小于等于)
== != (测试等于 测试不等于)
&& || ! (逻辑与 逻辑或 逻辑非 )
>> << (位右移 位左移)
& | (按位与 按位或)
^ ~ (按位异或 按位取反)
利用位左移,移入第一位是零,来编写程序
#include<reg52.h> //52单片机头文件
#include <intrins.h> //包含有左右循环移位子函数的库
#define uint unsigned int //宏定义
#define uchar unsigned char //宏定义
void delay(uint z) //延时函数,z的取值为这个函数的延时ms数,如delay(200);大约延时200ms.
{ //delay(500);大约延时500ms.
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void main() //主函数
{
uchar a,i,j;
while(1) //大循环
{
a=0xfe; //赋初值
for(j=0;j<8;j++)
{
for(i=0;i<8-j;i++) //左移
{
P1=a; //点亮小灯
delay(200); //延时200毫秒
a=_crol_(a,1); //将a变量循环左移一位
}
a=_crol_(a,j); //补齐,方便下面的左移一位,通过列出数可以看出此步骤是必需要有的
P1=0xff; //全部关闭
a=a<<1; //左移一位让多一个灯点亮,注意左移后要重新赋给变量
}
}
}
间隔300ms先奇数亮再偶数亮,循环三次;一个灯上下循环三次;两个分别从两边往中间流动三次;再从中间往两边流动三次;8个全部闪烁3次;关闭发光管,程序停止:
一步一步做,做一步调试一步,程序中每两步之间要有空格,这样结构清楚
#include<reg52.h> //52单片机头文件
#include <intrins.h> //包含有左右循环移位子函数的库
#define uint unsigned int //宏定义
#define uchar unsigned char //宏定义
void delay(uint z) //延时函数,z的取值为这个函数的延时ms数,如delay(200);大约延时200ms.
{ //delay(500);大约延时500ms.
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void main() //主函数
{
uchar a,i,j;
for(j=0;j<3;j++) //奇偶交替
{
P1=0x55; //点亮小灯
delay(300); //延时300毫秒
P1=0xaa;
delay(300); //延时300毫秒
}
for(j=0;j<3;j++) //流水灯
{
a=0xfe;
for(i=0;i<8;i++)
{
P1=a; //点亮小灯
delay(300); //延时300毫秒
a=_crol_(a,1);
}
}
P1=0xff;
for(j=0;j<3;j++) //从两边往中间流
{
P1=0x7e; //点亮小灯
delay(300); //延时300毫秒
P1=0xbd;
delay(300); //延时300毫秒
P1=0xdb; //点亮小灯
delay(300); //延时300毫秒
P1=0xe7;
delay(300); //延时300毫秒
}
P1=0xff;
for(j=0;j<3;j++) //从中间往两边流
{
P1=0xe7; //点亮小灯
delay(300); //延时300毫秒
P1=0xdb;
delay(300); //延时300毫秒
P1=0xbd; //点亮小灯
delay(300); //延时300毫秒
P1=0x7e;
delay(300); //延时300毫秒
}
P1=0xff;
for(j=0;j<6;j++) //全部闪烁
{
P1=~P1; //点亮小灯
delay(300); //延时300毫秒
}
P1=0xff;
while(1);//程序停止,把while(1)放在后面
}
郭天祥的10天学会51单片机_第二节相关推荐
- 郭天祥的10天学会51单片机_第十三节
AD软件: AD软件可以编译C语言和VHDL语言等:AD软件的工具栏上面可以输入网络地址进行浏览网页:AD软件可以布差分信号,即可以两条线可以一起布 按住Shift键和左键可以向左移动,按住Shift ...
- 郭天祥的10天学会51单片机_第七节
串行通信:从D0位一位一位发发到D7位 十个位为一帧如:0101000100,表示一个字符 起始位低电平有效,停止位高电平有效,单片机是异步通信 宽带网线是八根线,组成两队差分信号,分别是TXD1(发 ...
- 郭天祥的10天学会51单片机_第三节
单片机管脚,P3口有两个功能,上电默认情况下就使用P3口的普通IO口,当对单片机内部的某些寄存器设置时就启用P3口的第二个功能 P3^4和 P3^5可以作为计时器或定时器使用,给这两个口输入方波,进行 ...
- 10.4.4 51单片机控制系统8个LED“跑马灯”实验
10.4.4 51单片机控制系统8个LED"跑马灯"实验 仿真+代码 方法一 利用数组 #include"reg52.h"#define u8 unsigned ...
- 51单片机学习笔记(郭天祥版)(1)——单片机基础和点亮LED灯
关于单片机型号的介绍: STC89C52RC40C-PDIP 0721CV4336..... STC:STC公司 89:89系列 C:COMS 52(还有51,54,55,58,516,):2表示存储 ...
- 红外测距模块 51单片机_[51单片机] HC-SR04超声波测距仪
1.HC-SR04超声波模块工作原理 (1)采用IO口触发测距,给至少10us高电平脉冲: (2)模块自动发送八个40khz方波,并自主检测是否有电波返回: (3)当有信号返回时,通过IO口输出一个高 ...
- 2440 8字数码管 显示0到10 c语言,51单片机对8位数码管依次显示0-7的设计
共阳极数组0~9:display[]={0xC0,0xF9,0xA4,0xB0,0x91,0xA2,0x82,0xF8,0x80,0x90} 共阳极数组A~F:display[]={0x88,0x83 ...
- 单片机c语言二进制转10进制,51单片机用C语言怎么样把八位二进制转换成十进制...
满意答案 sunzhaoming 2013.07.06 采纳率:41% 等级:12 已帮助:8866人 //******************************************* ...
- 手把手教学51单片机 | 第四节 动态数码管,用6位数码管做一个时钟
1.利用定时器做一个流水灯的程序 //流水灯从上到下一次点亮,然后让全部灯闪烁两次,依次循环 #include<reg52.h> #include<intrins.h> #de ...
- 51单片机_动态数码管显示
动态数码管显示(延时函数) 编程原理 利用延迟函数,每秒钟数码管加1显示,一直加到250.延时函数精度不高,最好使用定时器中断. 数码管动态显示原理 动态数码管显示有段选和位选.段选是单个数码管显示的 ...
最新文章
- alert 回调_element之Alert 警告
- scrapy (2)下载图片及存储信息
- C++的黑科技(深入探索C++对象模型)
- 通过telnet命令查看memcache运行状态
- centos6.8安装zabbix
- 使用Fiddler进行iOS APP的HTTP/HTTPS抓包
- sshd_config 中文手册
- StringBuilder-C#字符串对象
- 基于Flume的美团日志收集系统-----架构和设计
- Oculus关于Internal Error:OVR53225466报错解决方法
- Microsoft Deployment Toolkit build 8456
- C# Socket之TCPUDP
- qq远程控制无法连接服务器,win10系统QQ远程协助,无法控制对方电脑,怎么办?...
- 利用计算机指令清理垃圾,系统运维---教你用dos命令清除系统垃圾的快速方法
- 搭建安卓打包环境,用官方示例anysdk生成apk运行
- 关于生僻字乱码的问题
- yum安装php添加imap模块,php模块安装之imap
- 税费申报计算机代码,C语言编写一个计算个人所得税的程序,要求输入收入金额,能够输...
- 李宏毅学习笔记11.CNN(上)
- 语音合成数据解决方案助您获取专属AI声音
热门文章
- 取消计算机用户密码页面,取消开机密码 Windows电脑开机登录界面取消方法-电脑教程...
- Javascript中的prototype是什么
- u盘插上电脑显示计算机无响应,为什么u盘连接电脑没反应,u盘在电脑上显示不出来...
- html需要背的标签,html的header标签需要怎么使用
- elastic serach学习
- git里面的文件怎么删不掉_.git目录删不掉
- 【渝粤教育】电大中专学前教育学_1作业 题库
- 第八周 项目三--顺序串算法
- 程序员那些必须掌握的排序算法(上)
- Python入门学习二:列表