单片机C语言学习入门资料(3)

2019-03-27 16:55

{

P1_0 = 1; while( 1 ) {

{

//作为输入引脚,必须先输出高电平 //永远为真,即死循环

//如果按键,则为低电平

//如果一直按着键,则不停地执行该循环,实际是等待松键

if( P1_0 == 0 )

keyPut( 6 ); //保存按键编号值为按键队列 while( P1_0 == 0 );

}

if( keyHit() != 0 )

//如果队列中有按键

//从队列中取出按键值,并显示在数码管上

P2=Seg7Code[ keyGet() ];

}

}

例二:在例一中考虑按键20ms抖动问题。 #include #include “KEY.H” void main( void ) {

P1_0 = 1; while( 1 ) {

{

//作为输入引脚,必须先输出高电平 //永远为真,即死循环

//如果按键,则为低电平

if( P1_0 == 0 )

delay20ms(); //延时20ms,跳过接下抖动 keyPut( 6 ); //保存按键编号值为按键队列 while( P1_0 == 0 );

//如果一直按着键,则不停地执行该循环,实际是等待松键

}

delay20ms(); //延时20ms,跳过松开抖动 if( keyHit() != 0 )

}

例三:在例二中考虑干扰问题。即小于20ms的负脉冲干扰。 #include #include “KEY.H” void main( void ) {

P1_0 = 1; while( 1 ) {

{

//作为输入引脚,必须先输出高电平 //永远为真,即死循环

//如果按键,则为低电平

}

//如果队列中有按键

//从队列中取出按键值,并显示在数码管上

P2=Seg7Code[ keyGet() ];

if( P1_0 == 0 )

delay20ms(); //延时20ms,跳过接下抖动

if( P1_0 == 1 ) continue; //假按键 keyPut( 6 ); //保存按键编号值为按键队列 while( P1_0 == 0 );

//如果一直按着键,则不停地执行该循环,实际是等待松键

}

delay20ms(); //延时20ms,跳过松开抖动 if( keyHit() != 0 )

}

例四:状态图编程法。通过20ms周期中断,扫描按键。

}

//如果队列中有按键

//从队列中取出按键值,并显示在数码管上

P2=Seg7Code[ keyGet() ];

/**************************************************************************************** 采用晶体为12KHz时,指令周期为1ms(即主频为1KHz),这样T0工作在定时器方式2,8位自动重载。计数值为20,即可产生20ms的周期性中断,在中断服务程序中实现按键扫描

*****************************************************************************************/ #include #include “KEY.H” void main( void ) {

TMOD = (TMOD & 0xf0 ) | 0x02; //不改变T1的工作方式,T0为定时器方式2 TH0 = -20; TL0=TH0; TR0=1; ET0=1; EA=1;

{

if( keyHit() != 0 )

}

void timer0int( void ) interrupt 1 {

static unsigned char sts=0; P1_0 = 1; {

case 0: if( P1_0==0 ) sts=1; break; //按键则转入状态1 case 1:

if( P1_0==1 ) sts=0; break;

}

}

case 2: if( P1_0==1 ) sts=3; break; //如果松键,则转状态3 case 3:

if( P1_0==0 ) sts=2; else sts=0;

//假松键,回状态2

//真松键,回状态0,等待下一次按键过程

//假按错,或干扰,回状态0

else{ sts=2; keyPut( 6 ); } //确实按键,键值入队列,并转状态2

//作为输入引脚,必须先输出高电平

switch( sts )

//20ms;T0的中断号为1

}

//如果队列中有按键

//从队列中取出按键值,并显示在数码管上

P2=Seg7Code[ keyGet() ];

//计数周期为20个主频脉,即20ms //先软加载一次计数值 //允许T0开始计数

//允许T0计数溢出时产生中断请求 //允许CPU响应中断请求

while( 1 ) //永远为真,即死循环

例五:状态图编程法。

/**************************************************************************************** 如果采用晶体为12MHz时,指令周期为1us(即主频为1MHz),要产生20ms左右的计时,则计数值达到20000,T0工作必须为定时器方式1,16位非自动重载,即可产生20ms的周期性中断,在中断服务程序中实现按键扫描

*****************************************************************************************/ #include #include “KEY.H”

void main( void ) {

TMOD = (TMOD & 0xf0 ) | 0x01; //不改变T1的工作方式,T0为定时器方式1 TL0 = -20000; TR0=1; ET0=1; EA=1;

{

if( keyHit() != 0 )

}

void timer0int( void ) interrupt 1 {

static unsigned char sts=0; TL0 = -20000;

P1_0 = 1; {

case 0: if( P1_0==0 ) sts=1; break; //按键则转入状态1 case 1:

if( P1_0==1 ) sts=0; break;

}

}

case 2: if( P1_0==1 ) sts=3; break; //如果松键,则转状态3 case 3:

if( P1_0==0 ) sts=2; else sts=0;

//假松键,回状态2

//真松键,回状态0,等待下一次按键过程

//假按错,或干扰,回状态0

else{ sts=2; keyPut( 6 ); } //确实按键,键值入队列,并转状态2

//方式1为软件重载

//右移8位,实际上是取高8位

TH0 = (-20000)>>8; switch( sts )

//20ms;T0的中断号为1

}

//如果队列中有按键

//从队列中取出按键值,并显示在数码管上

P2=Seg7Code[ keyGet() ];

//计数周期为20000个主频脉,自动取低8位 //右移8位,实际上是取高8位 //允许T0开始计数

//允许T0计数溢出时产生中断请求 //允许CPU响应中断请求

TH0 = (-20000)>>8;

while( 1 ) //永远为真,即死循环

//作为输入引脚,必须先输出高电平

例六:4X4按键。

/**************************************************************************************** 由P1端口的高4位和低4位构成4X4的矩阵键盘,本程序只认为单键操作为合法,同时按多键时无效。 这样下面的X,Y的合法值为0x7, 0xb, 0xd, 0xe, 0xf,通过表keyCode影射变换可得按键值

10 P1.0(0xE) C P1.1(0xD) 8 P1.2(0xB) 4 P1.3(0x7) F B 7 3 E A 6 2 D 9 5 1 P1.4(E) P1.5(D) P1.6(B) P1.7(7) *****************************************************************************************/ #include #include “KEY.H”

unsigned char keyScan( void ) {

//返回0表示无按键,或无效按键,其它值为按键编码值

code unsigned char keyCode[16]=

/0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 4, 0 }; unsigned char x, y, retVal; P1=0x0f; x=P1&0x0f; P1=0xf0;

//低四位输入,高四位输出0 //P1输入后,清高四位,作为X值 //高四位输入,低四位输出0

//P1输入后移位到低四位,并清高四位,作为Y值

y=(P1 >> 4) & 0x0f;

retVal = keyCode[x]*4 + keyCode[y]; //根据本公式倒算按键编码 if( retVal==0 ) return(0); else return( retVal-4 ); }

//比如按键‘1’,得X=0x7,Y=0x7,算得retVal= 5,所以返回函数值1。 //双如按键‘7’,得X=0xb,Y=0xd,算得retVal=11,所以返回函数值7。 void main( void ) {

TMOD = (TMOD & 0xf0 ) | 0x01; //不改变T1的工作方式,T0为定时器方式1 TL0 = -20000; TR0=1; ET0=1; EA=1;

{

if( keyHit() != 0 )

//如果队列中有按键

//计数周期为20000个主频脉,自动取低8位 //右移8位,实际上是取高8位 //允许T0开始计数

//允许T0计数溢出时产生中断请求 //允许CPU响应中断请求

TH0 = (-20000)>>8;

while( 1 ) //永远为真,即死循环

P2=Seg7Code[ keyGet() ];

}

void timer0int( void ) interrupt 1 {

static unsigned char sts=0; TL0 = -20000;

P1_0 = 1; {

}

//从队列中取出按键值,并显示在数码管上

//20ms;T0的中断号为1 //方式1为软件重载

//右移8位,实际上是取高8位

TH0 = (-20000)>>8; switch( sts )

//作为输入引脚,必须先输出高电平

case 0: if( keyScan()!=0 ) sts=1; break; //按键则转入状态1 case 1:

if( keyScan()==0 ) sts=0; break;

//假按错,或干扰,回状态0

else{ sts=2; keyPut( keyScan() ); } //确实按键,键值入队列,并转状态2

}

}

case 2: if(keyScan()==0 ) sts=3; break; //如果松键,则转状态3 case 3:

if( keyScan()!=0 ) sts=2; else sts=0;

//假松键,回状态2

//真松键,回状态0,等待下一次按键过程

第六节:低频频率计

实例目的:学时定时器、计数器、中断应用

说明:选用24MHz的晶体,主频可达2MHz。用T1产生100us的时标,T0作信号脉冲计数器。假设晶体频率没有误差,而且稳定不变(实际上可达万分之一);被测信号是周期性矩形波(正负脉冲宽度都不能小于0.5us),频率小于1MHz,大于1Hz。要求测量时标1S,测量精度为0.1%。

解:从测量精度要求来看,当频率超过1KHz时,可采用1S时标内计数信号脉冲个数来测量信号频,而信号频率低于1KHz时,可以通过测量信号的周期来求出信号频率。两种方法自动转换。

对于低于1KHz的信号,信号周期最小为1ms,也就是说超过1000us,而我们用的定时器计时脉冲周期为0.5us,如果定时多计或少计一个脉冲,误差为1us,所以相对误差为1us/1000us=0.1%。信号周期越大,即信号频率越低,相对误差就越小。

从上面描述来看,当信号频率超过1KHz后,信号周期就少于1000us,显然采用上面的测量方法,不能达到测量精度要求,这时我们采用1S单位时间计数信号的脉冲个数,最少能计到1000个脉冲,由于信号频率不超过1MHz,而我们定时脉冲为2MHz,最差多计或少计一个信号脉冲,这样相对误差为1/1000,可见信号频率越高,相对误差越小。

信号除输入到T1(P3.5)外,还输入到INT1(P3.3)。 unsigned int us100; unsigned char Second; unsigned int K64; unsigned char oldT0;

unsigned int oldus, oldK64, oldT1; unsigned long fcy;

//存放频率值,单位为Hz

//对64K单位计数,即有多少个64K

//对100us时间间隔单位计数,即有多少个100us。


单片机C语言学习入门资料(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:小商品批发市场可行性研究报告

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: