相当经典的IO口扫描法

合集下载

微机原理与接口技术课件 5.IO端口地址地址译码方法(已看)

微机原理与接口技术课件 5.IO端口地址地址译码方法(已看)
系 统 总 线
2—4译码器
A15 A14 A13
Y0 Y1
B A
Y2
Y3
0# C S1 1# C S1 2# C S1 3# C S1
因此部分译码虽较全译码简单, 但存在地址重叠区。
20
可选式译码
比较器+地址开关 原理:比较器输出有效(相等)时,译码输出有效
21
返回
可选式译码实例
A9 A8 A7 DIP A6
译码器译码
地址线 用 途 十六进制 0 0 A9 A8 控 制 0H A7 A6 A5 片 选 0~7H A4 A3 A2 A1 A0 片 内 端 口 寻址 0~1FH
译码电路输入地址线的值
A5 A6 A7 A8 A9 AEN 15 1 A Y 2 B 74LS138 0 14 Y1 3 C 13 Y2 12 U54 Y3 9 8 11 G2B ≥1 Y4 G2A 10 10 74LS32 G1 Y5 9 13 ≥1 11 Y6 Y7 7 12 DMACS(8237) INTRCS(8259) T/CCS(8253) PPICS(8255) WRTDMAPG (写DMA页面寄存器) WRTNMIREG (写出NMI屏蔽寄存器)
80x86系列微处理器提供16条地址线访问io端口ibm系列采用非完全译码方式即只考虑了低10位地址线a0a9io端口地址范围是0000h03ffh总共只有1024个字节端口12io端口地址选用的原则必须避免端口地址发生冲突自行设计接口电路或给微机系统添加接口卡时申明保留的地址不要使用用户可使用300h31fh地址2的5次方32个字节端口13若接口电路中需使用多个端口地址则采用译码器译码比较方便
1
1 1 0 1 1 1 1 1 1
1

STM8教程实验2-按键扫描

STM8教程实验2-按键扫描

实验二 按键扫描按键扫描实际上就是对IO口的输入捕捉操作,跟LED 的刚好相反,LED 的对IO 口输出的操作,因此在操作上很相似的。

相信大家会点亮LED 的话,那么按键扫描的话也很容易了。

先看下风驰电子STM8开发板上的按键的硬件连接由电路连接图来看,如果按键按下的话,IO口读到的电平信号就是低电平。

先看看按键扫描要用到的内部资源"stm8s.h""stm8s_clk.h""stm8s_clk.c""stm8s_gpio.h""stm8s_gpio.c"首先,我们从主函数看起时钟和LED的初始话大家都清楚了,这里不多说了。

下面主要来看下按键的初始化Buttom_Init();他的函数原型很简单,对吧,就是初始话一下IO口。

上面的意思是对按键Buttom1、Buttom2、Buttom3的相应IO口初始话为上拉输入,没触发中断。

GPIO_Init(GPIOD,Buttom1|Buttom2|Buttom3,GPIO_MODE_IN_PU_NO_IT);函数原型按键的宏定义设置的模式的定义下面看看按键扫描的函数原型这个函数是当有按键按下的话就返回Buttom_ON,否则的话就返回Buttom_OFF。

他们的宏定义下面在看看另外一个函数这个函数直接是对LED的管脚的值直接取反。

GPIO_WriteReverse(GPIOD, LedPins);函数原型所以Led_Reverse(led1);是和51单片机里面的led1=~led1是一样的。

也就是对该管脚的值取反。

所以在主函数里面的的意思说Buttom1按键按一下灯LED1就会亮,再按一下,灯就会灭,不断循环。

实验现象:当你把例程下载到风驰电子STM8开发板上,你就会看到每当你按一下Buttom1(Key1),灯LED1就会亮,再按一下就会灭,如此循环。

行列式键盘扫描

行列式键盘扫描

实验二 行列式键盘扫描一. 实验内容与目的1. 实验内容利用行列式键盘,当按下键盘中的一个键子时会在数码管上显示出相应的键值,要求键盘有去抖功能,数码管显示的键值能进行移位。

2,实验目的学会行列式键盘扫描的原理与方法,进一步强化对MSP430I/O 口使用方法的掌握,加强msp430C 语言编程的能力。

二. 方法与结果键盘扫描:利用P3口进行键盘扫描,如图,令P3.0~P3.3为输出端口,P3.4~P3.7为输入端口,由于P3.4~P3,7接了上拉电阻,所以当没有键子按下时P3.4~P3.7都为‘1’,当有键子按下时P3.4~P3.7就有可能发生变化。

所以键盘扫描式先让P3.0~P3.3都为‘0’,当有键子按下时P3.4~P3.7就会有一个由‘1’变为‘0’,根据哪一个变为‘0’就能判断出相应的列有键子按下,再让P3.0~p3.3逐个变为‘1’判断出哪一行有键子按下进而确定出哪一个键子按下。

11221112221122311224112251122611227112281122911221122#1122*1122A 1122B1122C1122DR2510k R2610kR2710kR2810kP_30P_31P_32P_33P_34P_35P_36P_37P3.0~p3.3为‘0’P3.4~p3.7都为‘1’P3.4~P3.7不都为‘1’ 令P3.0~p3.3逐个为‘1’ 确定列确定行当P3.4~p3.7都为‘1’确定键值数码管显示:数码管位选与段选共用P1.0~P1.3,利用锁存器74HC373分时进行段选和位选,P6.1和P6.2控制74HC373,从而使相应数码管显示相应数。

电路图如下:e 1d 2d p3c 4g 546b 73829f 10a 11112seg4O E 1Q 02D 03D 14Q 15Q 26D 27D 38Q 39G N D 10L E11Q 412D 413D 514Q 515Q 616D 617D 718Q 719V C C 2074HC373_174HC373O E 1Q 02D 03D 14Q 15Q 26D 27D 38Q 39G N D 10L E11Q 412D 413D 514Q 515Q 616D 617D 718Q 719V C C 2074HC373_274HC373R19100R20100R21100R22100R2310k R2410k P_61P_62VCCVCCGND GNDGND GND GNDGNDP_10P_11P_12P_13P_14P_15P_16P_17三. 实验程序#include<msp430.h> void KEYSCAN(); void TUBESCAN();void KEYSLOVE( unsigned int key); unsigned char const table[]={0xff,0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //0~F 码值 unsigned int s1=0,s2=0,s3=0,s4=0; //s1~s4保存相应键值,进行显示 unsigned int key;void delay1(unsigned int i) {while(i--); }void main() {WDTCTL=WDTPW+WDTHOLD; P1DIR=0xff; P1SEL=0x00; P3SEL=0x00; P3DIR=0x0f;P6DIR=BIT1+BIT2; TUBESCAN(); P3OUT=0xf0; while(1)KEYSCAN();TUBESCAN();}}void KEYSCAN(){P3OUT=0xf0;if(P3IN!=0xf0){switch(P3IN){case (0xe0):P3OUT=0x01;if(P3IN==0xf1) {key=16;break;}P3OUT=0x02;if(P3IN==0xf2) {key=12;break;}P3OUT=0x04;if(P3IN==0xf4) {key=8;break;}P3OUT=0x08;if(P3IN==0xf8) {key=4;break;}case (0xd0):P3OUT=0x01;if(P3IN==0xf1) {key=15;break;}P3OUT=0x02;if(P3IN==0xf2) {key=11;break;}P3OUT=0x04;if(P3IN==0xf4) {key=7;break;}P3OUT=0x08;if(P3IN==0xf8) {key=3;break;}case (0xb0):P3OUT=0x01;if(P3IN==0xf1) {key=14;break;}P3OUT=0x02;if(P3IN==0xf2) {key=10;break;}P3OUT=0x04;if(P3IN==0xf4) {key=6;break;}P3OUT=0x08;if(P3IN==0xf8) {key=2;break;}case (0x70):P3OUT=0x01;if(P3IN==0xf1) {key=13;break;}P3OUT=0x02;if(P3IN==0xf2) {key=9;break;}P3OUT=0x04;if(P3IN==0xf4) {key=5;break;}P3OUT=0x08;if(P3IN==0xf8) {key=1;break;}}P3OUT=0xf0;KEYSLOVE(key);} //键盘扫描函数,得到相应的键值key }void KEYSLOVE( unsigned int key){delay1(200);if(P3IN!=0xf0){while(P3IN!=0xf0) TUBESCAN(); //键盘去抖,保证当手松开时读取键值if(s4==0)s4=s3;s3=s2;s2=s1;s1=key;}else{if(key==16){s1=0;s2=0;s3=0;s4=0;key=0;}}}} //将得到的键值进行处理:移位/重置void TUBESCAN(){P6OUT=0x02;P1OUT=table[s4];P6OUT=0x04;P1OUT=0x01;delay1(400);P6OUT=0x02;P1OUT=table[s3];P6OUT=0x04;P1OUT=0x02;delay1(400);P6OUT=0x02;P1OUT=table[s2];P6OUT=0x04;P1OUT=0x04;delay1(400);P6OUT=0x02;P1OUT=table[s1];P6OUT=0x04;P1OUT=0x08;delay1(400);} //数码管扫描,使数码管保持四.行列式键盘实验总结①做行列是键盘重点是键盘扫描确定键值,键盘扫描也有多种方式,要多思考确定最优方式,采用本实验中的键盘扫描方式当没有键子按下时不必执行键盘扫描的其他程序,将更多的时间给了数码管扫描,挺优的,在着手写程序之前一定要筹划如何去写,要寻求简单易行的方法,写程序规划挺重要的。

用普通IO口测温度

用普通IO口测温度

用普通IO口测温度这是一段利用单片机IO口作的温控程序,感温元件是NTC。

功能是,当温度低过某值时开始加热,随着温度上升。

当高到某值时停止加热,然后开始冷却。

不断重复。

使用时要注意RC常数,常数过大会造成16位计数溢出,得不到正确结果。

程序是作产品前的一个试验程序,当时调试已通过,能作到±0.5℃。

;******************************************************;filename: IOTestNTC.asm; mcu: MDT2005EP; clock: 4 MHz for EXTXT; date: 2006/03/17; writer: aLin;******************************************************;计算被测量电阻。

只做比较,不作计算。

;计算公式:Rx = Rf * (Tx/Tf);Rx为被测电阻;Rf为已知电阻,Rf=10K;Tx为被测电阻对电容C放电的计数值,为16位数;Tf为被测电阻对电容C放电的计数值,为16位数;查温度特性表(NTC型号为:CWF2-473F-3950K,大亚科技制造):;下限温度5摄氏度时电阻为121545.44欧,即121.54544K;换算为:Tx/Tf=Rx/Rf=12.154544;扩大1000倍后结果为:12154.544,约为12155,即2F76H;上限温度8摄氏度时电阻为104712.92欧,即104.71292K;换算为:Tx/Tf=Rx/Rf=10.471292;扩大1000倍后结果为:10471.292,约为10471,即28E7H;-------------------------------------------------------------------list p=pic16c54#i nclude "p16c5x.inc";定义I/O口#define vt portb,0#define rf portb,1#define rx portb,2#define on portb,4#define off portb,4#define f0 user,0;RAM 分配CNT EQU 10H ;计数器SOU1 EQU 11H ;四字节被除数最低位和16位商的低8位SOU2 EQU 12H ;被除数和16位商高8位SOU3 EQU 13H ;被除数和16位余数的低8位SOU4 EQU 14H ;四字节被除数最高位和16位余数的高8位USER EQU 15H ;用户标记位SOU EQU 16H ;被数低8位和积(四字节积的最低位)和RX电阻计数器低8位SOUH EQU 17H ;被乘数高8位和积和RX电阻计数器高8位RLT EQU 18H ;乘数低8位和积RLTH EQU 19H ;乘数高8位和积(四字节积的最高位)TEMP1 EQU 1AH ;临时寄存器1-4TEMP2 EQU 1BHTEMP3 EQU 1CHTEMP4 EQU 1DHRFCNTL EQU 1EH ;RF电阻计数器低8位RFCNTH EQU 1FH ;RF电阻计数器高8位;---------------------------------ORG 0000hstart bcf fsr,6 ;选择bank0bcf fsr,5movlw b'11101111' ;RB4定义为输出,其余输入,PortB4为一直输出tris 06h;---------------------------------------------------;停止加热处理程序;等待温度降到5摄氏度以下是,重新加热,跳到加热处理程序;;负温度系电阻,阻值越大,温度越低;用5摄氏度时对应的电阻减去测出的电阻,为负数,表明实际温度已低过5摄氏度;需加热处理;HOT_DOWN bcf off ;停止加热; call d1s ;延时1秒call io_rm ;调用测量电阻程序call DUMUL ;调用16位无符号乖法程序call DUDIV ;调用32位除以16位无符号除法程序;比较商大小;0E10 对应36K电阻,温度是31度MOVLW 2FHMOVWF TEMP1MOVF SOU2,WSUBWF TEMP1,W ;商高8位先减BTFSS STATUS,C ;检查是否有借位,有借位时C=0GOTO HOT_UP ;有借位,被减数小于减数,跳到加热程序BTFSS STATUS,Z ;无借位,查相减结果是否为0GOTO HOT_DOWN ;结果不为0,则被减数大于减数,跳到停止加热程序MOVLW 76H ;商高8位相等,商低8位相减MOVWF TEMP1MOVF SOU1,WSUBWF TEMP1,WBTFSS STATUS,CGOTO HOT_UPBTFSS STATUS,ZGOTO HOT_DOWNGOTO HOT_DOWN ;两数相等,返回;--------------------------------------;;加热程序处理程序;;当温度大于8摄氏度时跳到停止加热程序;HOT_UP bsf on ;加热; call d1s ;延时1秒call io_rm ;调用测量电阻程序call DUMUL ;调用16位无符号乖法程序call DUDIV ;调用32位除以16位无符号除法程序;比较商大小;07D0对应电阻20K,温度45度MOVLW 28HSUBWF SOU2,W ;商高8位先减BTFSS STATUS,C ;检查是否有借位,有借位时C=0GOTO HOT_DOWN ;有借位,被减数小于减数,跳到停止加热程序BTFSS STATUS,Z ;无借位,查相减结果是否为0GOTO HOT_UP ;结果不为0,则被减数大于减数,跳到加热程序MOVLW 0E7H ;商高8位相等,商低8位相减SUBWF SOU1,WBTFSS STATUS,CGOTO HOT_DOWNBTFSS STATUS,ZGOTO HOT_UPGOTO HOT_UP ;温度未低过下限温度,返回继续等待;----------------------------------------;io_rm clrf SOUHclrf SOUclrf RFCNTHclrf RFCNTLcall fullcharge ;让电容充电。

ATmega8-Protues仿真之三 键盘扫描

ATmega8-Protues仿真之三 键盘扫描

第三讲键盘扫描的学习提要:主要学习Atmega8通用数字I/O接口扫描键盘的应用。

前面我们学习了ATmega8的I/O口作为通用数字输入/输出口来用时对LED 数码管控制的应用,其实主要是作为输出口的应用。

下面我们就来学习一下用作输入口的应用――扫描键盘。

3.1 按键的使用特点:按键的应用主要就是在按键闭合时改变电路的电平,但是一般情况下按键的开关都是机械弹性触点开关,它利用触点的接触和分离来实现电路的通断,在按键按下和释放时往往会产生抖动干扰,所以要想办法消除抖动干扰。

消除抖动干扰即可用硬件设计也可用软件设计的方法。

硬件消抖就要在硬件设计上增加消抖电路,如用R-S触发器等,这样就会增加系统成本。

软件消抖就是要在软件中对按键进行二次测试确认,既当第一次检测到按键被按下后,间隔10毫秒左右再次检测该按键是否被按下,只有两次都册到按键按下时才确认该按键被按下了,从而消除抖动干扰。

另外我们还要判别按键的释放,为了设计方便,我们现不考虑长时间按下按键的情况,只简单考虑检测到按下和释放才计作一次按键操作。

3.2 单键盘扫描的应用下面我们就用软件消抖的方法来做个简单的应用,我们用PB口接一个LED 数码管,用来显示数据,用PC0端口接一个按键电路,我先画出电路:我们要实现的功能是每按一次按键,LED数码管显示的数据加1,到9回0。

怎么样不是很复杂吧,是不是很快就可以些出来了呢?下面是我写的,你也参考一下吧:上面的程序没考虑按键长按的情况,如果象我们使用的键盘一样,长时间按下一个按键,在屏幕上就不断的打印该字符,在这个例子里就是长时间按下按键的话就对CountNum加一,而不是每次按下按键一次就加一一次,该怎么考虑呢,你可以试试能不能实现。

3.3 矩阵按键(键盘)扫描的应用如果按键多的话,我们一般就要考虑节省I/O资源,通常会考虑采用矩阵式的接口。

矩阵键盘由行和列组成,每个按键都有它的行值和列值,行值和列值的组合就是识别每个键盘的编码。

plc及伺服IO接口电路常用接法

plc及伺服IO接口电路常用接法

plc及伺服IO接口电路常用接法集电极开路输出我们先来说说集电极开路输出的结构。

集电极开路输出的结构如图1所示,右边的那个三极管集电极什么都不接,所以叫做集电极开路(左边的三极管为反相之用,使输入为“0”时,输出也为“0”)。

对于图1,当左端的输入为“0”时,前面的三极管截止(即集电极c跟发射极e之间相当于断开),所以5v电源通过1k电阻加到右边的三极管上,右边的三极管导通(即相当于一个开关闭合);当左端的输入为“1”时,前面的三极管导通,而后面的三极管截止(相当于开关断开)。

我们将图1简化成图2的样子。

图2中的开关受软件控制,“1”时断开,“0”时闭合。

很明显可以看出,当开关闭合时,输出直接接地,所以输出电平为0。

而当开关断开时,则输出端悬空了,即高阻态。

这时电平状态未知,如果后面一个电阻负载(即使很轻的负载)到地,那么输出端的电平就被这个负载拉到低电平了,所以这个电路是不能输出高电平的。

再看图三。

图三中那个1k的电阻即是上拉电阻。

如果开关闭合,则有电流从1k电阻及开关上流过,但由于开关闭和时电阻为0(方便我们的讨论,实际情况中开关电阻不为0,另外对于三极管还存在饱和压降),所以在开关上的电压为0,即输出电平为0。

如果开关断开,则由于开关电阻为无穷大(同上,不考虑实际中的漏电流),所以流过的电流为0,因此在1k电阻上的压降也为0,所以输出端的电压就是5v了,这样就能输出高电平了。

但是这个输出的内阻是比较大的(即1kω),如果接一个电阻为r的负载,通过分压计算,就可以算得最后的输出电压为5*r/(r+1000)伏,即5/(1+1000/r)伏。

所以,如果要达到一定的电压的话,r就不能太小。

如果r真的太小,而导致输出电压不够的话,那我们只有通过减小那个1k的上拉电阻来增加驱动能力。

但是,上拉电阻又不能取得太小,因为当开关闭合时,将产生电流,由于开关能流过的电流是有限的,因此限制了上拉电阻的取值,另外还需要考虑到,当输出低电平时,负载可能还会给提供一部分电流从开关流过,因此要综合这些电流考虑来选择合适的上拉电阻。

用单片机IO口直接驱动段式LCD的方法

用单片机IO口直接驱动段式LCD的方法用IO口驱动段式LED(数码管)的方法相信大家比较清楚,但用IO口直接驱动段式LCD的方法相对复杂一些。

在网上搜了一下单片机IO口驱动段式LCD的方法,大部分资料讲得不够清晰、具体,而且简单问题复杂化。

后来查了LCD的显示原理,结合网上的相关介绍,发现IO口直接驱动段式LCD原理比较简单,用几句话就可以描述清楚:和LED的显示原理不一样:LED是加正向电压发光,而LCD必须交替加正、反向电压才会持续显示(可以做个实验,如果把恒定电压加到LCD的一段上,该段会显示一下,但马上不能显示,而且长时间加恒定电压,会加速LCD的老化和损坏)2.常听说1/2bias,1/3bias LCD,是什么意思呢对于1/2bias LCD,假如LCD的显示电压是3V,则1/2bias是,也就是说在±3V电压作用时,LCD有显示;±及以下的电压作用时没有显示3.普通单片机IO口不能直接输出半高电平(),但可以用相等的上下拉电阻实现,当IO口设置为输入(高阻)时,由于上下拉电阻的分压作用,则产生一个半高电平()知道了以上3点后,动态驱动LCD就不是难事了,对于4*8段的LCD(4个COM,8个SEG,显示电压为3V,1/2bias),驱动方法如下:1、四个COM采用交替扫描的方式,每个COM在相邻两次扫描时又进行电压交变的方式。

2、若扫描到某一个COM时,该COM输出3V(0V):与该COM相连的SEG输出与COM相反,ΔV=±3V,则该相连点亮;与该COM相连的SEG输出与COM相同,ΔV=0,则该相连点不亮。

3、其他没有扫描到的COM,单片机IO口为输入,从而产生1/2 bias(),不管SEG为何值,ΔV<±,故该点不亮。

本人用4*8段的LCD自制了一个数字钟表,验证了以上方法的可行性,现把制作过程罗列如下1.原理图说明:由于管脚不够用,所以时钟芯片DS1302的RST和LCD的一个SEG是复用的,只要在这个SEG无效的时候去读取时间就可以了,另外,3PIN串口是ISP 下载程序用的。

全面剖析单片机io口的原理与应用技巧

全面剖析单片机io口的原理与应用技巧IO口操作是单片机实践中最基本最重要的一个知识,本篇花了比较长的篇幅介绍IO口的原理。

也是查阅了不少资料,确保内容正确无误,花了很长时间写的。

IO口原理原本需要涉及很多深入的知识,而这里尽最大可能做了简化方便理解。

这样对于以后解决各种IO口相关的问题会有很大的帮助。

IO口等效模型是本人独创的方法,通过此模型,能有效的降低对IO口内部结构理解的难度。

并且经查阅资料确认,这种模型和实际工作原理基本一致。

前面说了很多东西,不少人或许已经迫不及待的想要实际操作单片机了。

IO口作为单片机与外界通信最主要的手段,是单片机学习最基本也最重要的一个知识。

前面我们编程实现了IO口点亮LED的实验,本篇继续对IO口相关知识进行介绍。

为了更好的学习IO口操作,有必要了解一下IO口的内部结构和相关概念。

这些知识对于后续的学习很有帮助,重点是理解,完全不需要刻意去记。

不记得就回来再看看就行了,用得多了自然就记住了。

我们说过,要了解一个芯片,最准确有效的方法,是查看官方给出的芯片手册等资料。

但是初学单片机,直接看芯片手册资料恐怕很难弄明白,尤其是看到一堆英文、陌生的电路、名词术语,如果是我,一定也会抓狂的。

但是这里我还是给出一张从Atmel官方的《Atmel 8051 Microcontrollers Hardware Manual》中截取的图片。

给出这张图片并不是为了打击大家学习热情,而是希望大家能明白,我们所见过的各种单片机资料到底是怎么来的,到底是否准确,这一切都可以通过官方资料弄清楚,对于大家以后深入学习一些东西有一定的帮助。

第二功能简介上图正是官方给出的权威的51单片机IO口结构图。

可以看出,单片机的四组IO口内部结构各不相同,原因是有些IO口有第二功能,入门篇里面提到过。

还记得这张管脚图吗?括号中标注的就是IO口的第二功能名称。

除了P1以外,每个接口都有第二功能。

介绍单片机系统模块时,我提到51单片机有预留扩展存储器的接口,正。

单片机IO端口工作原理

单片机IO端口工作原理单片机(IO)端口工作原理是指单片机芯片中用来与外部输入输出设备进行数据交换的控制引脚,它可以将外部数据引入到单片机内部进行处理,或者将单片机内部处理的数据输出到外部设备上。

常用的单片机(IO)端口包括P0、P1、P2和P3等。

其中,P0端口是8051系列单片机中最常用的IO端口之一、它具有三种工作模式:漏极开路模式、推挽模式和准双向口模式。

首先,漏极开路模式是指P0端口作为输入端口时,引脚处于高阻态。

这时,外部设备通过给引脚上拉或下拉来实现输入,单片机通过读取引脚的状态来获取外部输入的数据。

当P0端口作为输出端口时,引脚采用的是开漏输出的方式,即输出1时,引脚处于高阻态;输出0时,引脚处于低电平态。

这种模式下,输出引脚需要连接外部上拉电阻或二极管来实现高电平输出。

其次,推挽模式是指P0端口既可以作为输入端口,也可以作为输出端口。

当P0端口作为输入端口时,引脚需要通过外部上拉或下拉电阻来实现输入;当P0端口作为输出端口时,引脚采用的是推挽输出方式,输出1时,引脚处于高电平态;输出0时,引脚处于低电平态。

这种模式下,引脚无需连接外部上拉电阻。

最后,准双向口模式是指P0端口同时具有输入和输出的功能。

当P0端口作为输入端口时,引脚通过外部上拉或下拉电阻来实现输入;当P0端口作为输出端口时,引脚采用的是推挽输出方式,输出1时,引脚处于高电平态;输出0时,引脚处于低电平态。

这种模式下,输入和输出的数据通过引脚上的跳线帽来选择输入还是输出。

除了以上三种工作模式,P0端口还可以通过连接外部上拉电阻来实现上拉电阻功能。

上拉电阻可以在引脚上提供一个默认的高电平,当引脚未被外部设备拉低时,引脚处于高电平状态。

这种方式主要用于消除外部干扰。

总之,单片机IO端口工作原理涉及漏极开路、推挽、上拉电阻和准双向口等多种方式,通过选择不同工作模式和引脚连接方式来实现数据的输入和输出功能。

开发人员可以根据具体的应用需求选择合适的工作模式和连接方式。

扫描SCAN算法和循环扫描CSCAN

各种扫描算法
扫描(SCAN)算法
进程“饥饿”现象
对于SSTF算法,只要不断有新进程到达,且其所要访问的磁道与磁头当前所在磁
道的距离较近,这种新进程的I/O请求务必先被满足,形成老进程的“饥饿”现象。

SCAN算法
该算法不仅考虑到欲访问的磁道与当前磁道的距离,更优先考虑的是磁头的当前
移动方向。

这种算法中磁头移动的规律颇似电梯的运行,又称电梯调度算法。

循环扫描CSCAN(Circular SCAN)
为了减少SCAN算法造成的某些进程的请求被严重推迟,CSCAN算法规定磁头单向移动。

(从100#磁道开始,向磁道号增加的方向)
SCAN调度算法示例(从100#磁道开始,向磁道号增加的方向)
CSCAN调度算法示例N-Step-SCAN和FSCAN调度算法
N-Step-SCAN算法
将磁盘请求队列分成若干个长度为N的子队列,磁盘调度按FCFS算法处理子队列,
而处理队列则按SCAN算法,这样可避免粘着现象。

FSCAN算法
实质上是N-Step-SCAN算法的简化。

它只将磁盘请求队列分成两个子队列。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

在做项目(工程)的时候,我们经常要用到比较多的按键,而且IO资源紧张,于是我们就想方设法地在别的模块中节省IO口,好不容易挤出一两个IO 口,却发现仍然不够用,实在没办法了就添加一个IC来扫键。

一个IC虽然价格不高,但对于大批量生产而且产品利润低的厂家来说,这是一笔不菲的开支! 那,我们能不能想到比较好的扫键方法:用最少的IO口,扫最多的键?可以吗?举个例:给出5个IO口,能扫多少键?有人说是2*3=6个,如图一:
图一
对,大部分技术参考书都这么做,我们也经常这样做:用3个IO口作行扫描,2个IO作列检测(为方便描述,我们约定:设置某一IO口输出为“0”――称其为“扫某IO口”)。

用行线输出扫键码,列线检测是否有按键的查询方法进行扫键。

扫键流程:在行线依次输出011,101,110扫键值,行线每输出一个扫键值,列线检测一次。

当列线检测到有按键时,结合输出的扫键值可以判断相应的按键。

但是,5个IO真的只能扫6个键吗?有人说可以扫9个,很聪明!利用行IO 与地衍生3个键(要注意上拉电阻),如图二:
图二
扫键流程:先检测3个行IO口,对K1’,K2’,K3’进行扫键,之后如上述2*3扫键流程。

5个IO口能扫9个键,够厉害吧,足足比6个键多了1/2!
动动脑,还能不能再多扫几个?就几个?一个也行!好,再想一下,硬是被逼出来了!如图三:
图三
不多不少,正好10个键!这种扫键方式比较少见吧!漂亮!扫键流程:设IO1输出为“0”,检测IO2…IO5,若判断有相应健按下,则可知有健;若无键,则继续扫键:设IO2输出为“0”,检测IO3,IO4,IO5,判断有无键按下,如此类推。

这里应注意:当扫某一IO口(输出为“0”)时,不要去检测已经扫过的IO 口。

如:此时设置IO2输出为“0”,依次检测IO3,IO4,IO5,但不要去检测IO1,否则会出错(为什么,请思考)。

感觉怎么样?不错吧!让我们再看看图三,好有成就感!看着,看着……又看到了什么?快!见图四:
图四
真强!被您看出20个键!多了一个对称的三角形。

可是,像这样的排列能正确扫20个键吗?回答是肯定的:不能!上下三角形相互对称,其对称扫出的键无法区别。

有没有注意到分析图三时提到的注意点?(à“当扫某IO口时,不要去检测已经扫过的IO口,否则会出错”)
我们分析一下图四:当IO1输出“0”时,按下K11或K11’键都能被IO2检测到,但IO2检测却无法区别K11和K11’键!同理,不管扫哪个IO口,都有两个对称的键不能区分。

我们假想,如果能把对称键区分开来,我们就能正常地去判断按键。

我们在思考:有没有单向导通性器件?有!见图五!
图五
很巧妙的思路!利用二极管的单向导通性,区别两个对称键。

扫键思路:对逐个IO口扫键,其他四个IO口可以分别检测其所在的四个按键。

这样,就不会有分析图三时提到的注意点。

够酷吧!等等,大家先别满足现状,我们再看一下图二,是不是有点启发?对,我们再分析一下“用5个IO口对地衍生的5个键”。

看图六:
图六
25个键!5个IO口扫出25个键!先别激动,我们再分析一下它的可行性,分析通得过才能真正使用。

假设扫键流程:先扫对地的5个键,再如图五扫键。

先扫对地5个键,判断没有按键,接着对逐一对IO口进行扫键。

但当对某一IO 口扫键时,如果有对地的键按下,这时有可能会误判按键,因为对地键比其他键有更高的响应优先级。

例如:扫IO1,IO1输出“0”,恰好此时K62按下,IO2检测到有按键,那就不能判断是K11还是K62。

我们可以在程序上避免这种按键误判:若IO2检测到有按键,那下一步就去判断是否有对地键按下,如果没有,那就可以正确地判断是K11了。

我们小结扫键个数S:
S = (N-1)*N + N ――启用二极管S = (N-1)*N /2 + N ――省掉二极管。

相关文档
最新文档