整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

51单片机进阶,处于瓶颈的你必看

51单片机进阶,处于瓶颈的你必看

:最小系统能够运行起来的必要条件。

1.电源 2.晶振3.复位电路

二:对单片机任意IO口的随意操作

1.输出控制电平高低2.输出检测电平高低。

三:单片机特殊功能应用

1: 定时器:重点掌握最常用的方式2

2: 中断:外部中断、定时器中断、串口中断

3: 串口通信:单片机之间、单片机与计算机间

(在此不详细介绍单片机C语言)

一:最小系统运行条件

1.电源 2.晶振3.复位电路 详细资料参见导论中的最小系统电路图

二:普通I/O口的操作

1:输出高低电平 output

操作:用程序给输出寄存器P0/P1/P2/P3赋值,1/0实现高低电平的控制

应用:这种高低可实现一些对外部设备的控制,比如led,lcd····,也可加上电流驱动或继电器或可控硅等器件实现对大型用电器的控制

实例:I/O操作最简单的实例就是流水灯,流水灯程序参见:http://blog.csdn.net/metalseed/article/details/8196727

2:检测电平高低 input

操作:先给寄存器P1/P2/P3赋值0xff,然后用 if 语句来进行判断

应用:可用来读取外部外部信息实现模拟通信,获得传感器数据,按键采集等

实例:矩阵键盘的扫描代码:http://blog.csdn.net/metalseed/article/details/8296590

数码管显示:http://blog.csdn.net/metalseed/article/details/8537554

PS: P0为三态(高电平,低电平,高阻态) P1,P2,P3为准双向IO口(内部有上拉电阻,做输入用时,先写1)

三:单片机特殊功能应用

这是进阶的核心内容,单片机的特殊功能全部集中在P3口,这些引脚具有多功能,可通过寄存器配置(关于寄存器,日后补上详细描述,寄存器理解属于高阶思想,在此先讲操作)来确定启用第几功能。

首先附上P3第二功能定义

P3第二功能定义:

P3.0:RXD串行口输入

P3.1:TXD串行口输出

P3.2:INT0外部中断0输入

P3.3:INT1外部中断1输入

P3.4:T0定时器0外部输入

P3.5:T1定时器1外部输入

P3.6:WR外部写控制

P3.7:RD外部读控制

1: 中断

中断的概念:

中断其实很容易理解,这样来说吧,比如说你在做A事,但是突然间来了你想起来了更重要的B事,所以你马上去做B事了,做完之后再回来继续做A事,这个就是中断!在程序里面也是一样的!中断系统里面有五个中断,外部中断0和1,定时器/计数器中断0/1,串行口中断!

举个例子你可能会容易懂点,定时中断:比如你定时1ms,主程序在运行,每当1ms时间到后,就跑到定时中断子程序 里面执行,执行完后再回到主程序。。。中断程序是1ms进去一次

后面中断讲解太过系统,不易理解,日后补上简洁易懂的,请亲见谅.....。。

中断data请移步至:http://wenku.baidu.com/view/4f3738f64693daef5ef73da6.html

中断实例:

超声波外部中断 + 串口通信 将测出的距离通过串口发送

http://blog.csdn.net/metalseed/article/details/8764348

2: 定时器

定时器简介

定时器及计数器的应用,比 I / O 功能稍微高级点,可实现更为复杂的功能。

顾名思义,定时器可实现延时操作,计数器则可实现计数功能(这两者都靠中断实现)。

两者实质上都是加一计数器(16位),由高8位和低8位两个寄存器组成,当所有位为1即定时器溢出时,便触发中断。

PS:51内部有两个定时器:定时器0,定时器1,定时模式加1的周期为一个机器周期 12M晶振的机器周期为1us

应用定时器,需要操作响应的寄存器。

主要涉及三个: 1:中断允许寄存器IE (可位寻址,所以能直接操作EA,ET0, ET1,)

2:TMOD 是定时/计数的工作方式寄存器,确定工作方式和功能

3:TCON是控制寄存器,控制T0,T1的启动和停止及设置溢出标志。

操作方法:

step 1: 配置IE寄存器,让定时器使能(使能即能被应用,可假象为函数的声明)。

step 2: 配置TMOD寄存器,来确定定时器的工作方式,同时配置TH,TL寄存器来对定时器装入初值

step 3: 配置TCON寄存器,启动或停止定时器(因为定时器一旦启用,就不停加1,直到TH,TL所有位为1时溢出,跳入中断函数,所以在启用前,要写好中断函数,中断函数写法demo里有说明)

这里所说的配置,即给寄存器赋值,例如: TMOD=0X0f;

总而言之:要使用定时器或者计数器需要依次给如下寄存器赋值: IE,TOMD,TH,TL, TCON,具体要赋什么值,参加下面的寄存器位含义说明;

寄存器说明及定时器工作方式:

点击打开特殊功能寄存器详细说明

代码示例:

1:最直白的定时器工作方式1演示,每隔50MS P0取反

[java] view plain copy print?

#include

void main()

{

EA=ET0=1; /*step 1 : 中断允许*/

TMOD=0x01; /*step 2 : 模式配置*/

TH0=(65536 - 50000) / 256; /*装初值*/

TL0=(65536 - 50000) % 256; /*装初值*/

TR0=1; /*step 3 : 启动*/

while(1)

{

/*Hello World*/

}

}

/*timer0为函数名,随意写,后面的interrupt X,X是相应中断的编号,5个中断源各有固定编号*/

/*using x 表示占用ram中的X寄存器(0-3),C语言中IDE自动分配不用写 */

void timer0() interrupt 1 using 1

{

/*重装初值*/

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

/*operation*/

P0=~P0;

}

2:高级模板

待补~

3: 串口通信

接口:RS232C

RS-422A用于全双工,而RS-485则用于半双工(比232距离远)

需配置的寄存器 : SCON PCON IE

SCON是一个特殊功能寄存器,用以设定串行口的工作方式、接收/发送控制以及设置状态标志:

SM0和SM1为工作方式选择位,可选择四种工作方式

SM2,多机通信控制位,主要用于方式2和方式3。当接收机的SM2=1时可以利用收到的RB8来控制是否激活RI(RB8=0时不激活RI,收到的信息丢弃;RB8=1时收到的数据进入SBUF,并激活RI,进而在中断服务中将数据从SBUF读走)。当SM2=0时,不论收到的RB8为0和1,均可以使收到的数据进入SBUF,并激活RI(即此时RB8不具有控制RI激活的功能)。通过控制SM2,可以实现多机通信。

在方式0时,SM2必须是0。在方式1时,若SM2=1,则只有接收到有效停止位时,RI才置1。

REN,允许串行接收位。由软件置REN=1,则启动串行口接收数据;若软件置REN=0,则禁止接收。

TB8,在方式2或方式3中,是发送数据的第九位,可以用软件规定其作用。可以用作数据的奇偶校验位,或在多机通信中,作为地址帧/数据帧的标志位。

在方式0和方式1中,该位未用。

RB8,在方式2或方式3中,是接收到数据的第九位,作为奇偶校验位或地址帧/数据帧的标志位。在方式1时,若SM2=0,则RB8是接收到的停止位。

TI,发送中断标志位。在方式0时,当串行发送第8位数据结束时,或在其它方式,串行发送停止位的开始时,由内部硬件使TI置1,向CPU发中断申请。在中断服务程序中,必须用软件将其清0,取消此中断申请。

RI,接收中断标志位。在方式0时,当串行接收第8位数据结束时,或在其它方式,串行接收停止位的中间时,由内部硬件使RI置1,向CPU发中断申请。也必须在中断服务程序中,用软件将其清0,取消此中断申请。

PCON中只有一位SMOD与串行口工作有关:

SMOD(PCON.7) 波特率倍增位。在串行口方式1、方式2、方式3时,波特率与SMOD有关,当SMOD=1时,波特率提高一倍。复位时,SMOD=0。

波特率的计算

方式0的波特率=fosc/12

方式2的波特率=(2SMOD/64)·fosc

方式1的波特率=(2SMOD/32)·(T1溢出率)

方式3的波特率=(2SMOD/32)·(T1溢出率)

当T1作为波特率发生器时,最典型的用法是使T1工作在自动再装入的8位定时器方式(即方式2,且TCON的TR1=1,以启动定时器)。这时溢出率取决于TH1中的计数值。

T1溢出率=fosc /{12×[256-(TH1)]}

操作步骤:

1:确定串口工作方式 (配置SCON 可位寻址)

2:根据1确定的方式,看是否需要手动设置波特率 (TMODE,TH TL)

3:设置波特率后启动(REN, TR)

4:如果使用中断,开中断并写函数(EA=ES=1, void ser() interrupt 4 )

串口通信模板:

http://blog.csdn.net/metalseed/article/details/8579997

点对点通信:

多机通信:

1、硬件连接

单片机构成的多机系统常采用总线型主从式结构。所谓主从式,即在数个单片机中,有一个是主机,其余的是从机,从机要服从主机的调度、支配。80C51单片机的串行口方式2和方式3适于这种主从式的通信结构。当然采用不同的通信标准时,还需进行相应的电平转换,有时还要对信号进行光电隔离。在实际的多机应用系统中,常采用RS-485串行标准总线进行数据传输。

2、通信协议

所有从机的SM2位置1,处于接收地址帧状态。

主机发送一地址帧,其中8位是地址,第9位为地址/数据的区分标志,该位置1表示该帧为地址帧。

所有从机收到地址帧后,都将接收的地址与本机的地址比较。对于地址相符的从机,使自己的SM2位置0(以接收主机随后发来的数据帧),并把本站地址发回主机作为应答;对于地址不符的从机,仍保持SM2=1,对主机随后发来的数据帧不予理睬。

从机发送数据结束后,要发送一帧校验和,并置第9位(TB8)为1,作为从机数据传送结束的标志。

主机接收数据时先判断数据接收标志(RB8),若RB8=1,表示数据传送结束,并比较此帧校验和,若正确则回送正确信号00H,此信号命令该从机复位(即重新等待地址帧);若校验和出错,则发送0FFH,命令该从机重发数据。若接收帧的RB8=0,则存数据到缓冲区,并准备接收下帧信息。

主机收到从机应答地址后,确认地址是否相符,如果地址不符,发复位信号(数据帧中TB8=1);如果地址相符,则清TB8,开始发送数据。

从机收到复位命令后回到监听地址状态(SM2=1)。否则开始接收数据和命令。

3、应用程序

主机发送的地址联络信号为:00H,01H,02H ,… …(即从机设备地址),地址FFH为命令各从机复位,即恢复SM2=1。

主机命令编码为:01H,主机命令从机接收数据;02H,主机命令从机发送数据。其它都按02H对待。

RRDY=1:表示从机准备好接收。

TRDY=1:表示从机准备好发送。

ERR=1: 表示从机接收的命令是非法的。

程序分为主机程序和从机程序。约定一次传递数据为16个字节,以01H地址的从机为例。

寄存器数据手册:

单片机细节:

定义的变量存储在RAM中,对寄存器赋值时,单片机内部通过数据交换实现。

复位时 P0,P1,P2,P3寄存器全为0xff,其他各位0x00;

avaScript Break 和 Continue

  • JS Loop While
  • JS 类型转换



break 语句“跳出”循环。

continue 语句“跳过”循环中的一个迭代。

Break 语句

在本教程稍早的章节中,您已见到了 break 语句。它被用于“跳出” switch 语句。

break 语句也可用于跳出循环。

break 语句会中断循环,并继续执行循环之后的代码(如果有):

实例

for (i=0; i < 10; i++) {
    if (i===3) { break; }
    text +="数字是 " + i + "<br>";
}

亲自试一试

Continue 语句

continue 语句中断(循环中)的一个迭代,如果发生指定的条件。然后继续循环中的下一个迭代。

本例跳过值 3 :

实例

for (i=0; i < 10; i++) {
    if (i===3) { continue; }
    text +="数字是 " + i + "<br>";
} 

亲自试一试

JavaScript 标签

如需标记 JavaScript 语句,请将标签名和冒号置于语句之前:

label:
statements

break 和 continue 语句是仅有的可“跳出”代码块的 JavaScript 语句。

语法:

break labelname;

continue labelname;

continue 语句(不论有无标签引用)只能用于跳过一个迭代。

break 语句,如果没有标签引用,只能用于跳出一个循环或一个 switch。

如果有标签引用,则 break 语句可用于跳出任意代码块:

实例

var  cars=["BMW", "Volvo", "Saab", "Ford"];
list: {
    text +=cars[0] + "<br>"; 
    text +=cars[1] + "<br>"; 
    text +=cars[2] + "<br>"; 
    break list;
    text +=cars[3] + "<br>"; 
    text +=cars[4] + "<br>"; 
    text +=cars[5] + "<br>"; 
}

亲自试一试

代码块指的是 { 与 } 直接的代码片段。

近作者看了一些关于JavaScript反调试的帖子,今天给大家整理一下希望有帮助哦~~~

前言

对于JavaScript来说,你只需要花一点时间进行调试和分析,你就能够了解到JavaScript代码段的功能逻辑。而我们所要讨论的内容,可以给那些想要分析你JavaScript代码的人增加一定的难度。不过我们的技术跟代码混淆无关,我们主要针对的是如何给代码主动调试增加困难。

本文所要介绍的技术方法大致如下:

1. 检测未知的执行环境(我们的代码只想在浏览器中被执行);
2. 检测调试工具(例如DevTools);
3. 代码完整性控制;
4. 流完整性控制;
5. 反模拟;
就是如果我们监控到到了“非正常”的情况,程序的运行流程将会改变,并跳转到伪造的代码块,并“隐藏”真正的功能代码。

一、对函数的重新定义

这是一种最基本也是最常用的代码反调试技能了。在JavaScript中,咱们能够对用于搜集信息的函数进行重新定义。例如,函数console.log()能够用来搜集函数和变量等信息,并将其显现在操控台中。例如我们把这个函数重新定义一下,就能够修改函数的行为,并隐去特定信息或显现假的信息。

可以在控制台直接运行这个函数来看一下结果:

#测试代码块console.log("HelloWorld");var fake=function() {};window['console']['log']=fake;console.log("Youcan't see me!");

运行后结果:

VM48:1 Hello World

如上测试代码,第二个信息console.log()信息并输出,因为我们把console.log()函数给重新定义了,即“禁用”了它原有的功能。但是我们也可以让它显示伪造后的信息,例如:

console.log("Normalfunction");//First we save a reference to the original console.log functionvaroriginal=window['console']['log'];//Next we create our fake function//Basicly we check the argument and if match we call original function with otherparam.// If there is no match pass the argument to the original functionvar fake=function(argument) { if (argument==="Ka0labs") {
 original("Spoofed!");
 } else {
 original(argument);
 }
}// We redefine now console.log as our fake functionwindow['console']['log']=fake;//Then we call console.log with any argumentconsole.log("Thisis unaltered");//Now we should see other text in console different to "Ka0labs"console.log("Ka0labs");//Aaaand everything still OK
console.log("Byebye!");

输出结果:

Normal functionVM117:11 This is unalteredVM117:9 Spoofed!VM117:11 Bye bye!

实际上,为了操控代码的运行方式,咱们还能用更好的方法来修正函数的功用。例如,根据上述代码来构建一个代码段,对eval函数重新定义。就能够把JavaScript代码传递给eval函数,接下来代码将会被计算并运行。假如咱们重新定义了这个函数,咱们就能够运行不同的代码了:

//Just a normal evaleval("console.log('1337')");//Now we repat the process...var original=eval;var fake=function(argument) { // If the code to be evaluated contains1337...if (argument.indexOf("1337") !==-1) { // ... we just execute a different code
 original("for (i=0; i < 10;i++) { console.log(i);}");
 } else {
 original(argument);
 }
}eval=fake;eval("console.log('Weshould see this...')");//Now we should see the execution of a for loop instead of what is expectedeval("console.log('Too1337 for you!')");

输出运行结果:

1337VM146:1We should see this…VM147:10VM147:11VM147:12VM147:13VM147:14VM147:15VM147:16VM147:17VM147:18VM147:19

这样的方法虽然非常巧妙,但这也只是一种非常基础并且常见的方法,也容易被检测到。

二、断点

我们在了解代码的功能的时候,一般通过JavaScript调试工具(例如DevTools)通过设置断点的方式来中断或阻止脚本代码的执行,而断点也是代码调试中最基本的了。

如果你研究过调试器或者x86架构,你可能会比较熟悉0xCC指令。在JavaScript中,我们有一个名叫debugger的类似指令。当我们在代码中声明了debugger函数后,脚本代码将会在debugger指令这里停止运行。比如说:

console.log("Seeme!");debugger;console.log("Seeme!");

许多商业产品会在代码中设置一个无限循环的debugger指令,不过某些浏览器会屏蔽这种代码,而有些则不会。这种办法的首要意图就是让那些想要调试你代码的人感到厌烦,由于无限循环意味着代码会不断地弹出窗口来问询你是否要继续运转脚本代码:

setTimeout(function(){while (true) {eval("debugger")

更多精彩内容可以关注“IT实战联盟”,也可以留言和作者互动或者加入我们实战交流群哦~~~