c51常用程序大全
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
TL0=(65536-45872)%256; EA=1; //开总中断 ET0=1; //定时器/计数器0 中断允许位 TR0=1; //启动定时器/计数器0
while(1); //程序停止在这里等待中断发生 } void T0_time() interrupt 1 //中断序号INT0-0,T0-1,INT1-2,T1-3,TI/RI-4,T2-5 {
{ if(keycode==key_code[j])//查表得键值 { key=j;
}
}
}
}
}
3.数码管显示:
1.当程序程序返回函数时间太长,会有前几位显示很暗,最后一位显示很亮;原因:每次 调用这个函数的时候,4个数码管刷新一遍,所以4个数码管都会亮,在这个函数内部,4个 数码管是一样亮的。但是函数返回的时候一直到下次再调用这个程序这段时间(很长的时 间)都是程序里面最后一个数码管在亮---解决办法用定时器
{ if(num1>=4000) { num1=0; d1=~ d1; } if(num2>=2000) { num2=0; d2=~ d2; }
} } void TL0_time() interrupt 1 //中断序号INT0-0,T0-1,INT1-2,T1-3,TI/RI-4,T2-5 {
TL0= 6; num1++; }
i=0;
d1=~ d1;
d2=~ d2;
}
}
void T0_time() interrupt 1
{
i++;
}
IV.工作方式3,当TMOD=0X03时,TO工作在方式3,T1无论处于那种工作方式都不可以使用中断,因为 其中断TF1被TH0给占用了
uint num1,num2;
void main()
{
TMOD=0x03;
delay_ms(20);//延时30ms scan1=P3; if((scan1&0xf0)!=0xf0)//二次判键是否按下 {
P3=0x0f;//线翻转法 delay_ms(1);//延时 scan2=P3;//读P3口的状态 keycode=scan1|scan2; //组合成键编码 while(P3!=0x0f); //等待按键释放 for(j=0;j<=15;j++)
a3=num%100000%10000%1000/100;
a2=num%100000%10000%1000%100/10 ;
a1=num%10;
dispay(b3,b2,b1,a3,a2,a1);
}
}
总而言之,T0,T1是计数还是定时、工作为方式几都由寄存器TMOD设置;T2的定时设置、计数设置 由 寄存器T2CON控制,具体看书P212
void keyscan()
{
uchar scan1,scan2,keycode,j;
/*****************************************/
/* 一、scan1读取P3值时,恰好已经有按键按下
/* 改变了P3口,而不是太快虽有按键按下, /* 但scan1读取P3值仍为开始设置值; /*二、延时夷小不大,否则按下键后值到松开scan1还没 /* 去读取P3值,后面在读取则也仍为起始设置的值 /***********************************************/ P3=0xf0;//先给矩阵的行发初值P3=1111 0000也即来检测按下键后是那列拉低 delay_ms(1);//此处的延时目的;一、; 二、(应此要考虑当程序过多时,scan1 读P3口是否是键按下) scan1=P3;//读P3口的状态 if((scan1&0xf0)!=0xf0)//判键是否按下 {
//0000 0011 设置定时器0为工作方式3
TH0= 256-250 ; //6 以1s装初值,12M溢出4000次,11.0592溢出3686次 TL0= 256-250 ; //6 EA=1; //开总中断 ET0=1; //定时器/计数器0 中断允许位 ET1=1; //开定时器1中断 TR0=1; //启动定时器0 TR1=1; //启动定时器0的高8位Biblioteka Baidu数器 while(1) //程序停止在这里等待中断发生
头文件:#include"reg52.h " reg51.h
#include"math.h" #include"intrins.h"
stdio.h ctype.h stdlib.h absacc.h < > -编译器先进入到软件安装文件夹处开始搜索这个头文件,如果这个文件夹下没有引用的头文件, 编译器将会报错。 " " --编译器先进入到当前工程所在文件夹处开始搜索该头文件,如果当前工程所在文件夹下没有 该头文件,则编译器回到前者。
TR0=1; //启动T0计数器
TH0=0; //装初值
TL0=0;
while(1)
{
num=read();
if(num>=245959)
//TL0
{
num=0; //TL0
TH0=0; //将计数器寄存器值清0
TL0=0;
}
b3=num/100000
;
b2=num %100000/10000;
b1=num%100000%10000/1000 ;
break;
}
val=th1*256+t1; //T0工作方式1
return val;
}
void main()
{
TMOD=0x05;
//模式设置,0000 0101,可见采用的是定时器0,
//利用计数器模式(c/t非=1)且工作为方式1(M1=0,M0=1)
EA=1; //开总中断
ET0=1; //定时器/计数器0 中断允许位
当12M,t=50ms,则 N=t/Tcy=50000
I.工作方式1,16位定时器/计数器,不会自动重装,只会默认从0开始
void main()
{
TMOD=0x01;//00000001 启用定时器/计数器0,工作方式为1,即16位的定时器
TH0=(65536-45872)/256; //定50ms的初值
基本数据类型:p17书c51 bit 位变量声明,sbit 特殊功能位声明
#define uint unsigned int #define uchar unsigned char
typedef unsigned char byte; typedef unsigned int word;
1.延时大全:
//段选
uchar code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f }; //不带点的
uchar code table1[]={ 0xbf,0x86,0xdb,0xcf, 0xe6,0xed,0xfd,0x87, 0xff,0xef }; //带点的
int i; TH0=(65536-45872)/256; //中断中的中断,给初值 TL0=(65536-45872)%256; i++; if(i>=20) //4次,也即1s到时闪烁
{ i=0; d1=~d1; d2=~d2;
} } II.工作方式0,13位定时器/计数器,不会自动重装,只会默认从0开始,装初值THX=(8192-t/Tcy)/32 (8位全部用到) ,TLX=(8192-t/Tcy)%32 (前5位用到) ,当t=5ms时,N=5000/1.0851=4607,其用法 同上;
{
dula=1; P0=table[s3]; //小时h2 dula=0; P0=0xff; //在位选锁存开通时,给d0-d7高电平,位选都不不工作,消影 wela=1; P0=0xfe; wela=0; delay_ms(4);
led=0;
} }
独创矩阵键盘:
#define uchar unsigned char
uchar key;
unsigned char code key_code[]={
0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,
0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77 };//矩阵键盘0-15键值
作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微
秒。 NOP指令为单周期指令(即为12个时钟周期),1/12 us可由晶振频率算出延时时间,对于12M晶振, 延时1uS;对于11.0592M,则n个NOP指令为单周期为1.08155 us * n 对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现
uint i; for(i = us; i>0; i--) { _nop_(); }
}
二、硬件延时
//12M晶振 i=250 ,4个nop
要使定时器产生一次中断的时间为t,那么需装初值 THX=(65536-t/Tcy)/256 ,TLX=(65536-t/Tcy)%256
当11.095M,t=50ms,则 N=t/Tcy=45872
2.独立按键:51开发板独立键和矩阵键盘不能同时用,会有冲突
sbit s2=P3^4;
while(1) { if(s2==0) led=0; else led=1; }
//通过大循环不断扫描按键状态(方法一)
if(s2==0)
//消抖动 (方法二)
{
delay_ms(20);
if(s2==0)
{
while(!s2); //等待按键释放
一、软件延时
void delay_ms(uint xms)
//方法一 (x*1.000445083 ms)
{
uint i,j;
for(i=xms;i>0;i--) //千万别把i--写成i++,否则数码管显示,真他妈坑爹
for(j=114;j>0;j--); //延时x ms
}
#include<intrins.h> //声明了 void _nop_(void); _nop_(); // 产生一条NOP指令
III.工作方式2,8位初值自动重装的8位定时器/计数器,THX作为常数缓冲器,当TLX计数溢出时, 在溢出TFX置1的同时,还自动将THX中的常数重装入TLX中。THX=256-t/Tcy,TLX=256-t/Tcy unsgined int i; void main()
{ TMOD=0x02;
void delay(int ms)
//方法二
{
int i;
while(ms--)
{
for(i = 185; i>0; i--) //12M晶振
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
i=250 ,4个nop
/****微秒延时******/ void delay_us(uint us) {
void TH0_time() interrupt 3
{
TH0=6;
num2++;
}
三、T0用作计数器且为工作模式1
uint read() //读取TH0,TL0中计数的数值
{
uchar t1,th1,th2;
uint val;
while(1)
{
th1=TH0;
t1=TL0;
th2=TH0;
if(th1==th2) //TH0寄存器的值需要读两次以确保读取的时候没有发生进位
2.当数码管显示时,数字显示模糊不清时,那就是个数字间的延时太长
#define uint unsigned int //所占位数16,表示数范围0-65535 #define uchar unsigned char //所占位数8,表示数范围0-255
sbit dula=P2^6; sbit wela=P2^7;
//0000 0010
TH0= 256-250 ; //6
TL0= 256-250 ; //6
EA=1;
ET0=1;
TR0=1;
while(1)
{
if(i>=4000) //本来是可以写成i==4000;但我们必须考虑到如果,
{ //有几个中断,就会出现有个中断也同时达到,但因要走程序就会错过那次中断
//WE1、WE1、WE1、WE1、WE1、WE1 位选
//fe, fd, fb, f7, ef, df
void dispay(uchar s3,uchar s2,uchar s1,uchar m3,uchar m2,uchar m1) // 数码管由 左到右的显示顺序 uchar h2,uchar h1,uchar m2,uchar m1,uchar s2,uchar s1