51单片机原理及应用——张毅刚版本代码全集可复制

从左到右的流水灯的制作(重点)

在这里插入图片描述

#include <reg51.h>
#include <intrins.h> //移位函数的头文件
unsigned int j;
void Delay(unsigned int i) // 延时函数
{while(i--) // 注意这里是i--{for(j = 0;j < 120;j++); // 注意这里是120}
}void main()
{P1 = 0xFE;while(1){P1 = _crol_(0,1); //数据每次左移一位// crol函数是循环左移函数,即把挪出去的那一位补在后面空的一位//<<是左移函数,会在空的那一位补0Delay(100);}
}

左到右的来回流水灯的制作

在这里插入图片描述

#include <reg51.h>
#include <>
void Delay(unsigned int i)
{while(i--){for(j=0;j<120;j++);}
}unsigned int x;
unsigned int y;void main()
{P1 = 0xFE;while(1){for(x=0;x<8;x++){P1 =  _crol_(0,1);Delay(100);}for(y=0;y<8;y++){P1 = _cror_(0,1);Delay(100);}}
}

开关量检测指示器

在这里插入图片描述

#include <reg51.h>
void Delay(unsigned int i)
{while(i--){for(int j=0;j<120;j++);}
}
void main()
{while(1){if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);P1_0 = 0;}if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);P1_1 = 0;}if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);P1_2 = 0;}if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);P1_3 = 0;}}
}

单一外中断的应用

在这里插入图片描述

#include <reg51.h>
void Delay(unsigned int i)
{while(i--){for(j=0;j<120;j++);}
}void EX0_Init()
{EA = 1;EX0 = 1;IT0 = 1; // 负跳沿触发IT = 1   低电平触发IT = 0
}void do_EX0() interrupt 0
{EX0 = 0;while(1){P1 = 0xF0;Delay(100);P1 = 0x0F;Delay(100);}EX0 = 1;
}void main()
{P1 = 0x00;EX0_Init();while(1);
}

两个外中断的应用

在这里插入图片描述

#include <reg51.h>
void Delay(unsigned int i)
{while(i--){for(j=0;j<120;j++);}
}void EX_Init()
{EA = 1;EX0 = 1;EX1 = 1;IT0 = 1;IT1 = 1;IP1 = 1;IP0 = 1; // 两个中断都设置为高优先级
}void do_EX0() interrupt 0
{while(1){P1 = 0xF0;Delay(100);P1 = 0x0F;Delay(100);}
}void do_EX1() interrupt 2
{P1 = 0x00;
}void main()
{EX_Init();while(1){//流水灯代码}
}

ps:这个代码因为设置了同级中断,所以在进入任何一个中断后,另一个中断不会被响应

中断嵌套(重点)

在这里插入图片描述

#include <reg51.h>
void Delay(unsigned int i)
{while(i--){for(j=0;j<120;j++);}
}void EX_Init()
{EA = 1;EX0 = 1;EX1 = 1;IT0 = 1;IT1 = 1; // 设置触发方式IP0 = 0;IP1 = 1; //设置优先级
}void do_EX0() interrupt 0
{while(1){P1 = 0xF0;Delay(100);P1 = 0x0F;Delay(100);}
}void do_EX1() interrupt 2
{P1 = 0x00;Delay(100);P1 = 0xFF;Delay(100);
}void main()
{EX_Init();while(1){//流水灯代码}
}

多外部中断源系统设计(非重点)

在这里插入图片描述
在这里插入图片描述

#include <reg51.h>
void EX_Init()
{EA = 1;EX0 = 1;EX1 = 1;IT0 = 1;IT1 = 1;IP0 = 1; // 将外部中断0设置为最高优先级IP1 = 0;
}void do_EX0() interrupt 0
{P1 = 0xFF; // 进入外部中断0,熄灭所有灯
}void do_EX1() interrupt 2
{if(P1_0 == 0){P1_4 = 0;}if(P1_1 == 0){P1_5 = 0;}if(P1_2 == 0){P1_6 = 0;}if(P1_3 == 0){P1_7 = 0;}
}void main()
{EX_Init();while(1);
}

P1口外接的8只LED每0.5s闪亮一次

在这里插入图片描述

#include <reg51.h>
//计算初值
//公式:定时时间 = (2^16-初值X)*(12/fos) 其中(2^16-初值X)即为TH0和TL0的值
//定时时间为0.5s 也就是5000us 即初值X≈60927
void Timer0_Init()
{TMOD = 0x01;TH1 = 60927/256;TL1 = 60927%256;EA = 1;ET0 = 1;TR0 = 1;
}void do_Timer0() interrupt 1
{P1 = ~P1;TH1 = 60927/256;TL1 = 60927%256;
}void main()
{Timer0_Init();while(1);
}

计数器的应用(重点)

在这里插入图片描述

#include <reg51.h>
void Delay(unsigned int i)
{while(i--){if(j=0;j<120;j++);}
}void Timer1_Init()
{TMOD = 0x50; //0101 0000TH1 = 0xFF;TL1 = 0xFC;EA = 1;ET1 = 1;TR1 = 1;
}void do_Timer1() interrupt 3
{while(1){P1 = 0xFF;Delay(100);P1 = 0x00;Delay(100);}
}void main()
{Timer1_Init();while(1);
}

扩展一个外部中断源(非重点)

在这里插入图片描述

#include <reg51.h>
void Timer0_Init()
{TMOD = 0x06;TH0 = 0xFF;TL0 = 0xFF;ET0 = 1;TR0 = 1;TF0 = 0; //溢出标志位清零
}void main()
{Timer0_Init();while(1);
}

在P1.0上产生周期为2ms的方波

在这里插入图片描述

#include <reg51.h>
//计算初值
//产生周期为2ms的方波,即要要让P1.0口每1ms翻转一次,所以定时器1需要定时1ms
//定时时间 = (2^16-X)*(12/fos)
//此时的定时时间为1ms,即1000us
// X = 65536-1000
void Timer1_Init()
{TMOD = 0x10;//0001 0000TH1 = (65536-1000)/256;TL1 = (65536-1000)%256;EA = 1;ET1 = 1;TR1 = 1;
}void do_Timer1() interrupt 3
{P1_0 = !P1_0;TH1 = (65536-1000)/256;TL1 = (65536-1000)%256; //重置初值
}void main()
{Timer1_Init();P1_0 = 0;while(1);
}

在P1.1上产生周期为1s的方波

在这里插入图片描述

多次中断法(推荐)

#include <reg51.h>
//这个题目的定时时间应该是1s/2 = 0.5s  0.5s = 500ms
//定时时间比较长,我们此时采用多次中断的方式来定时
//还是采用定时1的方式1来定时,可以让定时器1一次产生50ms的定时 一共定时10次
//50ms = 50000us
//X = 65536-50000
void Timer1_Init()
{TMOD = 0x10;TH1 = (65536-50000)/256;TL1 = (65536-50000)%256;EA = 1;ET1 = 1;TR1 = 1;
}unsigned int count;
void do_Timer1() interrupt 3
{count++;if(count == 10){count = 0;P1_1 = !P1_1;}TH1 = (65536-50000)/256;TL1 = (65536-50000)%256;
}void main()
{Timer1_Init();P1_1 = 0;while(1);
}

双定时器法(不推荐)

在这里插入图片描述

T1控制发出1KHZ的音频信号(重点)

在这里插入图片描述

#include <reg51.h>
//书上写的计算初值是错误的,以下面注释为准
//产生1KHZ的音频信号,也就是产生音频信号的周期为1ms 所以需要定时的时间为0.5ms
//由0.5ms = 500us  500/1.08 = 460
// X = (65536-460)
void Timer1_Init()
{TMOD = 0x10;TH1 = (65536-460)/256;TL1 = (65536-460)%256;EA = 1;ET1 = 1;TR1 = 1;
}void do_Timer1() interrupt 3
{P1_7 = !P1_7;TH1 = (65536-460)/256;TL1 = (65536-460)%256;
}void main()
{P1_7 = 0;Timer1_Init();while(1);
}

测量脉冲宽度——门控位GATEx的应用(非重点)

在这里插入图片描述

#include <reg51.h>
unsigned count_high; // 读取TH0 
unsigned count_low; // 读取TL0
//最后INT1的正脉冲宽度以机器周期数的形式读入到上面俩变量中
//正脉冲是一个周期信号中高电平的信号
void read_count()
{do{count_high = TH1;count_low = TL1;...//可进行显示或其他处理}while(count_high!=TH1)
}void main()
{TMOD = 0x90; // 1001 0000//需要注意的是:当单片机的GATE为1的时候,如果要打开定时器,除了TR1=1以外还需要INT1=1才可以真正开启定时器TH1 = 0;TL1 = 0;TR1 = 1;while(P3_3 == 1); //等待P3_3为低电平TR1 = 1; //P3_3为低电平的时候,TR1=1,但是此时定时器并未被真正开启,还需要INT1=1while(P3_3 == 0);//等待P3_3为高电平while(P3_3 == 1); //P3_3为高电平后,真正打开定时器,开始计数TR1 = 0;//读取函数read_count();
}

串口 方式0输出输入(非重点)

例题

在这里插入图片描述

#include <reg51.h>
#include <stdio.h>
unsigned char nIndex;
unsigned char nSendByte;void Delay()
{static int i = 100;static int j = 0;while(i--){for(j=0;j<120;j++);}
}void Serial_Init()
{SCON = 0x00; // 串口为方式0EA = 1;ES = 1; // 开启串口中断
}void dp_Serial() interrupt 4
{if(TI == 1) //发送中断标志位{P1_0 = 1;Delay();P1_0 = 0;nSendByte << 1;if(nSendByte == 0){nSendByte = 1;}SBUF = nSendByte;}TI = 0;RI = 0;
}void main()
{Serial_Init();nIndex = 1;SBUF = nSendByte;P1_0 = 0; //使能位while(1);
}

在这里插入图片描述

#include <reg51.h>
unsigned char nRxData;void Serial_Init()
{SCON = 0x00;EA = 1;ES = 1;
}void do_Serial() interrupt 4
{if(RI == 1) //接收到了数据{nRxData = SBUF;}TI = 0;RI = 0;
}void main()
{while(1){if(P1_0 == 0){P1_1 = 0;P1_1 = 1;}}
}

方式1的应用

在这里插入图片描述

#include <reg51.h>
//甲机发送程序
unsigned char temp;void Serial_Init()
{PCON = 0x00; // 波特率不倍增SCON = 0x40; // 0100 0000 SM2位只能在方式二和方式三多机通信//串口的方式一专门是为了双机通信设置的TMOD = 0x20;// 0010 0000TH1 = 0xFD;TL1 = 0xFD; // 波特率9600TR1 = 1;P1 = 0xFF; //P1口输入的时候,需要拉高电平
}void main()
{while(1){temp = P1;SUBF = temp;//查询方式,无需申请中断while(TI == 0); //TI = 1 说明一帧数据发送完毕TI = 0;}
}//乙机接收程序
unsigned char temp;
void Serial_Init()
{PCON = 0x00;SCON = 0x50;//0101 0000TMOD = 0x20;//0010 0000TH1 = 0xFD;TL1 = 0xFD;TR1 = 1;
}void main()
{while(1){//查询方式while(RI == 0);RI = 0;temp = SBUF;P1 = temp;}
}

方式2和方式3的应用

在这里插入图片描述

#include <reg51.h>
sbit p = PSW_0;
//甲机发送程序
unsigned char Tab[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯显示数据void Delay()
{unsigned int i = 100;unsigned int j;while(i--){for(j=0;j<120;j++);}
}void Serial_Init()
{SCON = 0xC0;//1100 0000 注意这里的SM2位不需要为1PCON = 0x00;TMOD = 0x20;//0010 0000TH1 = 0xFD;TL1 = 0xFD; //波特率9600EA = 1;ES = 1;TR1 = 1;
}void Send(unsigned char data)
{ACC = data; //把data数据暂存到ACC寄存器中TB8 = p; //奇偶校验位SBUF = data; //准备发送数据while(TI == 0); //等待数据发送TI = 0;
}unsigned int count;
void main()
{Serial_Init();while(1){for(count=0;count<8;count++){Send(Tab[count]);Delay(); //等待一段时间再发送}}
}//乙机接收程序
sbit p = PSW_0;unsigned char Receive()
{unsigned char data;while(RI == 0); // 等待接收 查询方式RI = 0;ACC = SBUF;if(RB8 == p) //奇偶校验{data = ACC;return data;}
}void Serial_Init()
{SCON = 0xD0; // 1101 0000 注意这里需要把REN位也置为1PCON = 0x00;TMOD = 0x20;TL0 = 0xFD;TH0 = 0xFD; //波特率9600EA = 1;ES = 1;TR1 = 1;
}void main()
{while(1){P1 = Receive();}
}

单片机向计算机发送数据(重点)

在这里插入图片描述

#include <reg51.h>
unsigned char Tab[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯显示数据void Send(unsigned char data)
{SBUF = data;while(TI == 0); // 等待单片机发送数据结束TI = 0;
}void Delay()
{unsigned int i = 100;unsigned int j;while(i--){for(j=0;j<120;j++);}
}void Serial_Init()
{SCON = 0x40;//0100 0000PCON = 0x00;TMOD = 0x20;TH1 = 0xFD;TL1 = 0xFD; //波特率9600EA = 1;ES = 1;//EA和ES可以不写,因为这里用的是查询方式TR1 = 1;
}unsigned int count;
void main()
{Serial_Init();while(1){for(count=0;count<8;count++){Send(Tab[count]);Delay();}}
}

单片机接收计算机发送的数据(重点)

在这里插入图片描述

#include <reg51.h>
void Serial_Init()
{SCON = 0x50;//0101 0000PCON = 0x00;TMOD = 0x20;TL1 = 0xFD;TH0 = 0xFD; //波特率9600EA = 1;ES = 1; //EA和ES可以不写,因为这里用的是查询方式TR1 = 1;
}unsigned char Recevive()
{unsigned char data;while(RI == 0); //接收数据RI = 0;data = SBUF;return data;
}void main()
{Serial_Init();while(1){P1 = Receive();}
}

数码管的实现(重点)

#include <reg51.h>
unsigned char Nixie_Table[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};void Delay(unsigned int i)
{unsigned int j;while(i--){for(j=0;j<120;j++);}
}void Nixie(unsigned location,unsigned number)
{switch(location){case 1:P2_4=1;P2_3=1;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 9:P2_4=0;P2_3=0;P2_2=0;break;}P0 = Nixie_Table[number];Delay(1);P0 = 0x00; // 消影子
}

矩阵键盘的实现(重点)

#include <reg51.h>void Delay(unsigned int i)
{unsigned int j;while(i--){for(j=0;j<120;j++);}
}unsigned char MartrixKey()
{unsigned char KeyNumber;P1 = 0xFF;P1_3 = 0;if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}P1 = 0xFF;P1_2 = 0;if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}P1 = 0xFF;P1_1 = 0;if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}P1 = 0xFF;P1_0 = 0;if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}return KeyNumber;
}

DAC0832输出锯齿波

在这里插入图片描述

#include <reg51.h>
#include <absacc.h>
#define DAC0832 XBYTE[0x7FFF]void stair()
{unsigned char i;for(i=0;i<255;i++){DAC0832 = i;}
}

DAC0832输出三角波

在这里插入图片描述

#include <reg51.h>
#include <absacc.h>
#define DAC0832 XBYTE[0x7FFF]void triangle()
{unsigned char i;for(i=0;i<255;i++){DAC0832 = i; //上升沿}for(i=255;i>0;i--){DAC0832 = i; // 下降沿}
}

DAC0832输出矩形波

在这里插入图片描述

#include <reg51.h>
#include <absacc.h>
#define DAC0832 XBYTE[0x7FFF]void rectangular()
{DAC0832 = 0xAF; //上限电平Delay();DAC0832 = 0x10; //下限电平Delay()
}

ADC转换

在这里插入图片描述

#include <reg51.h>
#include <absacc.h>
#define ADCstart 0x7FFF
#define ADCdata 0x2000unsigned char i;
void main()
{i = 8; //8路模拟信号EA = 1;EX1 = 1;IT1 = 1;XBYTE[ADCstart] = i;while(i);
}void int1() interrupt 2
{unsigned char temp;temp = XBYTE[ADCstart];i--;XBYTE[ADCdata+i] = temp;XBYTE[ADCstart] = i;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/415190.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

INS-06003错误处理

在麒麟V10操作系统上安装Oracle RAC 19C&#xff0c;安装GI的建立互信步骤中&#xff0c;遇到INS-06003错误&#xff1a; [INS-06003] Failed to setup password SSH connectivity with following node(s) 查看详细信息&#xff1a; PRVG-11001: PRCZ-2136: PRCZ-2006: 此时在操…

leetcode82. 删除排序链表中的重复元素 II

文章目录 题目思路1复杂度Code2 思路2复杂度2Code2 题目 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;…

SpringBoot Redis入门(四)——Redis单机、哨兵、集群模式

单机模式&#xff1a;单台缓存服务器&#xff0c;开发、测试环境下使用&#xff1b;哨兵模式&#xff1a;主-从模式&#xff0c;提高缓存服务器的高可用和安全性。所有缓存的数据在每个节点上都一致。每个节点添加监听器&#xff0c;不断监听节点可用状态&#xff0c;一旦主节点…

CTF CRYPTO 密码学-1

题目名称&#xff1a;enc 题目描述&#xff1a; 压缩包中含两个文件&#xff1a;一个秘钥d.dec&#xff0c;一个密文flag.enc 解题过程&#xff1a; Step1&#xff1a;这题是一个解密他题目&#xff0c;尝试openssl去ras解密 工具简介 在Kali Linux系统中&#xff0c;openss…

深入理解 Kubernetes Ingress:路由流量、负载均衡和安全性配置

Kubernetes Ingress 是 Kubernetes 集群中外部流量管理的重要组件。它为用户提供了一种直观而强大的方式&#xff0c;通过定义规则和配置&#xff0c;来控制外部流量的路由和访问。 1. 什么是 Ingress&#xff1f; 在 Kubernetes 中&#xff0c;Ingress 是一种 API 资源&#…

C语言--质数算法和最大公约数算法

文章目录 1.在C语言中&#xff0c;判断质数的常见算法有以下几种&#xff1a;1.1.试除法&#xff08;暴力算法&#xff09;&#xff1a;1.2.优化试除法&#xff1a;1.3.埃拉托色尼筛法&#xff1a;1.4.米勒-拉宾素性检验&#xff1a;1.5.线性筛法&#xff1a;1.6.费马小定理&am…

LLM:Scaling Laws for Neural Language Models (中)

核心结论 1&#xff1a;LLM模型的性能主要与计算量C&#xff0c;模型参数量N和数据大小D三者相关&#xff0c;而与模型的具体结构 (层数/深度/宽度) 基本无关。三者满足: C ≈ 6ND 2. 为了提升模型性能&#xff0c;模型参数量N和数据大小D需要同步放大&#xff0c;但模型和数…

赋能客户不停歇,卓翼飞思职业院校无人智能装备师资培训圆满落幕

1月10日-15日&#xff0c;卓翼飞思在北京研发中心成功举办职业院校无人智能装备高级师资培训。来自湖南汽车工程职业学院&#xff08;以下简称&#xff1a;湖南汽车职院&#xff09;的10名师生&技术人员参与此次培训&#xff0c;针对无人智能集群应用开发进行系统性的培训及…

重生奇迹MU快速升级

1、前期&#xff0c;都是主线任务&#xff0c;我们必须要跟着主线任务走&#xff0c;前面的话升级一次需要的经验很少的&#xff0c;一天下来可以升级100级是轻轻松松的&#xff0c;主线任务是比较多的&#xff0c;我们跟着任务一直做差不多可以到150级&#xff0c;接下来就是后…

flink学习之水位线

什么是水位线 在事件时间语义下&#xff0c;我们不依赖系统时间&#xff0c;而是基于数据自带的时间戳去定义了一个时钟&#xff0c; 用来表示当前时间的进展。于是每个并行子任务都会有一个自己的逻辑时钟&#xff0c;它的前进是靠数 据的时间戳来驱动的。 我们可以把时钟也以…

MySQL 基于创建时间进行RANGE分区

MySQL是一款广泛使用的关系型数据库。在MySQL中&#xff0c;大量数据场景提高查询效率是非常关键的&#xff0c;所以&#xff0c;对数据表进行分区是一个很好的选择。 在创建分区表之前&#xff0c;需要了解一下MySQL分区的基本概念。MySQL分区可以将一个大表分成多个小表&…

Skydel 23.8新版本发布!GNSS模拟器完成首项实地路测项目

奥本大学自动驾驶团队运用GNSS模拟器完成首项实地路测项目 奥本大学与最近与阿拉巴马州伯明翰的巴伯赛车运动公园合作进行道路测试&#xff0c;该车在没有任何人工干预的情况下成功绕赛道完成了一圈&#xff0c;这也是印地自动驾驶挑战赛中车辆首次在美国专业赛道上完成一圈。…