从业将近十手把手教你单片机程序框架DOC

从业将近十手把手教你单片机程序框架DOC
从业将近十手把手教你单片机程序框架DOC

第一节:吴坚鸿谈初学单片机的误区。

(1)很难记住繁杂的寄存器?寄存器不用死记硬背,鸿哥我行走江湖多年,连一个寄存器都记不住。需要配置寄存器的时候,直接在网上或者书本上参考别人现成的配置程序是上策,查找芯片数据手册是中策,死记硬背寄存器是最最下策。

(2)很难记住繁杂的汇编语言指令?除非是在校学生要应付考试或者少数工作中绕不开汇编,否则学汇编就是浪费时间。鸿哥我行走江湖多年,从来就没有用汇编帮客户做过一个项目。

(3)C语言很难学?你不用学指针,你不用学带形参的函数,你不用学结构体,你不用学宏定义,你不用学文件操作,你也不用死记繁琐的数据类型。你只要会:

5条指令语句switch语句,if else语句,while语句,for语句,=赋值语句。

7个运算符+,-,*,/,|,&,!。

4个逻辑关系符||,&&,!=,==.

3个数据类型unsigned char,unsigned int,unsigned long。

3个进制相互转化,二进制,十六进制,十进制。

1个void函数。

1个一维数组code(或const) unsigned char array[]。

那么世界上任何一种逻辑功能的单片机软件你都能做出来。

鸿哥我当年刚毕业出来工作的时候才知道可以用C语言开发单片机,一开始只用if语句就把项目做出来了,没有用指针,没有用带形参的函数等复杂的功能。再到后来才慢慢开始用C语言其他的高级功能,但是我发现C语言其他的高级功能,本质上都是用我前面列举出来的最基本功能集合而成,只是书写更加简单方便了一点,编译后的机器码都大同小异。所以不会指针等高级功能你不用自卑,恰恰相反,当你会最简单的几个语句,就把这些高级功能的程序都做出来了,你才发现你对底层了解得更加透切,再学那些高级功能轻而易举。当你裸机跑的程序都能够协调得很好的时候,你才发现所谓高深的操作系统也不过如此,只要给你时间和金钱你也可以写个操作系统来玩玩。

(4)很难记住精确时间的计算公式?经常看到时间公式等于晶振,时钟周期,执行指令次数他们之间的乘除关系式。鸿哥我认为这些都是浮云,不用纠结也不用去记,大概了解一下就可以了。不管你对公式掌握得有多精确,你都不可能做出非常精确的时间。想用单片机做一个非常精确的时间这种想法一开始就是错的,不可能的。真想做一个比较精确的时间,应该用外围时钟芯片或者FPGA和CPLD,而不是单片机。

(5)很难记住繁杂的各种通信协议?什么IIC,SPI,232串口通讯,CAN,USB等等。这些都是浮云,你不用记那么多,你只要理解两种通讯方式就够了,那就是串行通讯方式和并行通讯方式。不管世界上有多少种通讯协议,物理世界上只有这两种通讯方式,其他各种名称的通讯协议都基于此两种方式演变而来。

(6)很难写短小精悍的程序?初学者不要纠结于此。做项目开发,程序容量不是刻意追求的目标,程序多一点少一点没关系,现在大容量的单片机品种非常多,容量不会是寸土寸金的事情,我们更加要关注程序的运行效率,可读性和可修改性。

既然鸿哥列出了那么多误区,那么什么才是初学者关注的核心?预知详情,请听下回分解----delay()延时实现LED灯的闪烁。

第二节:delay()延时实现LED灯的闪烁。

开场白:

上一节鸿哥列出了初学者六大误区,到底什么才是初学者关注的核心?那就是裸机奔跑的程序结构。一个好的程序结构,本身就是一个微型的多任务操作系统。鸿哥教给大家的就是如何编写这个简单的操作系统。在main函数循环中用switch语句实现多任务并行处理的任务切换,再外加一个定时器中断,这两者的结合就是鸿哥多年来所有实战项目的核心。鸿哥的程序结构看似简单,实际上就是那么简单。大家不用着急,本篇连载文章现在才正式开始,这一节我

要教会大家两个知识点:

第一点:鸿哥首次提出的“三区一线”理论。此理论把程序代码分成三个区,一个延时分割线。第二点:delay()延时的用途。

(1)硬件平台:基于朱兆祺51单片机学习板。

(2)实现功能:让一个LED闪烁。

(3)源代码讲解如下:

#include "REG52.H"

void initial_myself();

void initial_peripheral();

void delay_short(unsigned int uiDelayshort);

void delay_long(unsigned int uiDelaylong);

void led_flicker();

/* 注释一:

* 吴坚鸿个人的命名风格:凡是输出后缀都是_dr,凡是输入后缀都是_sr。

* dr代表drive驱动,sr代表sensor感应器

*/

sbit led_dr=P3^5;

void main() //学习要点:深刻理解鸿哥首次提出的三区一线理论

{

/* 注释二:

* initial_myself()函数属于鸿哥三区一线理论的第一区,

* 专门用来初始化单片机自己的寄存器以及个别外围要求响应速度快的输出设备,

* 防止刚上电之后,由于输出IO口电平状态不确定而导致外围设备误动作,

* 比如继电器的误动作等等。

*/

initial_myself();

/* 注释三:

* 此处的delay_long()延时函数属于第一区与第二区的分割线,

* 延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定。

* 比如液晶模块,AT24C02存储芯片,DS1302时钟芯片,

* 这类芯片有个特点,一般都是跟单片机进行串口或并口通讯的,

* 并且不要求上电立即处理的。

*/

delay_long(100);

/* 注释四:

* initial_peripheral()函数属于鸿哥三区一线理论的第二区,

* 专门用来初始化不要求上电立即处理的外围芯片和模块.

* 比如液晶模块,AT24C02存储芯片,DS1302时钟芯片。

* 本程序基于朱兆祺51单片机学习板。

*/

initial_peripheral();

/* 注释五:

* while(1){}主函数循环区属于鸿哥三区一线理论的第三区,

* 专门用来编写被循环扫描到的非中断应用程序

*/

while(1)

{

led_flicker(); //LED闪烁应用程序

}

}

void led_flicker() //LED闪烁应用程序

{

led_dr=1; //LED亮

delay_short(50000); //延时50000个空指令的时间

/* 注释六:

* delay_long(100)延时50000个空指令的时间,因为内嵌了一个500次的for循环*/

led_dr=0; //LED灭

delay_long(100); //延时50000个空指令的时间

}

/* 注释七:

* delay_short(unsigned int uiDelayShort)是小延时函数,

* 专门用在时序驱动的小延时,一般uiDelayShort的数值取10左右,

* 最大一般也不超过100.本例为了解释此函数的特点,取值范围超过100。

* 此函数的特点是时间的细分度高,延时时间不宜过长。uiDelayShort数值

* 的大小就代表里面执行了多少条空指令的时间。数值越大,延时越长。

* 时间精度不要刻意去计算,感觉差不多就行。

*/

void delay_short(unsigned int uiDelayShort)

{

unsigned int i;

for(i=0;i

; //一个分号相当于执行一条空语句

}

}

/* 注释八:

* delay_long(unsigned int uiDelayLong)是大延时函数,

* 专门用在上电初始化的大延时,

* 此函数的特点是能实现比较长时间的延时,细分度取决于内嵌for循环的次数,

* uiDelayLong的数值的大小就代表里面执行了多少次500条空指令的时间。

* 数值越大,延时越长。时间精度不要刻意去计算,感觉差不多就行。

*/

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于执行一条空语句

}

}

}

void initial_myself() //初始化单片机

{

led_dr=0; //LED灭

}

void initial_peripheral() //初始化外围

{

; //本例为空

}

总结陈词:

鸿哥首次提出的“三区一线”理论概况了各种项目程序的基本分区。我后续的程序就按此分区编写。

Delay()函数的长延时适用在上电初始化。

Delay()函数的短延时适用在驱动时序的脉冲延时,此时的时间不能太长,本例中暂时没有列出这方面的例子,在后面的章节中会提到。

在本例源代码中,在led_flicker()闪烁应用程序里用到的两个延时delay,它们的延时时间都太长了,在实战项目中肯定不能用这种延时,因为消耗的时间太长了,其它任务根本没有机会执行。那怎么办呢?我们应该如何改善?欲知详情,请听下回分解-----累计主循环次数使LED灯闪烁。

第三节:累计主循环次数使LED灯闪烁。

开场白:

上一节鸿哥提到delay()延时函数消耗的时间太长了,其它任务根本没有机会执行,我们该怎么改善?本节教大家利用累计主循环次数的方法来解决这个问题。这一节要教会大家两个知识点:

第一点:利用累计主循环次数的方法实现时间延时

第二点:switch核心语句之初体验。鸿哥所有的实战项目都是基于switch语句实现多任务并行处理。

(1)硬件平台:基于朱兆祺51单片机学习板。

(2)实现功能:让一个LED闪烁。

(3)源代码讲解如下:

#include "REG52.H"

/* 注释一:

* const_time_level是统计循环次数的设定上限,数值越大,LED延时的时间越久

*/

#define const_time_level 10000

void initial_myself();

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void led_flicker();

sbit led_dr=P3^5;

/* 注释二:

* 吴坚鸿个人的命名风格:凡是switch语句里面的步骤变量后缀都是Step.

* 前缀带uc,ui,ul分别表示此变量是unsigned char,unsigned int,unsigned long.

*/

unsigned char ucLedStep=0; //步骤变量

unsigned int uiTimeCnt=0; //统计循环次数的延时计数器

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

led_flicker();

}

}

void led_flicker() ////第三区LED闪烁应用程序

{

{

case 0:

/* 注释三:

* uiTimeCnt累加循环次数,只有当它的次数大于或等于设定上限const_time_level时,

* 才会去改变LED灯的状态,否则CPU退出led_flicker()任务,继续快速扫描其他的任务,* 这样的程序结构就可以达到多任务并行处理的目的。

* 本程序基于朱兆祺51单片机学习板

*/

uiTimeCnt++; //累加循环次数,

if(uiTimeCnt>=const_time_level) //时间到

{

uiTimeCnt=0; //时间计数器清零

led_dr=1; //让LED亮

ucLedStep=1; //切换到下一个步骤

}

break;

case 1:

uiTimeCnt++; //累加循环次数,

if(uiTimeCnt>=const_time_level) //时间到

{

uiTimeCnt=0; //时间计数器清零

led_dr=0; //让LED灭

ucLedStep=0; //返回到上一个步骤

}

break;

}

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于执行一条空语句

}

}

}

void initial_myself() //第一区初始化单片机

{

led_dr=0; //LED灭

}

void initial_peripheral() //第二区初始化外围

{

; //本例为空

}

总结陈词:

在实际项目中,用累计主循环次数实现时间延时是一个不错的选择。这种方法能胜任多任务处理的程序框架,但是它本身也有一个小小的不足。随着主函数里任务量的增加,我们为了保证延时时间的准确性,要不断修正设定上限const_time_level 。我们该怎么解决这个问题呢?欲知详情,请听下回分解-----累计定时中断次数使LED灯闪烁。

第四节:累计定时中断次数使LED灯闪烁。

开场白:

上一节提到在累计主循环次数来实现计时,随着主函数里任务量的增加,为了保证延时时间的准确性,要不断修正设定上限阀值const_time_level 。我们该怎么解决这个问题呢?本节教大家利用累计定时中断次数的方法来解决这个问题。这一节要教会大家四个知识点:

第一点:利用累计定时中断次数的方法实现时间延时

第二点:展现鸿哥最完整的实战程序框架。在主函数循环里用switch语句实现状态机的切换,在定时中断里累计中断次数,这两个的结合就是我写代码最本质的框架思想。

第三点:提醒大家C语言中的int ,long变量是由几个字节构成的数据,凡是在main函数和中断函数里有可能同时改变的变量,这个变量应该在主函数中被更改之前,先关闭相应的中断,更改完了此变量,再打开中断,否则会留下不宜察觉的漏洞。当然在大部分的项目中可以不用这么操作,但是在一些要求非常高的项目中,有一些核心变量必须这么做。

第四点:定时中断的初始值该怎么设置。不用严格按公式来计算时间,一般取个经验值是最大初始值减去1000就可以了。

具体内容,请看源代码讲解。

(1)硬件平台:基于朱兆祺51单片机学习板。

(2)实现功能:让一个LED闪烁。

(3)源代码讲解如下:

#include "REG52.H"

#define const_time_level 200

void initial_myself();

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void led_flicker();

void T0_time(); //定时中断函数

sbit led_dr=P3^5;

unsigned char ucLedStep=0; //步骤变量

unsigned int uiTimeCnt=0; //统计定时中断次数的延时计数器

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

led_flicker();

}

}

void led_flicker() ////第三区LED闪烁应用程序

{

switch(ucLedStep)

{

case 0:

/* 注释一:

* uiTimeCnt累加定时中断的次数,每一次定时中断它都会在中断函数里自加一。

* 只有当它的次数大于或等于设定上限const_time_level时,

* 才会去改变LED灯的状态,否则CPU退出led_flicker()任务,继续快速扫描其他的任务,

* 这样的程序结构就可以达到多任务并行处理的目的。这就是鸿哥在所有开发项目中的核心框架。*/

if(uiTimeCnt>=const_time_level) //时间到

{

/* 注释二:

* ET0=0;uiTimeCnt=0;ET0=1;----在清零uiTimeCnt之前,为什么要先禁止定时中断?

* 因为uiTimeCnt是unsigned int类型,本质上是由两个字节组成。

* 在C语言中uiTimeCnt=0看似一条指令,实际上经过编译之后它不只一条汇编指令。

* 由于定时中断函数里也对这个变量进行累加操作,如果不禁止定时中断,

* 那么uiTimeCnt这个变量在main()函数中还没被完全清零的时候,如果这个时候

* 突然来一个定时中断,并且在中断里又更改了此变量,这种情况在某些要求高的

* 项目上会是一个不容易察觉的漏洞,为项目带来隐患。当然,大部分的普通项目,

* 都可以不用那么严格,可以不用禁止定时中断。在这里只是提醒各位初学者有这种情况。

*/

ET0=0; //禁止定时中断

uiTimeCnt=0; //时间计数器清零

ET0=1; //开启定时中断

led_dr=1; //让LED亮

ucLedStep=1; //切换到下一个步骤

}

break;

case 1:

if(uiTimeCnt>=const_time_level) //时间到

{

ET0=0; //禁止定时中断

uiTimeCnt=0; //时间计数器清零

ET0=1; //开启定时中断

led_dr=0; //让LED灭

ucLedStep=0; //返回到上一个步骤

}

break;

}

}

/* 注释三:

* C51的中断函数格式如下:

* void 函数名() interrupt 中断号

* {

* 中断程序内容

* }

* 函数名可以随便取,只要不是编译器已经征用的关键字。

* 这里最关键的是中断号,不同的中断号代表不同类型的中断。* 定时中断的中断号是1.至于其它中断的中断号,大家可以查找* 相关书籍和资料。大家进入中断时,必须先清除中断标志,并且* 关闭中断,然后再写代码,最后出来时,记得重装初始值,并且* 打开中断。

*/

void T0_time() interrupt 1

{

TF0=0; //清除中断标志

TR0=0; //关中断

if(uiTimeCnt<0xffff) //设定这个条件,防止uiTimeCnt超范围。 {

uiTimeCnt++; //累加定时中断的次数,

}

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

TR0=1; //开中断

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于执行一条空语句

}

}

}

void initial_myself() //第一区初始化单片机

{

/* 注释四:

* 单片机有几个定时器,每个定时器又有几种工作方式,

* 那么多种变化,我们记不了那么多,怎么办?

* 大家记住鸿哥的话,无论一个单片机有多少内置资源,

* 我们做系统框架的,只需要一个定时器,一种工作方式。

* 开定时器越多这个系统越不好。需要哪种定时工作方式呢?

* 就需要响应定时中断后重装一下初始值继续跑那种。

* 在51单片机中就是工作方式1。其它的工作方式很少项目能用到。

*/

TMOD=0x01; //设置定时器0为工作方式1

/* 注释五:

* 装定时器的初始值,就像一个水桶里装的水。如果这个桶是空桶,那么想

* 把这个桶灌满水的时间就很长,如果是里面已经装了大半的水,那么想

* 把这个桶灌满水的时间就相对比较短。也就是定时器初始值越小,产生一次

* 定时中断的时间就越长。如果初始值太小了,每次产生定时中断

* 的时间分辨率太粗,如果初始值太大了,虽然每次产生定时中断的时间分辨率很细,* 但是太频繁的产生中断,不但会影响主函数main()的执行效率,而且累记中断次数

* 的时间误差也会很大。凭鸿哥多年的江湖经验,

* 我觉得最大初始值减去2000是比较好的经验值。当然,大一点小一点没关系。不要走

* 两个极端就行。

*/

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

led_dr=0; //LED灭

}

void initial_peripheral() //第二区初始化外围

{

EA=1; //开总中断

ET0=1; //允许定时中断

TR0=1; //启动定时中断

}

总结陈词:

本节程序麻雀虽小五脏俱全。在本节中已经展示了我最完整的实战程序框架。

本节程序只有一个LED灯闪烁的单任务,如果要多增加一个任务来并行处理,该怎么办?

欲知详情,请听下回分解-----蜂鸣器的驱动程序。

第五节:蜂鸣器的驱动程序。

开场白:

上一节讲了利用累计定时中断次数实现LED灯闪烁,这个例子同时也第一次展示了我最完整的实战程序框架:用switch语句实现状态机,外加定时中断。这个框架看似简单,实际上就是那么简单。我做的所有开发项目都是基于这个简单框架,但是非常好用。上一节只有一个单任务的LED灯在闪烁,这节开始,我们多增加一个蜂鸣器报警的任务,要教会大家四个知识点:

第一点:蜂鸣器的驱动程序框架编写。

第二点:多任务处理的程序框架。

第三点:如何控制蜂鸣器声音的长叫和短叫。

第四点:如何知道1秒钟需要多少个定时中断,也就是如何按比例修正时间精度。

具体内容,请看源代码讲解。

(1)硬件平台:基于朱兆祺51单片机学习板。

(2)实现功能:同时跑两个任务,第一个任务让一个LED灯1秒钟闪烁一次。第二个任务让蜂鸣器在前面3秒发生一次短叫报警,在后面6秒发生一次长叫报警,反复循环。

(3)源代码讲解如下:

#include "REG52.H"

/* 注释一:

* 如何知道1秒钟需要多少个定时中断?

* 这个需要编写一段小程序测试,得到测试的结果后再按比例修正。

* 步骤:

* 第一步:在程序代码上先写入1秒钟大概需要200个定时中断。

* 第二步:基于以上1秒钟的基准,编写一个60秒的简单测试程序(如果编写超过

* 60秒的时间,这个精度还会更高)。比如,编写一个用蜂鸣器的声音来识别计时的

* 起始和终止的测试程序。

* 第三步:把程序烧录进单片机后,上电开始测试,手上同步打开手机里的秒表。

* 如果单片机仅仅跑了27秒。

* 第四步:那么最终得出1秒钟需要的定时中断次数是:const_time_1s=(200*60)/27=444 */

#define const_time_05s 222 //0.5秒钟的时间需要的定时中断次数

#define const_time_1s 444 //1秒钟的时间需要的定时中断次数

#define const_time_3s 1332 //3秒钟的时间需要的定时中断次数

#define const_time_6s 2664 //6秒钟的时间需要的定时中断次数

#define const_voice_short 40 //蜂鸣器短叫的持续时间

#define const_voice_long 200 //蜂鸣器长叫的持续时间

void initial_myself();

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void led_flicker();

void alarm_run();

void T0_time(); //定时中断函数

sbit beep_dr=P2^7; //蜂鸣器的驱动IO口

sbit led_dr=P3^5; //LED灯的驱动IO口

unsigned char ucLedStep=0; //LED灯的步骤变量

unsigned int uiTimeLedCnt=0; //LED灯统计定时中断次数的延时计数器

unsigned char ucAlarmStep=0; //报警的步骤变量

unsigned int uiTimeAlarmCnt=0; //报警统计定时中断次数的延时计数器

unsigned int uiVoiceCnt=0; //蜂鸣器鸣叫的持续时间计数器

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

led_flicker(); //第一个任务LED灯闪烁

alarm_run(); //第二个任务报警器定时报警

}

}

void led_flicker() //第三区LED闪烁应用程序

{

switch(ucLedStep)

{

case 0:

if(uiTimeLedCnt>=const_time_05s) //时间到

{

uiTimeLedCnt=0; //时间计数器清零

led_dr=1; //让LED亮

ucLedStep=1; //切换到下一个步骤

}

break;

case 1:

if(uiTimeLedCnt>=const_time_05s) //时间到

{

uiTimeLedCnt=0; //时间计数器清零

led_dr=0; //让LED灭

ucLedStep=0; //返回到上一个步骤

}

break;

}

}

void alarm_run() //第三区报警器的应用程序

{

switch(ucAlarmStep)

{

case 0:

if(uiTimeAlarmCnt>=const_time_3s) //时间到

{

uiTimeAlarmCnt=0; //时间计数器清零

/* 注释二:

* 只要变量uiVoiceCnt不为0,蜂鸣器就会在定时中断函数里启动鸣叫,并且自减uiVoiceCnt

* 直到uiVoiceCnt为0时才停止鸣叫。因此控制uiVoiceCnt变量的大小就是控制声音的长短。*/

uiVoiceCnt=const_voice_short; //蜂鸣器短叫

ucAlarmStep=1; //切换到下一个步骤

}

break;

case 1:

if(uiTimeAlarmCnt>=const_time_6s) //时间到

{

uiTimeAlarmCnt=0; //时间计数器清零

uiVoiceCnt=const_voice_long; //蜂鸣器长叫

ucAlarmStep=0; //返回到上一个步骤

}

break;

}

}

void T0_time() interrupt 1

{

TF0=0; //清除中断标志

TR0=0; //关中断

if(uiTimeLedCnt<0xffff) //设定这个条件,防止uiTimeLedCnt超范围。

{

uiTimeLedCnt++; //LED灯的时间计数器,累加定时中断的次数,

}

if(uiTimeAlarmCnt<0xffff) //设定这个条件,防止uiTimeAlarmCnt超范围。

{

uiTimeAlarmCnt++; //报警的时间计数器,累加定时中断的次数,

}

/* 注释三:

* 为什么不把驱动蜂鸣器这段代码放到main函数的循环里去?

* 因为放在定时中断里,能保证蜂鸣器的声音长度是一致的,

* 如果放在main循环里,声音的长度就有可能受到某些必须

* 一气呵成的任务干扰,得不到及时响应,影响声音长度的一致性。

*/

if(uiVoiceCnt!=0)

{

uiVoiceCnt--; //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫 beep_dr=0; //蜂鸣器是PNP三极管控制,低电平就开始鸣叫。

}

else

{

; //此处多加一个空指令,想维持跟if括号语句的数量对称,都是两条指令。不加也可以。

beep_dr=1; //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。

}

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

TR0=1; //开中断

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于执行一条空语句

}

}

}

void initial_myself() //第一区初始化单片机

{

beep_dr=1; //用PNP三极管控制蜂鸣器,输出高电平时不叫。

led_dr=0; //LED灭

TMOD=0x01; //设置定时器0为工作方式1

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

}

void initial_peripheral() //第二区初始化外围

{

EA=1; //开总中断

ET0=1; //允许定时中断

TR0=1; //启动定时中断

}

总结陈词:

本节程序已经展示了一个多任务处理的基本思路,假如要实现一个独立按键检测,能不能也按照这种思路来处理呢?欲知详情,请听下回分解-----在主函数中利用累计主循环次数来实现独立按键的检测。

第六节:在主函数中利用累计主循环次数来实现独立按键的检测。

开场白:

上一节讲了多任务中蜂鸣器驱动程序的框架,这节继续利用多任务处理的方式,在主函数中利用累计主循环次数来实现独立按键的检测。要教会大家四个知识点:

第一点:独立按键的驱动程序框架。

第二点:用累计主循环次数来实现去抖动的延时。

第三点:灵活运用防止按键不松手后一直触发的按键自锁标志。

第四点:在按键去抖动延时计时中,添加一个抗干扰的软件监控判断。一旦发现瞬间杂波干扰,马上把延时计数器清零。这种方法是我在复杂的工控项目中总结出来的。以后凡是用到开关感应器的地方,都可以用类似的方法实现软件上的抗干扰处理。

具体内容,请看源代码讲解。

(1)硬件平台:基于朱兆祺51单片机学习板。用矩阵键盘中的S1和S5号键作为独立按键,记得把输出线P0.4一直输出低电平,模拟独立按键的触发地GND。(2)实现功能:有两个独立按键,每按一个独立按键,蜂鸣器发出“滴”的一声后就停。

(3)源代码讲解如下:

#include "REG52.H"

#define const_voice_short 40 //蜂鸣器短叫的持续时间

/* 注释一:

* 调整抖动时间阀值的大小,可以更改按键的触发灵敏度。

* 去抖动的时间本质上等于累计主循环次数的时间。

*/

#define const_key_time1 500 //按键去抖动延时的时间

#define const_key_time2 500 //按键去抖动延时的时间

void initial_myself();

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void T0_time(); //定时中断函数

void key_service(); //按键服务的应用程序

void key_scan(); //按键扫描函数

sbit key_sr1=P0^0; //对应朱兆祺学习板的S1键

sbit key_sr2=P0^1; //对应朱兆祺学习板的S5键

sbit key_gnd_dr=P0^4; //模拟独立按键的地GND,因此必须一直输出低电平

sbit beep_dr=P2^7; //蜂鸣器的驱动IO口

unsigned char ucKeySec=0; //被触发的按键编号

unsigned int uiKeyTimeCnt1=0; //按键去抖动延时计数器

unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志

unsigned int uiKeyTimeCnt2=0; //按键去抖动延时计数器

unsigned char ucKeyLock2=0; //按键触发后自锁的变量标志

unsigned int uiVoiceCnt=0; //蜂鸣器鸣叫的持续时间计数器

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

key_scan(); //按键扫描函数

key_service(); //按键服务的应用程序

}

}

void key_scan()//按键扫描函数

{

/* 注释二:

* 独立按键扫描的详细过程:

* 第一步:平时没有按键被触发时,按键的自锁标志和去抖动延时计数器一直被清零。

* 第二步:一旦有按键被按下,去抖动延时计数器开始累加,在还没累加到

* 阀值const_key_time1时,如果在这期间由于受外界干扰或者按键抖动,而使

* IO口突然瞬间触发成高电平,这个时候马上又把延时计数器uiKeyTimeCnt1

* 清零了,这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。这是我实战中摸索出来的。* 以后凡是用到开关感应器的时候,都可以用类似这样的方法去干扰。

* 第三步:如果按键按下的时间超过了阀值const_key_time1,则触发按键,把编号ucKeySec赋值。

* 同时,马上把自锁标志ucKeyLock1置位,防止按住按键不松手后一直触发。

* 第四步:等按键松开后,自锁标志ucKeyLock1及时清零,为下一次自锁做准备。

* 第五步:以上整个过程,就是识别按键IO口下降沿触发的过程。

*/

if(key_sr1==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位

{

ucKeyLock1=0; //按键自锁标志清零

uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。 }

else if(ucKeyLock1==0)//有按键按下,且是第一次被按下

{

++uiKeyTimeCnt1; //延时计数器

if(uiKeyTimeCnt1>const_key_time1)

{

uiKeyTimeCnt1=0;

ucKeyLock1=1; //自锁按键置位,避免一直触发

ucKeySec=1; //触发1号键

}

}

if(key_sr2==1)

{

ucKeyLock2=0;

uiKeyTimeCnt2=0;

}

else if(ucKeyLock2==0)

{

++uiKeyTimeCnt2;

if(uiKeyTimeCnt2>const_key_time2)

{

uiKeyTimeCnt2=0;

ucKeyLock2=1;

ucKeySec=2; //触发2号键

}

}

}

void key_service() //第三区按键服务的应用程序

{

switch(ucKeySec) //按键服务状态切换

{

case 1:// 1号键对应朱兆祺学习板的S1键

uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发

break;

case 2:// 2号键对应朱兆祺学习板的S5键

uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发

break;

}

}

void T0_time() interrupt 1

{

TF0=0; //清除中断标志

TR0=0; //关中断

if(uiVoiceCnt!=0)

{

uiVoiceCnt--; //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫 beep_dr=0; //蜂鸣器是PNP三极管控制,低电平就开始鸣叫。

}

else

{

; //此处多加一个空指令,想维持跟if括号语句的数量对称,都是两条指令。不加也可以。

beep_dr=1; //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。

}

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

TR0=1; //开中断

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于执行一条空语句

}

}

}

void initial_myself() //第一区初始化单片机

{

/* 注释三:

* 矩阵键盘也可以做独立按键,前提是把某一根公共输出线输出低电平,

* 模拟独立按键的触发地,本程序中,把key_gnd_dr输出低电平。

* 朱兆祺51学习板的S1和S5两个按键就是本程序中用到的两个独立按键。

*/

key_gnd_dr=0; //模拟独立按键的地GND,因此必须一直输出低电平

beep_dr=1; //用PNP三极管控制蜂鸣器,输出高电平时不叫。

TMOD=0x01; //设置定时器0为工作方式1

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

}

void initial_peripheral() //第二区初始化外围

{

EA=1; //开总中断

ET0=1; //允许定时中断

TR0=1; //启动定时中断

}

总结陈词:

本节程序已经展示了在主函数中,利用累计主循环次数来实现独立按键的检测。这种方法我经常在实战用应用,但是它也有一个小小的不足,随着在主函数循环中任务量的增加,为了保证去抖动延时的时间一致性,要适当调整一下去抖动的阀值const_key_time1。如何解决这个问题呢?欲知详情,请听下回分解-----在主函数中利用累计定时中断的次数来实现独立按键的检测。

第七节:在主函数中利用累计定时中断的次数来实现独立按键的检测。

开场白:

上一节讲了在主函数中利用累计主循环次数来实现独立按键的检测,但是它也有一个小小的不足,随着在主函数中任务量的增加,为了保证去抖动延时的时间一致性,要适当调整一下去抖动的时间阀值const_key_time1。如何解决这个问题呢?这一节教大家在主函数中利用累计定时中断的次数来实现独立按键的检测,

51单片机常用子程序汇总

目录 1、通过串口连续发送n个字节的数据 /*************************************************************** 模块功能:通过串口连续发送n个字节的数据 参数说明: s:待发送数据的首地址 n:要发送数据的字节数 ***************************************************************/ void SendD(unsigned char *s,unsigned char n) { unsigned char unX; if(n>0) { ES=0; // 关闭串口中断 for(unX=0;unX #include #define Nop() _nop_() //空指令

sbit SDA=P1^3; sbit SCL=P1^2; bit ACK; void Start_I2c() { SDA=1; Nop(); SCL=1; Nop(); Nop(); Nop(); Nop(); Nop(); SDA=0; Nop(); Nop(); Nop(); Nop(); Nop(); SCL=0; //钳住I2C总线,准备发送或接受数据Nop(); Nop(); } (2)结束总线函数 /*************************************************************** 模块功能:发送I2C总线结束条件 ***************************************************************/ void Stop_I2c() { SDA=0; Nop(); SCL=1; Nop(); Nop(); Nop(); Nop(); Nop(); SDA=1; Nop(); Nop(); Nop(); Nop();

手把手教你STC51的ISP下载线

手把手教你STC51的ISP下载线 说起我从认识学习使用C51单片机到现在有两年多,时间不长,菜鸟一只。从用TOP151烧写AT89C51,到用easy51pro在线编程AT89S51,再到用STC-ISP 软件在线编程STC89C51,最后现在变得越来越懒,干脆用protues仿真单片机外围电路。 现在简单的总结一下,入门级的C51学习在没有昂贵的单片机仿真器情况下,怎样算是方便调试又花费少吧。 先说说AT89C51,噢,差点忘了,这型号的单片机不知何年被停产了,现在就靠它的库存仍在这个历史的舞台上挣扎。 缺点:对入土为安的芯片没什么好说了。 那就说AT89S51,这可是一个令人振奋的产物,最大的特点莫过于它的ISP(在线编程)功能,就是使用者每编译好程序,就可以立即通过ISP下载线写到单片机上去。而且ISP下载线的制作简单令单片机和我们的距离更加接近了。它的ISP原理图如下:

其中ISP下载程序可以用easy 51pro v2.0。相比昂贵的仿真器,做上图的元器件总共也就十块钱左右吧。 缺点:一、并口连接电脑,1.可能占用打印机口;2.是笔记本是没有并口的。 二、下载线制作一次成功率不大,不是漏接了这个脚就是那个口,对于新手而言尤其这样。 三、下载线寿命不长,一两次不知明的原因(通常静电),就可以把里面的那块芯片(74LS244)烧坏。并且,实际你都不知道到底哪里出毛病了。 也许,世界上真的没有最好,只要更好,自从好友张JL和陈Y介绍了STC的51系列单片机给我之后,发现竟然有这么方便好用功能强大的单片机。

STC51单片机的型号跟ATMEL的大致一样,有STC89C51,C52等,对应于AT89C51,C52等对应它们的内部RAM内部ROM中断口等,是完全一样的。 当然,STC系列单片机是改进型的单片机,它的热重启,串口ISP等功能确实为我准备介绍给大家提供了理由。 先说说ISP功能,它跟电脑连接就只有三根线,就是通过RS-232传输。它ISP 过程是这样的:冷重启(上电)-单片机运行系统ISP监控程序(出厂时已烧到里面)-检测P3.0/RXD有没有合法下载命令流,有的话,就下载用户程序进户程序区;没有的话,就跳到用户程序区,运行用户程序。所以,第一次下载程序,用户需要先点ISP下载软件的“download”,再把单片机通电。如图: 到了这里,大家不禁会说,下载线虽然简单,但每次都要断电上电,烦不烦?答:我都觉得烦。不过眼睛锐利的读者发现了上图右下片有一段文字。说什么的呢?哦,原来是自定义下载。什么是自定义下载?首先我先说个高兴的事儿——用自定义下载,从此告别断电上电的冷重启ISP下载。 所谓自定义下载,就是我从上面软件的自定义下载命令文本框中打入十六进制数字(如:FEH)然后点击发送,程序自动下载到用户单片机里。神奇吧。究其不用断电上电冷重启的原因,就是上面我所说的STC单片机具有热重启功能。用户只需简单控制ISP_CONTOR特殊功能寄存器即可实现系统复位了。汇编语

单片机实训心得

沧州职业技术学院单片机实训报告 心得体会 为期一周的单片机实训结束了,真是让我受益匪浅啊!学到了很多东西,不管怎么样,先感谢学校给我的这么多机会,真正的学到了东西。 随着电子技术的发展,特别是随着大规模集成电路的产生,给人们的生活带来了根本性的变化,我们就学习了单片机这门课程,感觉是有点难。也不知道整个学习过程是怎么过来得,可是时间不等人。不过在学习中,我才发现学习单片机不仅仅需要软件的知识,还需要硬件的知识。我买了一个单片机在实践中就是一个活生生的例子,没有相应的硬件知识,我连单片机怎么和电脑相连都不知道,我为我当初的想法感到羞愧。单片机是一门很好的学问,需要我去钻研它。 不过在学习中,我才发现学习单片机不仅仅需要软件的知识,还需要硬件的知识。我买了一个单片机在实践中就是一个活生生的例子,没有相应的硬件知识,我连单片机怎么和电脑相连都不知道,我为我当初的想法感到羞愧。单片机是一门很好的学问,需要我去钻研它。 时光飞逝,一转眼,一个学期又进尾声了,本学期的单片机综合课程设计也在一周内完成了。俗话说“好的开始是成功的一半”。说起课程设计,我认为最重要的就是做好设计的预习,认真的研究老师给的题目,选一个自己有兴趣的题目。其次,老师对实验的讲解要一丝不苟的去听去想,因为只有都明白了,做起设计就会事半功倍,如果没弄明白,就迷迷糊糊的去选题目做设计,到头来一点收获也没有。最后,要重视程序的模块化,修改的方便,也要注重程序的调试,掌握其方法。 在全组人竭尽全力,老师的精心指导下,程序基本编写成功,这是我们共同努力的结果,在享受我们成果之时,不得不感慨单片机的重要性与高难度性,所以为期一周的单片机课程设计没有浪费我我们学到了很多知识,也让我们对单片机有了更深一步的了解,虽然最后结果是出来了,可这与老师的精心指导是分不开的她引导我们的思路,本来一窍不通的我们经过老师的点拨基本上通了,所以老师是功不可没的。 总而言之,单片机课程设计对于我们有很大的帮助,我们从中受益匪浅。

汇编51单片机考试常见试题

一、填空题 1.单片机是把中央处理器、存储器、定时器/计数器以及I/O接口电路等主要计算机部件集成在一块集成电路芯片上的微型计算机。 2.除了单片机这一名称之外,单片机还可称为微控制器、嵌入式控制器。 3.计算机的系统总线有地址总线、控制总线和数据总线。 4.80C51单片机基本型内部RAM有 128 个字节单元,这些单元可以分为三个用途不同的区域,一是工作寄存器区、二是位寻址区、三是数据缓冲区。5.8051单片机有2 个16位定时/计数器。 6.单片机存储器的主要功能是存储程序和数据。80C51含4 KB掩膜ROM。7.80C51在物理上有4个独立的存储器空间。 8.通常、单片机上电复位时PC= 0000H,SP= 07H;而工作寄存器则缺省采用第00 组,这组寄存器的地址范围是从00H~ 07H。 9.8051的堆栈是向地址的高端生成的。入栈时SP先加1,再压入数据。10.使用8031芯片时,需将/EA引脚接低电平,因为其片内无程序存储器。11.MCS-51特殊功能寄存器只能采用直接寻址方式。 12.汇编语言中可以使用伪指令,它们不是真正的指令,只是用来对汇编过程进行某种控制。 13.半导体存储器的最重要的两个指标是存储容量和存储速度。 14.当PSW4=1,PSW3=0时,工作寄存器Rn,工作在第2组。 15.在8051单片机中,由 2 个振荡(晶振)周期组成1个状态(时钟)周期,由 6个状态周期组成1个机器周期。 16.假定累加器A的内容30H,执行指令:1000H:MOVC A,@A+PC后,把程序存储器1031H单元的内容送累加器A中。 17.MCS-51单片机访问外部存储器时,利用ALE信号锁存来自P0口的低8位地址信号。 18.内部RAM中,位地址为30H的位,该位所在字节的字节地址为26H。 19.若A中的内容为63H,那么,P标志位的值为0。 20.在基址加变址寻址方式中,以累加器A作变址寄存器,以DPTR或PC作基址寄存器。 21.指令格式是由操作码和操作数所组成,也可能仅由操作码组成。 22.通过堆栈操作实现子程序调用,首先就要把PC的内容入栈,以进行断点保护。调用返回时,再进行出栈保护,把保护的断点送回到PC。 23.MCS-51单片机程序存储器的寻址范围是由程序计数器PC的位数所决定的,因为MCS-51的PC是16位的,因此其寻址的范围为64KB。 24.在寄存器间接寻址方式中,其“间接”体现在指令中寄存器的内容不是操作数,而是操作数的地址。 25.假定累加器A中的内容为30H,执行指令1000H:MOVC A,@A+PC 后,把程序存储器1031H单元的内容送入累加器A中。 26.12根地址线可寻址4 KB存储单元。 27.:假定A=55H,R3=0AAH,在执行指令ANL A,R3后,A=00H,R3=0AAH。28.MCS-51的P0口作为输出端口时,每位能驱动8个LSTTL负载。 29.MCS-51有4个并行I/O口,其中P1~P3是准双向口,所以由输出转输入时必须先写入“1”。 30.MCS-51的堆栈是软件填写堆栈指针临时在片内数据存储器内开辟的区域。

51单片机实验报告94890

《单片机与接口技术》实验报告 信息工程学院 2016年9月

辽东学院信息技术学院 《单片机与接口技术》实验报告 姓名:王瑛 学号: 0913140319 班级: B1403 专业:网络工程 层次:本科 2016年9月

目录 实验题目:实验环境的初识、使用及调试方法(第一章) 实验题目:单片机工程初步实验(第二章) 实验题目:基本指令实验(第三章)4 实验题目:定时器/计数器实验(第五章)4 实验题目:中断实验(第六章)4 实验题目:输入接口实验(第八章)4 实验题目:I/O口扩展实验(第九章)4 实验题目:串行通信实验(第十一章)4 实验题目:A/D,D/A转换实验(第十七章)4

实验题目:实验环境的初识、使用及调试方法实验 实验类型:验证性实验课时: 1 时间:2016年10月24日 一、实验内容和要求 了解单片机的基础知识 了解51单片机的组成和工作方法 掌握项目工程的建立、编辑、编译和下载的过程方法 熟练单片机开发调试工具和方法 二、实验结果及分析 单片机最小系统的构成: Keil集成开发环境:

STC-ISP:

实验题目:单片机工程初步实验 实验类型:验证性实验课时: 1 时间:2016 年10 月24 日一、实验内容和要求 点亮一个LED小灯 程序下载到单片机中 二、实验结果及分析 1、点亮一个LED小灯 点亮LED小灯的程序: #include //包含特殊功能寄存器定义的头文件 sbit LED = P0^0; sbit ADDR0 = P1^0; //sbit必须小写,P必须大写 sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; void main() { ENLED = 0; ADDR3 = 1; ADDR2 = 1; ADDR1 = 1; ADDR0 = 0; LED = 0; //点亮小灯 while (1); //程序停止 } 2、程序下载 首先,我们要把硬件连接好,把板子插到我们的电脑上,打开设备管理器查看所使用的COM 口,如图所示:

单片机的各种程序

单片机的各种程序 1. 八个灯循环点亮 ORG 0030H START:MOV SP,#5FH MOV R2,#08H MOV A,#0FEH NEXT:MOV P1,A ACALL DELAY RL A DJNZ R2,NEXT MOV R2,#08H MOV A,#7FH NEXT1:MOV P1,A ACALL DELAY RR A DJNZ R2,NEXT1 SJMP START DELAY:MOV R3,#0FFH DEL1:MOV R4,#0FFH DJNZ R4,$ DJNZ R3,DEL1 RET END 2. 查表的例子 org 0000h start: mov dptr,#ledtab movc a,@a+dptr mov p0,a sjmp start ledtab: db:0c0h,0f9h,04h,0b0h,99h,92h,82h,0f8h,80h end https://www.360docs.net/doc/b59436169.html, 0000H MOV A,#0FEH SHIFT: LCALL FLASH

RL A SJMP SHIFT FLASH: MOV R2,0AH FLASH1:MOV P1,A LCALL DELAY MOV P1,#0FFH LCALL DELAY DJNZ R2,FLASH1 RET DELAY:MOV R5,#200 D1:MOV R6,#123 NOP DJNZ R6,$ DJNZ R5,D1 RET 4.数码显示管显示2015循环 org 0000h start: loop: mov p1,#0c0h lcall DELAY mov p1,#0f9h lcall DELAY mov p1,#0a4h lcall DELAY mov p1,#0b0h lcall DELAY mov p1,#99h lcall DELAY mov p1,#92h lcall DELAY mov p1,#82h lcall DELAY mov p1,#0f8h lcall DELAY mov p1,#80h lcall DELAY

云龙51单片机视频教程大全

云龙51单片机视频教程简介 本视频教程是针对YL-51单片机开发板讲的配套DVD视频教程目录: 讲次内容细节 第一课如何学好单片机单片机能做什么,学习单片机需要什么,如何学好单片机技术。 第二课预备知识点亮一个发光管认识单片机由来及内部结构,单片机最小工作单元组成;单片机开发软件操作:KEIL软件开发环境认识、单片机烧录软件使用。 第三课预备知识 C51基础知识及流水灯设计简单延时程序、子程序调用、、流水灯同时蜂鸣器响、如何驱动蜂鸣器,及如何驱动继电器,集电极开路的概念及应用。 第四课数码管显示的原理,数码管的静态显示共阳、共阴数码管显示原理、带参数子程序设计。 第五课中断和定时器原理定时器工作方式介绍、重点讲述工作方式2、中断概念及中断函数写法、定时器中断应用 第六课数码管的动态显示原理及应用实现动态扫描概念及定时器、中断加深 第七课按键学习:独立按键和矩阵按键键盘检测、消抖、键盘编码、带返回值函数写法及应用 第八课数模转换(DA)工作原理及应用数字电压与模拟电压的关系、如何使用DAC0832的实成DA转换 第九课模数转换(AD)工作原理及应用模拟电压与数字电压的关系,如何使用ADC0804的实成AD转换 第十课1602液晶显示原理及实现最简单液晶工作原理、如何开始对一个没有任何概念的芯片开始单片机的操作 第十一课串口原理及应用串口通讯工作方式、重点讲述最常用的10位数据通讯、波特率概念及如何根据波特率计算定时器初值 第十二课IIC总线原理和模块化编程方法 IIC总线工作原理、目前非常通用的一种通信机制; 项目开发模块化编程方法。 第十三课红外通信原理及应用红外通信是目前应用最为广泛的通信和遥控手段。在本课程中以红外遥控为代表,具体讲解红外通信的具体过程。

STC15W系列单片机初学者教程

目录 因为网站限制原因,其他链接都不予显示,还有联系方式都不予显示,带来不便非常抱歉 1.开始学习了 2.15W4K32S4单片机简介资料 3.单片机可以用来做什么呢? 4.单片机示例!写一个串口通讯程序,您也可以直接先从这 步开始学习 5.相关资料链接(数据手册,其他进阶例子,开拓眼界) 6.售后持续支持 7.所有下载链接汇总 一. 开始学习了 这个宝贝包含的硬件,也就是给您发货的内容包含以下东西:

1.15W4K32S4最小系统板 1块 2.转串口下载器一个2303转串口 1块用来下载程序和串口 通讯 3.白色面包板一个 1块适合搭建各种电路 4.一个霍尔传感器,制作一个霍尔电路做一个磁控开关 5.若干杜邦针;连接电路 6.彩灯3 颗若干电阻学习彩色灯控制彩色灯 7.三极管若干个电位计 1个灯亮度控制 8.提供上面所有元器件手把手教程手把手教程

这篇教程能够让您学会什么呢? 1.怎么使用 4软件编写的程序,并且使用下载程序到单片机 上面; 2.串口通讯程序,另外在电脑端使用软件进行图形化显示 程序; 如果您有兴趣的话,希望下面对您学习工作有帮助,资料有点多,但是还是值得花一些时间实际操作演示,只有自己动手了,才能体会到更多的内容。

二. 15W4K32S4单片机简介 15W4K32S4单片机是一款非常优秀的51系列单片机,很适合用来作为初学者入门单片机世界。当然单片机的世界没有最强大,只有最适合的单片机。如果你有了解过什么是51单片机和一点C语言。就可以尝试进入这款单片机。边玩边搭建更多的电路,在玩中学习。 继续往下看,将会一步一步演示给您看具体怎么是使用这款单片机。请有耐心的看下去哦,不过如果一次看不完的话,可以分多几天来操作,关键是要坚持! 那么单片机可以用来做什么呢? 目前单片机渗透到我们生活的各个领域,小到电话,玩具,手机,刷卡机,电脑键盘,彩电,冰箱,空调,电磁炉,大到汽车,工业自动控制,机器人,导弹导航装置,甚至是美国的火星车,这些设备里面都含有一个或者多个单片机。单片机的数量不仅远超过机,甚至比人类的数量还要多。可见数量之庞大,用途之广泛啊。 三. 我们掌握单片机有什么用呢?

51单片机实训报告

“51单片机”精简开发板的组装及调试实训报告

为期一周的单片机实习已经结束了。通过此次实训,让我们掌握了单片机基本原理的基础、单片机的编程知识以及初步掌握单片机应用系统开发实用技术,了解“51”单片机精简开发板的焊接方法。同时培养我们理论与实践相结合的能力,提高分析问题和解决问题的能力,增强学生独立工作能力;培养了我们团结合作、共同探讨、共同前进的精神与严谨的科学作风。 此次实训主要有以下几个方面: 一、实训目的 1.了解“51”精简开发板的工作原理及其结构。 2.了解复杂电子产品生产制造的全过程。 3.熟练掌握电子元器件的焊接方法及技巧,训练动手能力,培养工程实践概念。4.能运用51单片机进行简单的单片机应用系统的硬件设计。 5.掌握单片机应用系统的硬件、软件调试方法 二、实验原理 流水灯实际上就是一个带有八个发光二极管的单片机最小应用系统,即为由发光二极管、晶振、复位、电源等电路和必要的硬件组成的单个单片机。 它的电气性能指标:输入电压:DC4.5~6V,典型值为5V。可用干电池组供电,也可用直流稳压电源供电。 如图所示: 本流水灯实际上就是一个带有八个发光二极管的单片机最小应用系统,即为由发光二极管、晶振、复位、电源等电路和必要的硬件组成的单个单片机。 三、硬件组成 1、晶振电路部分 单片机系统正常工作的保证,如果振荡器不起振,系统将会不能工作;假如振荡器运行不规律,系统执行程序的时候就会出现时间上的误差,这在通信中会体现的很明显:电路将无法通信。他是由一个晶振和两个瓷片电容组成的,x1和x2分别接单片机的x1和x2,晶振的瓷片电容是没有正负的,注意两个瓷片电容相连的那端一定要接地。 2、复位端、复位电路 给单片机一个复位信号(一个一定时间的低电平)使程序从头开始执行;一般有两中复位方式:上电复位,在系统一上电时利用电容两端电压不能突变的原理给系统一个短时的低电平;手动复位,同过按钮接通低电平给系统复位,时如果手按着一直不放,系统将一直复位,不能正常。当要对晶体重置时,只要对此引脚电平提升至高电平并保持两个及其周期以上的时间便能完成系统重置的各

最经典的51单片机经典流水灯汇编程序

单片机流水灯汇编程序设计 开发板上的8只LED为共阳极连接,即单片机输出端为低电平时即可点亮LED。 程序A: ;用最直接的方式实现流水灯 ORG 0000H START:MOV P1,#01111111B ;最下面的LED点亮 LCALL DELAY;延时1秒 MOV P1,#10111111B ;最下面第二个的LED点亮 LCALL DELAY;延时1秒 MOV P1,#11011111B ;最下面第三个的LED点亮(以下省略) LCALL DELAY MOV P1,#11101111B LCALL DELAY MOV P1,#11110111B LCALL DELAY MOV P1,#11111011B LCALL DELAY MOV P1,#11111101B LCALL DELAY MOV P1,#11111110B LCALL DELAY MOV P1,#11111111B ;完成第一次循环点亮,延时约0.25秒 AJMP START ;反复循环 ;延时子程序,12M晶振延时约250毫秒 DELAY: MOV R4,#2 L3: MOV R2 ,#250 L1: MOV R3 ,#250 L2: DJNZ R3 ,L2 DJNZ R2 ,L1 DJNZ R4 ,L3 RET END 程序B: ;用移位方式实现流水灯

ajmp main ;跳转到主程序 org 0030h ;主程序起始地址 main: mov a,#0feh ;给A赋值成11111110 loop: mov p1,a ;将A送到P1口,发光二极管低电平点亮 lcall delay ;调用延时子程序 rl a ;累加器A循环左移一位 ajmp loop ;重新送P1显示 delay: mov r3,#20 ;最外层循环二十次 d1: mov r4,#80 ;次外层循环八十次 d2: mov r5,#250 ;最内层循环250次 djnz r5,$ ;总共延时2us*250*80*20=0.8S djnz r4,d2 djnz r3,d1 ret end 51单片机经典流水灯程序,在51单片机的P2口接上8个发光二极管,产生流水灯的移动效果。 ORG 0 ;程序从0地址开始 START: MOV A,#0FEH ;让ACC的内容为11111110 LOOP: MOV P2,A ;让P2口输出ACC的内容 RR A ;让ACC的内容左移 CALL DELAY ;调用延时子程序 LJMP LOOP ;跳到LOOP处执行 ;0.1秒延时子程序(12MHz晶振)=================== DELAY: MOV R7,#200 ;R7寄存器加载200次数 D1: MOV R6,#250 ;R6寄存器加载250次数 DJNZ R6,$ ;本行执行R6次 DJNZ R7,D1 ;D1循环执行R7次 RET ;返回主程序

单片机百度盘资料

一、51单片机 1、祥云51单片机学习光盘(视频教程、例程、操作系统)适合初学者 资料下载链接:https://https://www.360docs.net/doc/b59436169.html,/cJzLQdrBfp2KD 访问密码8f77 2、普中51单片机学习光盘 https://www.360docs.net/doc/b59436169.html,/s/1pK0c4BL 3、郭天祥----十天征服单片机 https://www.360docs.net/doc/b59436169.html,/s/1i4N2Hrn 4、新概念51单片机C语言教程.入门、提高、开发(500页,郭天祥著) https://https://www.360docs.net/doc/b59436169.html,/cYAYJtgFJNUup 访问密码9eb1 5、力天电子51单片机视频教程 https://www.360docs.net/doc/b59436169.html,/s/1hrulifU 6、天狼星51单片机视频教程 链接:https://www.360docs.net/doc/b59436169.html,/s/1pKsD3b9 密码:scy4 8、STC12C5A60S2例程 https://https://www.360docs.net/doc/b59436169.html,/cjPpH7uBBbIr8 访问密码a471 二、AVR单片机 1、郭天祥--十天学会AVR单片机视频教程 https://https://www.360docs.net/doc/b59436169.html,/cwVbV5mWw9pxk 访问密码34ba 1、锐志电子AVR单片机视频教程

https://https://www.360docs.net/doc/b59436169.html,/cweRHU4JUSypY 访问密码64b2 2、手把手AVR单片机视频教程 https://https://www.360docs.net/doc/b59436169.html,/cm926G3YrWKhG 访问密码dccb 3、DY_miniAVR单片机光盘资料 https://https://www.360docs.net/doc/b59436169.html,/c3fIFUrWu4LEG 访问密码0036 4、AVR代码生成器 https://https://www.360docs.net/doc/b59436169.html,/c3fILqj5h3aT9 访问密码2061 5、AVR开发工具 https://https://www.360docs.net/doc/b59436169.html,/c3fI3satMGmSh 访问密码d356 6、AVR例程 https://https://www.360docs.net/doc/b59436169.html,/c3fIFfSgCzhWE 访问密码48c1 三、msp430单片机 1、郭天祥---十天学会msp430单片机 https://https://www.360docs.net/doc/b59436169.html,/cYAYvyxDBaHgr 访问密码4dca 2、力天msp430单片机视频教程 https://https://www.360docs.net/doc/b59436169.html,/cYAY83HwRumTn 访问密码d66c 3、msp430 c语言.pdf https://https://www.360docs.net/doc/b59436169.html,/cYAY577Ucc7b2 访问密码86b3 4、msp430教程.pdf https://https://www.360docs.net/doc/b59436169.html,/cYAYtXwXYesgC 访问密码ccbf 5、IAR C 430标准库函数.pdf https://https://www.360docs.net/doc/b59436169.html,/cYAYnInwURHZx 访问密码52ef

单片机 c语言程序框架详解

/*单片机avr 流水灯源程序文件名:led.c */ #include void delay(uint time_c) //子函数,实现延时功能,void 表示此函数无返回值,delay 函数名,time_c 函数的参数-无符号的整形数值 { int i,j; //变量声明 while(time_c--) { for (j=0;j<1200;j++) {; }; //函数体内的语句以';'分号结尾,表示一条语句的结束,分号需要用英文标点输入 } } void main (void) //主函数 { //程序的初始化 DDRA=0xFF; //DDRA -PA口的方向寄存器,1为输出,0为输入,PA的8个I/O口全部设为输出。 PORTA=0xFF; //PORTA -PA口的输出控制寄存器,1为输出高电平,0为输出低电平,此处,PA口全部输出高电平。 while(1) // 死循环 { PORTA=0xFE; //PA口的第0位清0,点亮第一个灯 delay(500); // 延时 PORTA=0xFD; //点亮第二个灯 delay(500); PORTA=0xFB; //点亮第三个灯 delay(500); PORTA=0xF7; //点亮第四个灯 dealy(500); PORTA=0xEF; //点亮第五个灯 dealy(500); PORTA=0xDF; //点亮第六个灯 dealy(500);

PORTA=0xBF; //点亮第七个灯 delay(500); PORTA=0x7F; //点亮第八个灯 delay(500); } } /* 流水灯程序结束*/ ------------------------------------------------------------------------------------------------------------------------------- #include :#include c语言的文件包含指令,指的是在一个文件中包含另一个文件的全部内容,在这个源文件led.c中包含了头文件’iom16v.h'的全部内容,(c语言中源文件的扩展名'.c',头文件的扩展名为'.h'),此处iom16v.h 头文件定义了单片机ATmega16的内部寄存器参数,使用不同的单片机要用不同的头文件,例如:使用ATmega32 ,头文件需改为'iom32v.h' 。 中“<>"表示在系统默认的目录中搜索文件,若为"iom16v.h" 双引号表示在项目源文件所在的目录搜索文件。 void delay(unit time_c) { } ;为自定义的子函数,实现某一特定功能的函数,c语言函数的内容都放在{}中;delay(500)为子函数调用,实现延时功能,500为函数的实参,time_c 称为形式参数,单片机的运行速度非常快,如果不加延时,所有的灯看起来都是亮的,人眼无法分辨,可以增加,或减少延时的时间看看结果的变化。 void main(void) { .............. while(1) { .........}; } main 为主函数,是每一个c语言程序中必须有的,也必须只能有一个。它是单片机程序运行开始的入口处,在main函数中都有一个while(1)死循环,程序将在while所包含的语句中周而复始的运行。 /*单片机avr 流水灯源程序文件名:led.c */ 在c语言中在 '/* 和 '*/' 之间的内容为程序的注释,方便程序的阅读,可以对多行进行注释,'//':只能进行单行注释。 常量:在程序运行过程中数值不变的数据。 变量:在程序运行过程中,其值可以改变的数据 在书写变量说明时,应注意以下几点: 1.允许在一个类型说明符后,说明多个相同类型的变量。各变量名之间用逗号间隔。类型说明符与变量名之间至少用一个空格间隔。 2.最后一个变量名之后必须以“;”号结尾。 3.变量说明必须放在变量使用之前。一般放在函数体的开头部分。

03 第三讲 数字电路基础知识--力天手把手教你学单片机之入门篇

手把手教你学51单片机 ——之MCS-51入门篇 主讲: 尹延辉 策划:张勇 开发板:LT-Super51 QQ群:31646346 网址:https://www.360docs.net/doc/b59436169.html, E-Mail:litianmcu@https://www.360docs.net/doc/b59436169.html, litianmcu@https://www.360docs.net/doc/b59436169.html,

入门篇第三讲——数字电路基础知识?本讲内容提要 数字量和模拟量 数制和码制 算术运算和逻辑运算 数字芯片 常用数字芯片简介 可编程逻辑器件 存储器 学习板上扩展IO口 的实现

——数字量和模拟量 ?数字量和模拟量定义 模拟量:随时间连续变化的电压或电流信号称之为模拟量 数字量:随时间离散变化的量称之为数字量 ?数字量的实质为加入判决门限的模拟量

——数字电路’0’与’1’的定义?数字电路’0’与’1’的定义 TTL电平:电压+5V代表’1’,电压0代表’0’ LVTTL:+3.3V~’1’,0~’0’ RS232:-15V~’1’,+15V~’0’ LVDS:2根线上电压差的正负表示’1’或’0’

——数制和码制 ?数制的定义 计数过程中一位数字通常是不够用的,多位数码中每一位的构成方法及从低位向高位进位规则称为数制。 N进制数的通俗定义:逢N进1 ?十进制:逢十进一 ?十六进制:逢十六进一 ?二进制:逢二进一 ?常用数制 十进制、二进制、十六进制 ?人类有十个指头,所以习惯采用十进制 ?计算机只能识别0和1,采用二进制 ?为了计算机学中的数据书写方便,采用十六进制

——数制转换详解 ?数制间的转换 二-十转换 十-二转换 二-十六转换 十六-二转换 ?位与字节的概念: 位(bit):简写为b,表示二进制数的一位。 字节(Byte):简写为B,8位为一字节。 ?数制转换工具: Windows自带的计算器

51单片机数字电压表实验报告

微控制器技术创新设计实验报告 姓名:学号:班级: 一、项目背景 使用单片机AT89C52和ADC0808设计一个数字电压表,能够测量0-5V之间的直流电压值,四位数码显示。在单片机的作用下,能监测两路的输入电压值,用8位串行A/D转换器,8位分辨率,逐次逼近型,基准电压为 5V;显示精度伏。 二、项目整体方案设计 ADC0808 是含8 位A/D 转换器、8 路多路开关,以及与微型计算机兼容的控制逻辑的CMOS组件,其转换方法为逐次逼近型。ADC0808的精度为 1/2LSB。在AD 转换器内部有一个高阻抗斩波稳定比较器,一个带模拟开关树组的256 电阻分压器,以及一个逐次通近型寄存器。8 路的模拟开关的通断由地址锁存器和译码器控制,可以在8 个通道中任意访问一个单边的模拟信号。

三、硬件设计 四、软件设计#include<> #include""

#define uchar unsigned char #define uint unsigned int sbit OE = P2^7; sbit EOC=P2^6; sbit START=P2^5; sbit CLK=P2^4; sbit CS0=P2^0; sbit CS1=P2^1; sbit CS2=P2^2; sbit CS3=P2^3; uint adval,volt; uchar tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; void delayms(uint ms) {

51单片机考试常见试题简答 题

简答题部分 1、什么叫堆栈? 答:堆栈是在片内RAM中专门开辟出来的一个区域,数据的存取是以"后进先出"的结构方式处理的。实质上,堆栈就是一个按照"后进先出"原则组织的一段内存区域。 2、进位和溢出? 答:两数运算的结果若没有超出字长的表示范围,则由此产生的进位是自然进位;若两数的运算结果超出了字长的表示范围(即结果不合理),则称为溢出。 3、在单片机中,片内ROM的配置有几种形式?各有什么特点? 答:单片机片内程序存储器的配置形式主要有以下几种形式:(1)掩膜(Msak)ROM型单片机:内部具有工厂掩膜编程的ROM,ROM中的程序只能由单片机制造厂家用掩膜工艺固 化,用户不能修改ROM中的程序。掩膜ROM单片机适合于 大批量生产的产品。用户可委托芯片生产厂家采用掩膜方法 将程序制作在芯片的ROM。 (2)EPROM型单片机:内部具有紫外线可擦除电可编程的只读存储器,用户可以自行将程序写入到芯片内部的EPROM 中,也可以将EPROM中的信息全部擦除。擦去信息的芯片 还可以再次写入新的程序,允许反复改写。 (3)无ROM型单片机:内部没有程序存储器,它必须连接程序存储器才能组成完整的应用系统。 无ROM型单片机价格低廉,用户可根据程序的大小来选择外接 程序存储器的容量。这种单片机扩展灵活,但系统结构较复 杂。 (4)E2ROM型单片机:内部具有电可擦除叫可编程的程序存储器,使用更为方便。该类型目前比较常用 (5) OTP(One Time Programmable)ROM单片机:内部具有一次可编程的程序存储器,用户可以在编程器上将程序写入片 内程序存储器中,程序写入后不能再改写。这种芯片的价 格也较低。 4、什么是单片机的机器周期、状态周期、振荡周期和指令周期?它们之间是什么关系? 答:某条指令的执行周期由若干个机器周期(简称M周期)构成,一个机器周期包含6个状态周期(又称时钟周期,简称S周期),而一个状态周期又包含两个振荡周期(P1和P2,简称P周期)。也就是说,指令执行周期有长有短,但一个机器周期恒等于6个状态周期或12个振荡周

c51单片机实例下载大全

单片机资料教程下载,省去找资料的麻烦,只供学习参考用,下载24内删掉,祝大家学习进步 单片机点阵学习资料 https://www.360docs.net/doc/b59436169.html,/thread-1703-1-1.html 手把手教你学单片机--教程视频 https://www.360docs.net/doc/b59436169.html,/thread-1688-1-1.html 力天把手教你学单片机视频教程 https://www.360docs.net/doc/b59436169.html,/thread-1689-1-1.html 谱中单片机开发板例程 https://www.360docs.net/doc/b59436169.html,/thread-1683-1-2.html 初学单片机的30,硬件简单对初学者有帮助 https://www.360docs.net/doc/b59436169.html,/thread-1962-1-1.html 用单片机制作的MP3 https://www.360docs.net/doc/b59436169.html,/thread-1701-1-2.html 51单片机应用开发大全所含100个范例代码及电路图 https://www.360docs.net/doc/b59436169.html,/thread-1820-1-1.html 【含28个单片机实例流程图】 https://www.360docs.net/doc/b59436169.html,/thread-1959-1-2.html 谱中单片机程序烧录工具STC https://www.360docs.net/doc/b59436169.html,/thread-1682-1-2.html 《单片机技术》32讲

https://www.360docs.net/doc/b59436169.html,/thread-1693-1-1.html 51单片机c语言100例教程 https://www.360docs.net/doc/b59436169.html,/thread-1700-1-1.html 单片机超级精华包 https://www.360docs.net/doc/b59436169.html,/thread-1687-1-1.html 新手学的多功能电子钟 https://www.360docs.net/doc/b59436169.html,/thread-1679-1-1.html 十天学会单片机和c语言视频教程 https://www.360docs.net/doc/b59436169.html,/thread-1692-1-1.html C语言函数库速查手册 https://www.360docs.net/doc/b59436169.html,/thread-1696-1-1.html 历史上最全的KEIL中文学习资料 https://www.360docs.net/doc/b59436169.html,/thread-1729-1-2.html 单片机c语言程序设计实训100例--基于AVR+PROTUES https://www.360docs.net/doc/b59436169.html,/thread-1695-1-2.html (有电路图和程序) https://www.360docs.net/doc/b59436169.html,/thread-1965-1-1.html 关于单片机抗干扰的资料 https://www.360docs.net/doc/b59436169.html,/thread-1961-1-1.html 单片机矩阵扫描键盘程序 https://www.360docs.net/doc/b59436169.html,/thread-1723-1-1.html 共享通过串口在线调试51单片机的专业版培训资料

51单片机实验报告

51单片机实验报告

实验一 点亮流水灯 实验现象 Led灯交替亮,间隔大约10ms。实验代码 #include void Delay10ms(unsigned int c); void main() { while(1) { P0 = 0x00; Delay10ms(50); P0 = 0xff; Delay10ms(50); } }

void Delay10ms(unsigned int c) { unsigned char a, b; for (;c>0;c--) { for (b=38;b>0;b--) { for (a=130;a>0;a--); } } } 实验原理 While(1)表示一直循环。 循环体首先将P0的所有位都置于零,然后延时约50*10=500ms,接着P0位全置于1,于是LED全亮了。接着循环,直至关掉电源。延迟函数是通过多个for循环实现的。 实验2 流水灯(不运用库函数) 实验现象 起初led只有最右面的那一个不亮,半秒之后从右数第二个led

也不亮了,直到最后一个也熄灭,然后led除最后一个都亮,接着上述过程 #include #include void Delay10ms(unsigned int c); main() { unsigned char LED; LED = 0xfe; while (1) { P0 = LED; Delay10ms(50); LED = LED << 1; if (P0 == 0x00) { LED = 0xfe; } } } void Delay10ms(unsigned int c)

基于51单片机的音乐程序

基于51单片机的按键切换播放音乐 原理图: 引脚说明:共5个按键,分别接51单片机的P0~P4引脚,前4个按键控制播放设置好的四首音乐,第5个按键用来关闭音乐。按键采用中断方式,任意时刻按下任意按键则立即进入所按按键的功能;蜂鸣器接单片机的P3.6口。 仿真说明:使用proteus仿真,晶振:12MHZ。 程序代码如下: /*12Mhz晶振工作*/ #include #define uint unsigned int #define uchar unsigned char sbit voice=P3^6; uchar code sound1[]={0xff, 0x40,0x80,0x30,0x40,0x2b,0x40,0x26,0x80,0x24,0x10,0x26,0x40,0x30,0x40, 0x2b,0x80,0x30,0x40,0x39,0x40,0x30,0xc0,0x40,0x80,0x30,0x40,0x2b,0x40, 0x26,0x40,0x26,0x20,0x24,0x20,0x20,0x40,0x30,0x40,0x24,0x80,0x26,0x10,

0x20,0x40,0x19,0x40,0x19,0x80,0x1c,0x10,0x1c,0x80,0x20,0x40,0x20,0x20, 0x1c,0x20,0x19,0x40,0x1c,0x20,0x20,0x20,0x26,0xc0,0x24,0x80,0x24,0x10, 0x20,0x40,0x1c,0x40,0x20,0x40,0x24,0x20,0x26,0x20,0x2b,0x80,0x33,0x40, 0x33,0x20,0x39,0x20,0x40,0x40,0x39,0x40,0x30,0xc0,0x18,0x80,0x1c,0x80, 0x24,0x80,0x20,0x10,0x1c,0x80,0x19,0x40,0x19,0x20,0x19,0x20,0x19,0x40, 0x1c,0x20,0x20,0x20,0x26,0xc0,0x18,0x80,0x1c,0x80,0x24,0x80,0x20,0x10, 0x1c,0x80,0x1c,0x40,0x1c,0x20,0x1c,0x20,0x1c,0x40,0x24,0x20,0x26,0x20, 0xff,0x20,0x00};//同一首歌*/ uchar code sound2[]={0xff, 0x18,0x40,0x1c,0x20,0x18,0x20,0x13,0x40,0x13,0x20,0x15,0x20,0x13,0x20, 0x15,0x20,0x13,0x20,0x15,0x20,0x18,0x20,0x19,0x20,0x1c,0x20,0x20,0x20, 0x1c,0x40,0x19,0x20,0x18,0x20,0x15,0x40,0x10,0x80, 0x13,0x10,0x10,0x40,0x15,0x10,0x13,0x10,0x18,0x10,0x1c,0x10,0x26,0x10, 0x13,0x10,0x18,0x10,0x1c,0x10,0x26,0x10,0x13,0x10,0x18,0x10,0x1c,0x10, 0x26,0x10,0x13,0x10,0x18,0x10,0x1c,0x10,0x26,0x10,0x15,0x10,0x19,0x10, 0x20,0x10,0x2b,0x10,0x15,0x10,0x19,0x10,0x20,0x10,0x2b,0x10,0x15,0x10, 0x19,0x10,0x20,0x10,0x2b,0x10,0x15,0x10,0x19,0x10,0x20,0x10,0x2b,0x10, 0x18,0x10,0x1c,0x10,0x24,0x10,0x30,0x10,0x18,0x10,0x1c,0x10,0x24,0x10, 0x30,0x10,0x19,0x10,0x20,0x10,0x2b,0x10,0x19,0x10,0x19,0x10,0x20,0x10, 0x2b,0x10,0x19,0x10,0x18,0xc0,0xff,0x40,0x40,0x10,0x39,0x20,0x30,0x20, 0x2b,0x20,0x30,0x20,0x2b,0x20,0x26,0x20,0x26,0x20,0x26,0x20,0x26,0x20, 0x26,0x20,0x2b,0x20,0x30,0x20,0x2b,0x20,0x26,0x20,0x26,0x20,0x26,0x20, 0x26,0x20,0x26,0x20,0x2b,0x20,0x30,0x20,0x2b,0x40,0x30,0x10,0x30,0x20, 0x39,0x20,0x30,0x40,0x2b,0x10,0x2b,0x20,0x26,0x20,0x26,0x80,0x40,0x10, 0x39,0x20,0x30,0x20,0x2b,0x20,0x30,0x20,0x2b,0x20,0x30,0x20,0x30,0x20, 0x20,0x20,0x20,0x20,0x26,0x20,0x2b,0x20,0x26,0x20,0x2b,0x20,0x30,0x20, 0x30,0x20,0x26,0x20,0x26,0x20,0x26,0x20,0x2b,0x20,0x30,0x20,0x2b,0x40, 0x2b,0x10,0x2b,0x20,0x2b,0x20,0x2b,0x40,0x30,0x10,0x30,0x20,0x39,0x20,

相关文档
最新文档