51单片机基本程序

合集下载

51单片机常见程序,附带注释

51单片机常见程序,附带注释

51 单片机常见程序附带注释三位数分离成 3 个一位数,截取bai=num/100;// 输出百位数shi=num%100/10;// 输出十位数ge=num/10;// 输出个位数//跑马灯程序。

当时间约为20ms形成动态扫描,#include<intrins.h>#define uint unsigned int // 无符号整型,占16 位数,表示围0~65536#define uchar unsigned char // 无符号字符型占八位数,表示围0~255void delayms(uint);uchar aa;// 定义变量void main(){aa=0xfe;while(1){aa=_crol_(aa, 1);P2=aa; // 控制单片机接口p2, 循环亮delayms(500); 灯一直亮灭,原因是视觉延迟// 当500 换成5,看起来全亮,实际上#include<reg52.h> 看上去全亮。

void delayms(uint xms) // 子程序,延时,通过数数uint i, j; for(i=xms;i>0;i--) for(j=110;j>0;j--);#include<reg52.h> // 跑马灯程序。

现在时间较长,多以是亮灭的流动,当时间约为20ms形成动态扫描,看上去全亮。

#include<intrins.h>#define uint unsigned int #define uchar unsigned char void delayms(uint);uchar aa;void main(){aa=0xfe;while(1){P2=aa; delayms(500); 灯一直亮灭,原因是视觉延迟// 无符号整型,占16 位数,表示围0~65536 // 无符号字符型占八位数,表示围0~255// 定义变量// 控制单片机接口p2, 循环亮// 当500 换成5,看起来全亮,实际上aa=_crol_(aa, 1); }}void delayms(uint xms) // 子程序,延时,通过数数 {uint i, j; for(i=xms;i>0;i--) for(j=110;j>0;j--);}#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和两个共阴极数码 管:使用单片机的引脚 1和 2,控制两个数码管静态显示 00到59) #define uchar unsigned char #define uint unsigned int sbit dula1=P1A7;uchar num,num1; // 共阴极数码管 0123456789abcdef0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; void delayms(uint) ; void main (){while(1){for(num1=0;num1<=5;num1++)// 申明 U1 锁存器锁存端 段选 sbit dula2=P0A7;// 申明 U1 锁存器锁存端段选uchar code table[]={{for(num=0;num<=9;num++){dula2=1; // 打开U1 锁存端P1=table[num]; // 送入位选信号器dula2=0; // 关闭U1 锁存500 毫秒约0.3sdelayms(100); // 延时dula1=1; // 打开U1 锁存端P2=table[num1]; // 送入位选信号器dula1=0;// 关闭U1 锁存500 毫秒约0.3s}delayms(100); // 延时}}}void delayms (uint xms){uint x, y ;dula1=0;// 关闭 U1 锁存器for (y=200;y>0;y--);}#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和两个共阴极数码 管)#define uchar unsigned char #define uint unsigned int sbit dula1=P1A7; sbit dula2=P2A7; uchar num,num1; uchar code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; void delayms(uint) ; void main (){while(1){for(num1=0;num1<=9;num1++){dula1=1; //打开U1锁存端P1=table[num1]; // 送入位选信号for (x=xms;x>0;x--) //x=xms 即延时约为 xms 毫秒// 申明 U1 锁存器锁存端 段选 // 申明 U1 锁存器锁存端段选// 共阴极数码管 0123456789abcdefdelayms(1000);// 延时 500 毫秒约0xc0,0xf9,0xa4, 0xb0,// 共阳极数字: 0123456789abcdefg0.3s for(num=0;num<=9;num++)dula2=1; // 打开 U1 锁存端P1=table[num]; // 送入位选信号 dula2=0;// 关闭 U1 锁存器 500 毫秒约 0.3s }} } void delayms (uint xms) { uint x, y ; for (x=xms;x>0;x--) delayms(1000);// 延时//x=xms 即延时约为 xms 毫秒for (y=200;y>0;y--); 有语法错误 #include <reg52.h> //52 系列单片机头文件 #define uchar unsigned char // 无符号字符型占八位数,表示围 0~255 #define uint unsigned int //无符号整型 占 16 位数,表示围 sbit dula1=P1A 6; //申明U1锁存器锁存端 段选 sbit dula2=P0A7; //申明U1锁存器锁存端段选uchar code table[]={0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e};void delayms(uint) ;void display(uchar,uchar) ;uchar num,num2,shi,ge;void main (){TMOD=Ox11;〃设置定时器0和1为工作方式1 (M1M0为01, 0001 00THO= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL0= (65535-50000)%256;TH1= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL1= (65535-50000)%256;EA=1;// 开总中断ET0=1; // 开定时器0 中断ET1=1; // 开定时器 1 中断TR0=1;// 启动定时器0TR1=1;// 启动定时器 1while(1)// 程序停止在这里不停的对数码管动态扫描同时等待中断的发生display(shi,ge);dula2=1; // 打开U1 锁存端P1=table[shi]; // 送入位选信号dula2=0; // 关闭U1 锁存器delayms(1175); // 延时0.1 毫秒void delayms(uint xms) // 延时子程序{uint i,j;for (i=xms;i>0;i--)//i=xms 即延时约为xms 毫秒for (j=110;j>0;j--); }void T1_time()interrupt 1{TH1= (65536-50000)/256; // 重装初值TL1= (65536-50000)%256;num2++; //num 每加 1 次判断一次是否到20 次if(num2==20){num2=0; // 然后把num2 清0 重新再计数20 次num++;if (num==60) // 这个数用来送数码管显示,到60 后归0num=0;shi=num/10; // 把一个 2 位数分离后分别送数码管显示,十位数ge=num%10; // 个位数#include <reg52.h> //52 系列单片机头文件 (目标:控制时间24 小时一循环) #define uchar unsigned char#define uint unsigned intsbit dula1=P1A7; //申明U1锁存器锁存端段选sbit dula2=P0A7; //申明U1锁存器锁存端段选uchar num,num1,num2,num3,num4;uchar code table[]={0xc0,0xf9,0xa4, 0xb0, // 共阳极数字:0123456789abcdefg0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e};void delayms(uint) ;void main (){while(1){for(num3=0;num3<=23;num3++) // 每天24 小时进位一{for(num2=0;num2<=59;num2++)// 每60 分进位一{for(num1=0;num1<=5;num1++) //每6*10s 进位一{dula2=1; // 打开U1 锁存端P1=table[num1]; // 送入位选信号dula2=0; // 关闭U1 锁存0.1 毫秒// 每1s 进位一打开U1锁存端// 送入位选信号// 关闭U1 锁存器// 延时0.1 毫秒}}}}}void delayms (uint xms){uint x, y ;for (x=xms;x>0;x--)for (y=110;y>0;y--); }delayms(1175); //for(num=0;num<=9;num++){dula2=1;P1=table[num];dula2=0;delayms(1000);}//x=xms 即延时约为xms 毫秒延时//#include <reg52.h> //52 系列单片机头文件 (目标:控制时间 24 小时一循环,蜂鸣器每过一段时间响一次)#define uchar unsigned char #define uint unsigned int sbit dula1=P1A7; sbit dula2=P2A7; sbit f=P0;// 声明单片机 P0 口的第一位 ,也就是三极管基级的位置单片机第 39 接口uchar num,num1,num2,num3,num4; uchar code table[]={ 0xc0,0xf9,0xa4, 0xb0,// 共阳极数字: 0123456789abcdefg0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,// 申明 U1 锁存器锁存端// 申明 U1 锁存器锁存段选 段选0xcd,0xa1,0x86,0x8e}; void delayms(uint) ; void main (){while(1)f=0; // 控制蜂鸣器的不响 每 1ms 进位一for(num=0;num<=9;num++)//{锁存端dula2=1;// 打开 U1选信号P2=table[num];// 送入位U1锁存器dula2=0;// 关闭// 延时 0.1 毫秒delayms(1074);}// 控制蜂鸣器的响delayms(1000); }}}{进位一for(num2=0;num2<=59;num2++){for(num4=0;num2<=59;num4++)// 每 60 分// 每 60s 进位一{for(num3=0;num3<=23;num3++) // 每天进位一f=1;void delayms (uint xms){uint x, y ;for (x=xms;x>0;x--) //x=xms 即延时约为xms 毫秒for (y=10;y>0;y--);}#include <reg52.h> //52 系列单片机头文件(目标:用单片机和两个共阳极数码管,控制依次显示0到59,然后循环,有合适的时间间隔,程序停止)#define uchar unsigned char#define uint unsigned intsbit dula1=P1A7; // 申明U1 锁存器锁存端段选sbit dula2=P2A7; // 申明U1 锁存器锁存端段选uchar num,num1;uchar code table[]={0xc0,0xf9,0xa4, 0xb0,// 共阳极数字:0123456789abcdefg0x99,0x92,0x82,0xf8,}void delayms (uint xms)uint x, y ;0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e}; void delayms(uint) ; void main (){while(1)for(num1=0;num1<6;num1++){dula1=1; P1=table[num1]; dula1=0;delayms(100);// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存器// 延时 500 毫秒约0.3s器500 毫秒约 0.3s for(num=0;num<=9;num++){dula2=1; P2=table[num]; dula2=0;delayms(100);// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存// 延时dula1=0; // 关闭 U1 锁存器uchar num,num1; uchar code table[]={0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e};void delayms(uint) ; void main ()while(1){for(num=0;num1<6;num1++){dula1=1;//打开U1锁存端P1=table[num1]; // 送入位选信号for (x=xms;x>0;x--)//x=xms 即延时约为 xms 毫秒for (y=200;y>0;y--);}#include <reg52.h> //52 管,控制依次显示 0到 59, 系列单片机头文件 (目标:用单片机和两个共阳极数码 时间间隔约 0.5, 程序停止) #define uchar unsigned char #define uint unsigned int sbit dula1=P1A7; // 申明 U1 锁存器锁存端 段选 sbit dula2=P2A7;// 申明 U1 锁存器锁存端段选0xc0,0xf9,0xa4, 0xb0, // 共阳极数字: 0123456789abcdefgdelayms(100); // 延时500 毫秒约0.3sfor(num=0;num<=9;num++){dula2=1; // 打开U1 锁存端P2=table[num]; // 送入位选信号器dula2=0; // 关闭U1 锁存500 毫秒约0.3sdelayms(100);// 延时}}}}void delayms (uint xms)//延时子程序{uint x, y ;for (x=xms;x>0;x--) //x=xms 即延时约为xms毫秒for (y=300;y>0;y--);0.3sfor(num=0;num<=9;num++){dula2=1; //打开U2锁存端 P2=table[num];// 送入位选信号#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和两个共阳极数码 管,控制依次显示 0到 59,时间间隔约 0.5, 程序停止) #define uchar unsigned char #define uint unsigned intsbit dula1=P1A7; sbit dula2=P2A7; // 申明 U1 锁存器锁存端段选 段选uchar num,num1; uchar code table[]={ 0xc0,0xf9,0xa4, 0xb0, // 共阳极数字: 0123456789abcdefg0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e}; voiddelayms(uint) ; void main ()while(1){for(num=0;num1<6;num1++) {dula1=1; P1=table[num1]; dula1=0; delayms(100);// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存器// 延时 500 毫秒约#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和共阳极数码管, 控制依次显示 0到 9,时间间隔约 0.5s ;)#define uchar unsigned char #define uint unsigned int500 毫秒约 0.3sdelayms(100);// 延时}}}}void delayms (uint xms){uint x, y ;for (x=xms;x>0;x--)〃x=xms 即延时约为xms 毫秒for (y=300;y>0;y--);器// 关闭 U1 锁存}dula2=0;sbit dula1=P1A7;// 申明 U1 锁存器锁存端 段选// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存器// 延时 500 毫秒约 0.3//打开U2锁存端 // 送入位选信号//关闭U2锁存器// 延时 500 毫秒约 0.3sbit dula2=P2A7; // 申明 U2 锁存器锁存端 段选uchar num; uchar codetable[]={ 0xc0,0xf9,0x a4, 0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e}; void delayms(uint) ; void main (){while(1)// 共阳极数字: 0123456789abcdefgfor(num=0;num<10;num++){dula1=1; P1=table[num]; dula1=0; delayms(100);dula2=1; P2=table[num]; dula2=0; delayms(100);void delayms (uint xms) {uint x, y ;for (x=xms;x>0;x--)//x=xms 即延时约为xms 毫秒for (y=300;y>0;y--);}#include <reg52.h> //52 系列单片机头文件(目标:用定时器0 的方式 1 实现第一个灯管以200ms闪烁;用定时器1的方式1实现数码管前两位59s循环计时)#define uchar unsigned char // 无符号字符型占八位数,表示围0~255#define uint unsigned int // 无符号整型,占16 位数,表示围sbit dula=P2A6; //申明U1锁存器锁存端段选sbit wela=P2A7; //申明U2锁存器锁存位选sbit led1=P1A0; // 申明灯 1 点0uchar code table[]={ // 共阴极数码管0123456789abcdef0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; void delayms(uint) ; voiddisplay(uchar,uchar) ; uchar num,num1,num2,shi,ge; void main (){TMOD=0x01;〃设置定时器0和1为工作方式1 (M1M0为01, 0001 00THO= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL0= (65535-50000)%256; TH1= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL1= (65535-50000)%256; EA=1;// 开总中断ET0=1; // 开定时器0 中断ET1=1; // 开定时器 1 中断TR0=1;// 启动定时器 0TR1=1;// 启动定时器 1while(1)//程序停止在这里不停的对数码管动态扫描同时等待中断的发生 {display(shi,ge);}}void display (uchar shi,uchar ge) // 控制数码管{ dula=1;// 打开 U1 锁存端 段选 P0=table[shi];//送入段选信号 dula=0;// 关闭 U1 锁存器 P0=0xff;// 送位选数据前关闭所有显示,防止打开位选锁存器时 wela=1;// 原来的段选数据通过位选锁存器造成混乱 P0=0xfe;// 送位选数据 wela=0;delayms(5); // 延时dula=1; // 打开 U1 锁存端 段选P0=table[ge]; // 送入段选信号dula=0;// 关闭 U1 锁存器 P0=0xff;// 送位选数据前关闭所有显示,防止打开位选锁存器时 wela=1; // 原来的段选数据通过位选锁存器造成混乱P0=0xfe; // 送位选数据wela=0;delayms(5); // 延时} void delayms(uint xms) // 延时子程序{uint i,j;for (i=xms;i>0;i--) //i=xms 即延时约为 xms 毫秒for (j=110;j>0;j--);} void T0_time()interrupt 1{TH0= (65536-50000)/256; TL0= (65536-50000)%256;num++;//num1 每加 1次判断一次是否到 4次 ,时间间隔200ms // 重装初值if(num1==4)num1=0; // 然后把num1 清0 重新再计数 4 次led1=~led1; // 让发光管状态取反}} void T1_time()interrupt 3{TH1= (65536-50000)/256; // 重装初值TL1= (65536-50000)%256;num2++; //num 每加 1 次判断一次是否到20 次if(num2==20){num2=0; // 然后把num2 清0 重新再计数20 次num++;if (num==60) // 这个数用来送数码管显示,到60 后归0num=0;shi=num/10; // 把一个 2 位数分离后分别送数码管显示,十位数ge=num%10; // 个位数// 共阴极数码管 0123456789abcdef0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delayms(uint) ;void display(uchar,uchar) ;uchar num,num1,num2,shi,ge;void main (){TMOD=0x01;〃 设置定时器0和1为工作方式1 ( M1M (为01, 0001 0001 )TH0= (65535-50000)/256;// 装初值 12.00M 晶振定时 50s 数为 50000TL0= (65535-50000)%256;TH1= (65535-50000)/256;// 装初值 12.00M 晶振定时 50s 数为 50000 TL1=(65535-50000)%256;EA=1;// 开总中断ET0=1; // 开定时器 0 中断ET1=1; // 开定时器 1 中断TR0=1;// 启动定时器 0TR1=1;// 启动定时器 1#include <reg52.h> //52 系列单片机头文件 (目标:用定时器 0 的方式 1 实现第 一个灯管以200ms 闪烁;用定时器1的方式1实现数码管前两位59s 循环计时)#define uchar unsigned char 占八位数,表示围 0~255// 无符号字符型 #define uint unsignedint 数,表示围// 无符号整型, 占 16位 sbit dula=P2A 6;//申明U1锁存器锁存端 段选 sbit wela=P2A7;//申明U2锁存器锁存 位选sbit led1=P1A0;// 申明灯 1 点 0 uchar code table[]={while(1)// 程序停止在这里不停的对数码管动态扫描同时等待中断的发生{display(shi,ge);}}void display (uchar shi,uchar ge) // 控制数码管{dula=1; // 打开U1 锁存端段选P0=table[shi];//送入段选信号dula=0; // 关闭U1 锁存器P0=0xff;// 送位选数据前关闭所有显示,防止打开位选锁存器时wela=1; // 原来的段选数据通过位选锁存器造成混乱P0=0xfe; // 送位选数据wela=0;delayms(5); // 延时dula=1; // 打开U1 锁存端段选P0=table[ge];//送入段选信号dula=0; // 关闭U1 锁存器P0=0xff; // 送位选数据前关闭所有显示,防止打开位选锁存器时wela=1; // 原来的段选数据通过位选锁存器造成混乱P0=0xfe; // 送位选数据wela=0;delayms(5); // 延时{void delayms(uint xms) // 延时子程序uint i,j;for (i=xms;i>O;i--) 〃i=xms 即延时约为xms毫秒for (j=110;j>0;j--);}#include <reg52.h> //52 系列单片机头文件 (目标:中断程序,控制 1 点0 二极管10ms闪烁)#define uchar unsigned char#define uint unsigned intsbit led1=P1A0; II声明单片机P1 口的第一位uchar num;void main (){TMOD=0x01;〃设置定时器0为工作方式1 (M1M(为01)TH0= (65535-50000)/256;// 装初值12.00M 晶振定时50ms数为50000TL0= (65535-50000)%256;EA=1;// 开总中断ET0=1; // 开定时器0 中断TR0=1;// 启动定时器0while(1)// 程序停止在这里等待中断的发生{if(num==200)// 判断一次是否到20{num=0; // 然后把num 清0 重新再计数20 次led1=~led1; // 让发光管状态取反}}}void T0_time()interrupt 1{TH0= (65535-50000)/256; // 重装初值TL0= (65535-50000)%256;num++; //num 加上1#include <reg52.h> //52 系列单片机头文件 (目标:中断程序,控制 1 点0 二极管100ms 闪烁,若num=10则0.05s闪烁,换句话控制5000或者num都可以控制时间。

MCS-51单片机程序设计

MCS-51单片机程序设计

+1
,当X>0
Y= 0
,当X=0
开始
-1
,当X<0
X=0
N
程序流程框图如图4.1所示。 Y
Y←0
X>0 Y
Y←1
N Y←-1
结束
程序如下: ORG
MOV CJNE MOV AJMP MP1: JB MOV LJMP MP2: MOV HERE: SJMP
1000H A,R0 A,#00H,MP1 R1,#00H HERE ACC.7 MP2 R1,#01H HERE R1,#0FFH HERE
1000H DPTR,#2000H DPL DPH DPTR,#3000H R2,DPL R3,DPH
;源数据区首地址 ;源首址暂存堆栈
;目的数据区首地址 ;目的首址暂存寄存器
LOOP:
POP POP MOVX INC PUSH PUSH MOV MOV MOVX MOV MOV DJNZ SJMP
;源数据区首地址 ;目的数据区首地址 ;循环次数 ;取数据 ;数据传送 ;源地址加1 ;目的地址加1 ;循环控制 ;结束
例4.8 外部RAM之间的数据传送程序。
把外部RAM 2000H开始单元中的数据传送到外部RAM 3000H开始的单 元中,数据个数在内部RAM的35H单元中。
START:
ORG MOV PUSH PUSH MOV MOV MOV
K=?
K=0
K=1
转向 0 分支 转向 1 分支
K= n-1
K=n
转向 n-1 分支 转向 n 分支
例4.5 设内部RAM的30H单元有一个数,根据该数值的不同 转移到不同的程序段进行处理,设数值的范围为0~10的 无符号数。

51单片机基本程序

51单片机基本程序

51单片机基本程序在学习嵌入式系统开发中,51单片机是一个重要的组成部分。

通过编写基本程序,可以更好地理解51单片机的原理和工作方式。

本文将介绍51单片机基本程序的编写方法及应用。

一、概述51单片机是一种基于哈佛结构的8位单片机,采用英特尔的经典架构。

通过编写基本程序,可以实现各种功能,如LED灯控制、数码管显示以及与外设的通信等。

二、开发工具在编写51单片机基本程序之前,我们需要准备一些开发工具。

最常用的工具是Keil C51开发环境,它是一种集成开发环境(IDE),提供了包括编译器、调试器在内的多种工具。

另外,还需要一个烧录器,用于将程序烧录到单片机中。

三、编写基本程序编写51单片机基本程序的第一步是创建一个新的项目。

在Keil C51中,选择“File”->“New Project”来创建一个新的项目,然后选择单片机型号和存储路径。

接下来,我们需要编写程序代码。

以下是一个简单的LED闪烁程序的示例:```c#include <reg52.h>sbit LED = P1^0;void delay(unsigned int time) {unsigned int i, j;for (i = 0; i < time; i++)for (j = 0; j < 500; j++); }void main(){while (1){LED = 0; // LED灯亮 delay(1000); //延时1秒 LED = 1; // LED灯灭 delay(1000); //延时1秒 }}```在上述代码中,我们首先定义了一个LED的IO口,并使用了一个延时函数来控制LED的亮灭。

在主函数中,我们使用一个无限循环来实现LED的闪烁。

四、程序调试和测试编写完基本程序后,我们需要对程序进行调试和测试。

在Keil C51中,选择“Debug”->“Start/Stop Debug Session”来启动调试会话。

51单片机pid算法程序

51单片机pid算法程序

51单片机pid算法程序51单片机是一种广泛应用于嵌入式系统开发的微控制器。

PID算法是一种常用的控制算法,用于实现系统的闭环控制。

本文将介绍如何在51单片机上实现PID算法。

PID算法是一种经典的控制算法,它能够根据系统的反馈信息,自动调整控制量,使系统的输出接近期望值。

PID算法由比例项(P 项)、积分项(I项)和微分项(D项)组成。

比例项用来根据当前误差大小调整控制量,积分项用来根据过去误差的累积值调整控制量,微分项用来根据误差的变化速度调整控制量。

在51单片机上实现PID算法,首先需要编写程序来读取系统的反馈信息和期望值。

例如,可以通过ADC模块读取传感器的信号,然后通过计算得到当前误差。

接下来,根据比例项、积分项和微分项的系数,计算PID控制量。

最后,将PID控制量输出到执行机构,例如电机或舵机,来控制系统的输出。

在编写PID算法程序时,需要注意一些细节。

首先,要根据实际系统的特点和要求来选择合适的PID参数。

比例项的系数决定了控制量对误差的敏感程度,积分项的系数决定了控制量对误差累积值的敏感程度,微分项的系数决定了控制量对误差变化速度的敏感程度。

其次,要注意处理PID算法中的积分项和微分项的累积误差。

积分项的累积误差可能会导致系统出现超调或震荡,需要适当地进行限制或清零。

微分项的累积误差可能会导致系统出现噪声放大或不稳定,需要进行滤波或限制。

最后,要注意程序的效率和实时性。

PID算法通常需要以一定的频率进行计算和更新,要保证程序能够及时响应系统的变化。

除了基本的PID算法,还可以根据具体的应用需求进行算法的优化和改进。

例如,可以引入自适应调整PID参数的方法,使系统能够根据实时的工作条件自动调整PID参数。

还可以引入前馈控制或模糊控制等方法,进一步提高系统的控制性能和鲁棒性。

51单片机是一种常用的嵌入式系统开发平台,可以很方便地实现PID算法。

通过合理选择PID参数和优化算法,可以实现对系统的精确控制。

51单片机超详细教程PPT(绝对值)

51单片机超详细教程PPT(绝对值)
必须使必须使rstrst引脚持续引脚持续22微秒微秒高电平高电平外部时钟外部时钟12mhz12mhz10111213142827262524232221201918171615101112131428272625242322212019181716151011121314151617181920403938373635343332313029282726252424222110111213142827262524232221201918171615ram626410111213142827262524232221201918171615ram626480318751805189c51ramramromrom256b字节4k1程序存储器程序存储器程序存储器内部外部0000h0fffh4k0000hffffh64k0000h0fffh4k0000h0001h0002hpc0000h是程序执行的起始单元在这三个单元存放一条无条件转移指令中断5中断4中断3中断2中断10003h000bh0013h001bh0023h002bh外部中断0定时器0中断外部中断1定时器1中断串行口中断0fffh0ffehea1ea0程序存储器资源分布中断入口地址在单片机c语言程序设计中用户无需考虑程序的存放地址编译程序会在编译过程中按照上述规定自动安排程序的存放地址
00
3区
外部
FFH 80H 7FH (低128B) 00H (高128B) 专用 寄存器 内部 RAM 0000H
1FH 18H 17H 10H 0FH 08H 07H 00H
2区
工作寄存器区
1区 0区
数据存储器
内部RAM存储器
RAM位寻址区位地址表
单元地址 MSB
2FH 2EH 2DH 2CH 2BH 2AH 29H 28H 27H 26H 25H 24H 23H 22H 21H 20H 7F 77 6F 67 5F 57 4F 47 3F 37 2F 27 1F 17 0F 07 7E 76 6E 66 5E 56 4E 46 3E 36 2E 26 1E 16 0E 06 7D 75 6D 65 5D 55 4D 45 3D 35 2D 25 1D 15 0D 05

51单片机中断程序大全

51单片机中断程序大全

//实例42:用定时器T0查询方式P2口8位控制LED闪烁#include<reg51.h> // 包含51单片机寄存器定义的头文件void main(void){// EA=1; //开总中断// ET0=1; //定时器T0中断允许TMOD=0x01; //使用定时器T0的模式1TH0=(65536-46083)/256; //定时器T0的高8位赋初值TL0=(65536-46083)%256; //定时器T0的高8位赋初值{//实例43{// EA=1;//{while(TF1==0);TF1=0;sound=~sound; //将P3.7引脚输出电平取反TH1=(65536-921)/256; //定时器T0的高8位赋初值TL1=(65536-921)%256; //定时器T0的高8位赋初值}}//实例44:将计数器T0计数的结果送P1口8位LED显示#include<reg51.h> // 包含51单片机寄存器定义的头文件sbit S=P3^4; //将S位定义为P3.4引脚void main(void){// EA=1; //开总中断// ET0=1; //定时器T0中断允许TMOD=0x02; //使用定时器T0的模式2TH0=256-156; //定时器T0的高8位赋初值TL0=256-156; //定时器T0的高8位赋初值TR0=1; //启动定时器T0while(1)//无限循环等待查询{while(TF0==0) //如果未计满就等待{if(S==0) //按键S按下接地,电平为0P1=TL0; //计数器TL0加1后送P1口显示}//实例45{EA=1;{}//实例46#include<reg51.h> // 包含51单片机寄存器定义的头文件sbit D1=P2^0; //将D1位定义为P2.0引脚unsigned char Countor; //设置全局变量,储存定时器T0中断次数void main(void){EA=1; //开总中断ET0=1; //定时器T0中断允许TMOD=0x01; //使用定时器T0的模式2TH0=(65536-46083)/256; //定时器T0的高8位赋初值TL0=(65536-46083)%256; //定时器T0的高8位赋初值TR0=1; //启动定时器T0Countor=0; //从0开始累计中断次数while(1);}/************************************************************** 函数功能:定时器T0的中断服务程序**************************************************************/ void Time0(void) interrupt 1 using 0{Countor++; //中断次数自加1if(Countor==20) //若累计满20次,即计时满1s{D1=~D1; //按位取反操作,将P2.0引脚输出电平取反Countor=0; //将Countor清0,重新从0开始计数}//实例47{EA=1;}{Countor2++; //Countor2自加1if(Countor1==2) //若累计满2次,即计时满100ms{D1=~D1; //按位取反操作,将P2.0引脚输出电平取反Countor1=0; //将Countor1清0,重新从0开始计数}if(Countor2==8) //若累计满8次,即计时满400ms{D2=~D2; //按位取反操作,将P2.1引脚输出电平取反Countor2=0; //将Countor1清0,重新从0开始计数}TH1=(65536-46083)/256; //定时器T1的高8位重新赋初值TL1=(65536-46083)%256; //定时器T1的高8位重新赋初值}//实例50-1:输出50个矩形脉冲#include<reg51.h> //包含51单片机寄存器定义的头文件sbit u=P1^4; //将u位定义为P1.4/*************************************************函数功能:延时约30ms (3*100*100=30 000μs =30m*************************************************/void delay30ms(void){ unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<100;n++);}{u=1;//实例{//实例51-2#include<reg51.h> //包含51单片机寄存器定义的头文件sbit ui=P3^2; //将ui位定义为P3.0(INT0)引脚,表示输入电压void main(void){TMOD=0x0a; // TMOD=0000 1010B,使用定时器T0的模式2,GATE置1 EA=1; //开总中断ET0=0; //不使用定时器T0的中断TR0=1; //启动T0TH0=0; //计数器T0高8位赋初值TL0=0; //计数器T0低8位赋初值while(1) //无限循环,不停地将TL0计数结果送P1口{while(ui==0) : //INT0为低电平,T0不能启动TL0=0; //INT0为高电平,启动T0计时,所以将TL0清0 while(ui==1): //在INT0高电平期间,等待,计时P1=TL0; //将计时结果送P1口显示} }//实例53:用外中断0的中断方式进行数据采集#include<reg51.h> //包含51单片机寄存器定义的头文件sbit S=P3^2; //将S位定义为P3.2,void main(void){EA=1; //开放总中断EX0=1; //允许使用外中断IT0=1; //选择负跳变来触发外中断P1=0xff;{P1=~P1;//实例54-1sbit u=P1^4;{EA=1;{u=~u; //}//实例54-2sbit u=P3^2;{TMOD=0x02; //TMOD=0000 0010B,使用定时器T0的模式2EA=1; //开放总中断EX0=1; //允许使用外中断IT0=1; //选择负跳变来触发外中断ET0=1; //允许定时器T0中断TH0=0; //定时器T0赋初值0TL0=0; //定时器T0赋初值0TR0=0; //先关闭T0while(1) ; //无限循环,不停检测输入负脉冲宽度}void int0(void) interrupt 0 using 0 //外中断0的中断编号为0{ TR0=1; //外中断一到来,即启动T0计时TL0=0; //从0开始计时while(u==0) //低电平时,等待T0计时;P1=TL0; //将结果送P1口显示TR0=0; //关闭T0}//实例55:方式0控制流水灯循环点亮#include<reg51.h> //包含51单片机寄存器定义的头文件#include<intrins.h> //包含函数_nop_()定义的头文件unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码,该数组被定义为全局变量sbit P17=P1^7;/**************************************************************{{P17=0;_nop_();_nop_();P17=1;;TI=0; //}******************************************/void main(void){unsigned char i;SCON=0x00; //SCON=0000 0000B,使串行口工作于方式0while(1){for(i=0;i<8;i++){Send(Tab[i]); //发送数据delay(); //延时}}}。

51单片机经典流水灯程序

51单片机经典流水灯程序

单片机流水灯汇编程序设计开发板上的8只LED为共阳极连接,即单片机输出端为低电平时即可点亮LED。

程序A:;用最直接的方式实现流水灯ORG 0000HSTART:MOV P1,#01111111B ;最下面的LED点亮LCALL DELAY;延时1秒MOV P1,#10111111B ;最下面第二个的LED点亮LCALL DELAY;延时1秒MOV P1,#11011111B ;最下面第三个的LED点亮(以下省略)LCALL DELAYMOV P1,#11101111BLCALL DELAYMOV P1,#11110111BLCALL DELAYMOV P1,#11111011BLCALL DELAYMOV P1,#11111101BLCALL DELAYMOV P1,#11111110BLCALL DELAYMOV P1,#11111111B ;完成第一次循环点亮,延时约0.25秒AJMP START ;反复循环;延时子程序,12M晶振延时约250毫秒DELAY:MOV R4,#2L3: MOV R2 ,#250L1: MOV R3 ,#250L2: DJNZ R3 ,L2DJNZ R2 ,L1DJNZ R4 ,L3RETEND程序B:;用移位方式实现流水灯org 00h ;程序上电从00h开始ajmp main ;跳转到主程序org 0030h ;主程序起始地址main:mov a,#0feh ;给A赋值成11111110loop: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.8Sdjnz r4,d2djnz r3,d1retend51单片机经典流水灯程序,在51单片机的P2口接上8个发光二极管,产生流水灯的移动效果。

51单片机应用程序实例

51单片机应用程序实例
图 9.1 3.系统板上硬件连线 (1. 把“单片机系统”区域中的 P3.7/RD 端口连接到“独立式键盘”区域中的 SP1 端口上; (2. 把“单片机系统”区域中的 P1.0-P1.4 端口用 8 芯排线连接到“八路发光二 极管指示模块”区域中的“L1-L8”端口上;要求,P1.0 连接到 L1,P1.1 连接到 L2,
广告灯的左移右移
1. 实验任务
做单一灯的左移右移,硬件电路如图 4.1 所示,八个发光二极管 L1-L8 分别接在单 片机的 P1.0-P1.7 接口上,输出“0”时,发光二极管亮,开始时 P1.0→P1.1→P1.2→P1.3→┅→P1.7→P1.6→┅→P1.0 亮,重复循环。
2. 电路原理图
图 4.1
每次送出的数据是不同,具体的数据如下表 1 所示
P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 L8 L7 L6 L5 L4 L3 L2 1111111 1111110 1111101 1111011
P1.0 L1 0 1 1 1
说明
L1 亮 L2 亮 L3 亮 L4 亮
1110111 1 1101111 1 1011111 1 0111111 1
一键多功能按键识别技术
1.实验任务 如图 9.1 所示,开关 SP1 接在 P3.7/RD 管脚上,在 AT89S51 单片机的 P1 端口接有四 个发光二极管,上电的时候,L1 接在 P1.0 管脚上的发光二极管在闪烁,当每一次按 下开关 SP1 的时候,L2 接在 P1.1 管脚上的发光二极管在闪烁,再按下开关 SP1 的时 候,L3 接在 P1.2 管脚上的发光二极管在闪烁,再按下开关 SP1 的时候,L4 接在 P1.3 管脚上的发光二极管在闪烁,再按下开关 SP1 的时候,又轮到 L1 在闪烁了,如此轮 流下去。 2.电路原理图
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1第一位隔一秒闪烁一次
#include<>
#define uint unsigned int
sbit led1=P1^0;
uint i;
uint j;
void main()
{
while(1)
{
%
led1=0;
for(i=1000;i>0;i--)
for(j=110;j>0;j--);
led1=1;
for(i=1000;i>0;i--)
for(j=110;j>0;j--);
}
}

2复杂广告灯
#include<>
#define uint unsigned int
#define uchar unsigned char
uchar discode[]={ 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,sbit k2=P3^5; sbit k3=P3^6;
sbit k4=P3^7;
sbit d=P1^2;
sbit c=P1^3;

uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
void delayms(uint);
uchar numt0,num;
void display(uchar numdis) //显示59s的常用方式
!
{ uchar shi,ge;
shi=numdis/10;
ge=numdis%10;
P1=0xff; //控制十位数字
P1=0xfd;
P0=table[shi];
delayms(10);
P1=0x00;。

P1=0xff; //控制个位数字
P1=0xfe;
P0=table[ge];
delayms(10);
P1=0x00;
}
void delayms(uint xms) //简单的延时程序/
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void init() //初始化函数
{
TMOD=0x01;
TH0=(65536-45872)/256;

TL0=(65536-45872)%256;
EA=1;
ET0=1;
}
void keyscan() //控制键盘的程序{
if(k1==0)
{
delayms(10); //去抖动延时
\
if(k1==0)
{
num++;
if(num==60)
num=0;
while(!k1); //等待按键释放}
}
\
if(k2==0)
{
delayms(10);
if(k2==0)
{
if(num==0)
num=60;
num--;
while(!k2);
]
}
}
if(k3==0)
{
delayms(10);
if(k3==0)
{
num=0;
~
while(!k3);
}
}
if(k4==0)
{
delayms(10);
if(k4==0)
{

while(!k4);
TR0=~TR0;
}
}
}
void main() //主函数
{
init(); //1,先初始化数据init()

while(1)
{
keyscan(); //键盘选择
display(num); //显示两位数字函数
}
}
void T0_time()interrupt 1 //中断服务程序{
TH0=(65536-45872)/256;

TL0=(65536-45872)%256;
numt0++;
if(numt0==20) //1s的判断
{
numt0=0;
num++;
if(num==60)
num=0;
}
}
-
矩阵键盘使用
#include<>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
>
0xc6,0xa1,0x86,0x8e};
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void display(uchar num)
{
P0=table[num];
·
P1=0xf0;
}
void jianpan()
{
uchar temp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!=0xfe) //11111高位没有零,(没有键按下){

delayms(10);
temp=P3; //随时可能有键按下
temp=temp&0xf0;
if(temp!=0xfe)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
|
break;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
case 0x7e:
key=3;
break;

while(temp!=0xf0) //等待键盘释放
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}。

P3=0xfd;
temp=P3;
temp=temp&0xf0;
if(temp!=0xfe) //222222高位没有零,(没有键按下){
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xfe)
{
,
temp=P3;
switch(temp)
{
case 0xed:
key=4;
break;
case 0xdd:
key=5;
break;
case 0xbd:
)
key=6;
break;
case 0x7d:
key=7;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;

display(key);
}
}
P3=0xfb;
temp=P3;
temp=temp&0xf0;
if(temp!=0xfe) //333333高位没有零,(没有键按下){
`
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xfe)
{
temp=P3;
switch(temp)
{
case 0xeb:
key=8;
`
break;
case 0xdb:
key=9;
break;
case 0xbb:
key=10;
break;
case 0x7b:
key=11;
break;
*
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
*
P3=0xf7;
temp=P3;
temp=temp&0xf0;
if(temp!=0xfe) //44444高位没有零,(没有键按下){
delayms(10);
temp=P3;
temp=temp&0xf0;

if(temp!=0xfe)
{
temp=P3;
switch(temp)
{
case 0xe7:
key=12;
break;
case 0xd7:
key=13;
%
break;
case 0xb7:
key=14;
break;
case 0x77:
key=15;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
}
void main(void)
{
P1=0x0f; //打开数码管选通开关
while(1)
{
jianpan(); //扫描键盘程序
}
}。

相关文档
最新文档