当前位置: 首页 > news >正文

单片机学习笔记——入门51单片机

一、单片机基础介绍

1.何为单片机

单片机,英文Micro Controller Unit,简称MCU 。内部集成了中央处理器CPU、随机存储器ROM、只读存储器RAM、定时器/计算器、中断系统和IO口等一系列电脑的常用硬件功能 单片机的任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设备(例如电机,LED等)的控制 。单片机跟计算机相比,单片机算是一个袖珍版计算机,一个芯片就能构成完整的计算机系统。但在性能上,与计算机相差甚远,但单片机成本低、体积小、结构简单,在生活和工业控制领域大有所用。 同时,学习使用单片机是了解计算机原理与结构的最佳选择。

单片机工作的基本时序

我们都知道在学校是通过铃声来控制所有班级的上下课时间,我们都知道单片机执行指令的过程就是从ROM取出一条指令执行来完成它在各个地方的作用,那它什么时候取指令这个是顺序呢?这里引入一个时序的周期,每访问一次ROM的时间,就是一个机器周期的时间

1个机器周期 = 6个状态周期 = 12个时钟(振荡)周期  

时钟周期:即单片机的基本时间单位,若晶体的频率=12MHZ,那时钟周期 = 1/12MHZ,一个时钟周期 = 1/12MHZ = 1/12000 000每秒

机器周期:即12x1/12 000 000 =0.000001s = 1us,访问一次ROM取指令的时间就是1us

2.单片机命名规则

3.单片机内部结构

重点需记:单片机管脚

1.电源:Vcc:正极     Gnd:负极             2.XTAL:单片机时钟引脚,外接晶振

3.RST:复位

4.开发板介绍

开发板原理图

二、单片机的一些基础项目

2-1、点亮一个led灯

#include <REGX52.H>
void main()
{P2=0x7f;//1111 1110  d1   16 15//0111 1111  d8    7 16//1011 1111  d7   11 16}

通过高低电平控制led亮否

2-2、led闪烁

#include <REGX52.H>
#include <INTRINS.H>//延时函数
void Delay500ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}void main()
{while(1){P2=0xfe;//亮Delay500ms();//延时500msP2=0xff;//灭Delay500ms();//延时500ms}
}

通过延时函数使led闪烁

2-3、流水灯

#include <REGX52.H>
#include <INTRINS.H>void Delay500ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}void main()
{while(1){P2=0xfe;//1111 1110Delay500ms();P2=0xfd;//1111 1101Delay500ms();P2=0xfb;//1111 1011Delay500ms();P2=0xf7;//1111 0111Delay500ms();P2=0xef;//1110 1111Delay500ms();P2=0xdf;//1101 1111Delay500ms();P2=0xbf;//1011 1111Delay500ms();P2=0x7f;//0111 1111Delay500ms();}
}

位运算做法:

2-4、流水灯plus

#include <REGX52.H>
#include <INTRINS.H>//任意延时函数——1ms的延时函数执行x次循环
void Delay1ms(unsigned int xms)		//@11.0592MHz
{unsigned char i, j;while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}
}void main()
{while(1){P2=0xfe;//1111 1110Delay1ms(100);P2=0xfd;//1111 1101Delay1ms(100);P2=0xfb;//1111 1011Delay1ms(100);P2=0xf7;//1111 0111Delay1ms(100);P2=0xef;//1110 1111Delay1ms(100);P2=0xdf;//1101 1111Delay1ms(100);P2=0xbf;//1011 1111Delay1ms(100);P2=0x7f;//0111 1111Delay1ms(100);}
}

通过任意延时函数去简化步骤

3-1、通过独立按键控制led闪烁

#include <REGX52.H>void main()
{while(1){if(P3_1==0)//低电平 按下按键接地为0{P2_0=0;//d1亮}else {P2_0=1;}}
}

3-2、通过独立按键控制led状态

#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int xms)		//@11.0592MHz
{unsigned char i, j;
while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;
}
}void main()
{while(1){if(P3_1==0){Delay(20);//取消前摇while(P3_1==0);//判断何时松手Delay(20);//取消后摇P2_0=~P2_0;//按位取反}
}
}

取消按键时的抖动,使单片机稳定判断状态。按一次亮,按一次灭。

3-3、通过独立按键控制led完成二进制

#include <REGX52.H>
#include <INTRINS.H>void Delay(unsigned int xms)		//@11.0592MHz
{unsigned char i, j;
while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;
}
}void main()
{unsigned int lednum=0;while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);lednum++;P2=~lednum;}
}
}

也可以直接用P2--;代替最后两句,完成二进制运算。

3-4、用独立按键控制led灯移位

#include <REGX52.H>
#include <INTRINS.H>void Delay(unsigned int xms)		//@11.0592MHz
{unsigned char i, j;
while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;
}
}void main()
{unsigned int lednum=0;P2=~0x01;while(1){if(P3_1==0)//k1{Delay(20);while(P3_1==0);Delay(20);lednum++;if(lednum>=8)lednum=0;P2=~(0x01<<lednum);}if(P3_0==0)//k2{Delay(20);while(P3_0==0);Delay(20);if(lednum==0)lednum=7;else lednum--;P2=~(0x01<<lednum);
}
}}

4-1 静态数码管

1.常见数码管

2.控制数码管显示的原理图

3.管脚定义(对应字母控制对应位置亮):上面的为共阴极、下面的为共阳极(可以理解为3,8管脚处为供电,三角形尖尖有一横的是负极,所有共阴极),两个图中的数字为引脚:

4.下面为多个数码管,PCB板的4个为一体,同样上面为共阴极、下面为共阳极的原理图:

5.STC89C52实现数字显示

①原理图是共阴极(上面给0、下给1亮)

②138译码器:输入3(ABC,读的时候是从下读 C B A )个口,控制输出8个口,输出口连接共阴极的,是0还是1,在这里控制:使能端连接(按下图给1和0就可以用了)

通过CBA给数字0和1二进制转换10进制(得到数字几)就控制Y几,Y0头上“—”是表示低电平有效(即给0):

③双向缓冲,高电平往低电平送数据

CC2电容作用:滤波电容,稳定电源,确定电路稳定性,提高电路工作性能可靠运行;

RP4:排阻,限流,防止电流过大

④这里的P01......P07,就是用P0口,后面代码就是通过P0口控制灯的

只有Y5为0,其他Y0...Y7都为1;

读取顺序都是从下到上

⑤代码控制公共端,从下往上写:

二进制101转换为1十进制为5,控制Y5,即公共端的LED6;

要显示下图的数字6

代码实现如下(P2控制共阴极,P0控制显示数字)及结果;

 ⑥优化操作代码:通过数组,子函数来优化代码
#include <REGX52.H>
#include <INTRINS.H>unsigned char NixieTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};void Nixie(unsigned char Location,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 8:P2_4=0;P2_3=0;P2_2=0;break;}P0=NixieTable[Number];
}void main()
{Nixie(7,10);while(1);}

要显示的数字对应的值

4-2、动态数码管 

#include <REGX52.H>
#include <INTRINS.H>unsigned char NixieTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};void Delay (unsigned int xms)		//@11.0592MHz
{unsigned char i, j;
while(xms--){_nop_();i = 2;j = 199;do{while (--j);} while (--i);
}
}void Nixie(unsigned char Location,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 8:P2_4=0;P2_3=0;P2_2=0;break;}P0=NixieTable[Number];Delay(1);//保证亮度P0=0x00;//清零
}void main()
{while(1){Nixie(2,1);// Delay(20);Nixie(3,2);// Delay(20);Nixie(4,3);//	Delay(20);}
}

注释掉上面的延时调用,旁边的管会有些影响,需要消影,段选、位选影响造成串位,如下代码消除

了解

5-1、模块化编程 

1)驱动,先会用,后续有详细内容:

2)模块化,功能函数用点C文件写,点H文件声明函数,在main函数文件引入头文件直接调用:

3)注意事项

4)预编译

5)延时函数文件

6)头文件延迟

7)主函数文件程序入口:

8)数码管模块,用到的头文件要引用:

9)数码管模块头文件

10)函数调用

11)显示

5-2 、LCD1602调试工具-------

1)调试工具原理图

2)模块化代码,下完放到自己工程目录下:



3)将下好的两个文件添加到工程:

4)文件主要内容如下:

5)main函数调用:

6)显示其他管脚冲突,所有会一起显示:

7)其他函数的调用及功能,可以设置显示位置和范围:

8)需要用到延迟函数:可以直接将前面模块化文件复制到工程目录下,添加进来引用即可;

9)娱乐:小计时器

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"int Result=0;void main()
{LCD_Init();//初始化while(1){Result++;Delay(1000);LCD_ShowNum(1,1,Result,3);}//计时器



6-1.矩阵键盘

1)基础介绍:

P14-P17给0就代表扫描,其他给1(没选中),一次只能扫描一行;P10-P13给0表示按下,给1表示没按下;(逐列扫描)

2.代码实现:

①:创建工程并把“Delay”与“LCD1602”的模块加入此工程中。
②:编写MatrixKey(矩阵)代码
#include <REGX52.H>
#include "Delay.h"unsigned char MatrixKey()
{unsigned char KeyNumber=0;P1=0xff;      //按列扫描P1_3=0;       //控制扫描的列if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}    //while判断何时松手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;
}
③.编写主函数
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "matrixKey.h"unsigned char KeyNum;void main()
{LCD_Init();   //LCD上电初始化LCD_ShowString(1,1,"Helloworld");while(1){KeyNum=MatrixKey();if(KeyNum){LCD_ShowNum(2,1,KeyNum,2);}
}}
④.软件使用小技巧

快速生成常用格式代码:

设置,完成后双击就可以生成了:

6-2.矩阵键盘密码锁

1):把6-1文件全部cv到6-2工程文件中

2):代码实现

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "matrixKey.h"unsigned char KeyNum;
unsigned int Password,count;void main()
{LCD_Init();LCD_ShowString(1,1,"Helloworld");while(1){KeyNum=MatrixKey();if(KeyNum){if(KeyNum<=10){  				//s1~s10按下密码if(count<4){Password*=10;Password+=KeyNum%10;       //这两句是用来实现四位密码的显示count++; 		//计数  防止按下的密码数超过四位	}LCD_ShowNum(2,1,Password,4);//更新显示}if(KeyNum==11){    //s11设置为确认键if(Password==2345){LCD_ShowString(1,14,"OK ");Password=0;  //密码清零count=0;      //计数清零LCD_ShowNum(2,1,Password,4);//更新显示}else {LCD_ShowString(1,14,"ERR");Password=0;  //密码清零count=0;      //计数清零LCD_ShowNum(2,1,Password,4);//更新显示}}if(KeyNum==12){  //定义S12为取消键Password=0;count=0;LCD_ShowNum(2,1,Password,4);}
}}
}

7.定时器介绍

1)介绍,Delay前面CPU是一直在等的,用定时器在Delay时可以去检测按键,提高CPU利用率:

2)模式1最常用:

3)模式:时钟--计数最大65535(计数系统TL0\TH0:每来一个脉冲+1方法计数)-TF0(标志位,到最大了回到0)-中断:

4)非门与门图形为控制部分(TR0是否启动暂定)

5)定时器部分:

6)时钟可以由系统提供(上图,晶振),也可以由外部T0P提供(如下图引脚)

7)C/T,给1连上面为控制器,给0连接下面为定时器(如下图):

8)中断系统:

9)中断资源

10)定时器和中断系统

11)定时器相关寄存器

7-1.独立按键控制流水灯的模式

1.TMOD寄存器工作模式,定时器0配置使用(不可位寻址,只能整体赋值)

2.定时器模式1:门控端给0,就是tr0单独控制:C/T,T这里有一横表示低电平有效,就给0是用T(定时器模式),给1用C(控制器模式),M1,M0工作模式选择

3.TCON控制寄存器(可位寻址,可以单独每一位赋值)

中断溢出标志位:

TF=0(等于1产生中断);

TR0=1(定时器是否开启,给1开始,电机开始工作);

IE0、IT0:控制外部中断引脚,可以不配置

4.定时器配置  TH0\TL0

TH0\TL0 分开储存

代码优化,TMOD问题(不可位寻址)配置两个的时候,后面的会把前面的覆盖;

因此,可采用“与或”法设定TMOD

 

5.中断配置T0-->ET0=1--EA=1,PT0=0

6.定时器配置完成,模块化编程

#include <REGX52.H>void Timer0_Init(void)		//1ms@11.0592MHz
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0x66;		//设置定时器初值TH0 = 0xFC;		//设置定时器初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时ET0=1;    //下面三行为中断的配置EA=1;PT0=0;
}

 7.定时器中断函数模板


void Timer0_Routine() interrupt 1  //中断函数
{static unsigned int T0Count; TL0 = 0x66;		//设置定时器初值TH0 = 0xFC;		//设置定时器初值T0Count++;if(T0Count>=1000)   //每隔1s{		T0Count=0;}
}

8.独立按键模块

#include <REGX52.H>
#include "Delay.h"unsigned char Key()
{unsigned char KeyNumber=0;if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}return KeyNumber;
}

9.主函数

#include <REGX52.H>
#include "Timer0.h"
#include "key.h"
#include <INTRINS.H>unsigned char KeyNumber,LEDmode;
void main()
{P2=0xfe;  //与INTRINS.H中的循环左右移函数共同实现流水灯Timer0_Init(); //上电初始化while(1){KeyNumber=Key();if(KeyNumber){if(KeyNumber==1){LEDmode++;if(LEDmode>=2) LEDmode=0;}}}
}void Timer0_Routine() interrupt 1  //中断函数
{static unsigned int T0Count; TH0=64535/256;TL0=64535%256; 	T0Count++;if(T0Count>=1000)   //每隔1s{T0Count=0;if(LEDmode==0) P2=_crol_(P2,1);if(LEDmode==1) P2=_cror_(P2,1);}
}

7-2.时钟 

1.把LCD1602液晶显示、延迟、定时器、的代码复制到工程目录下,导入;

2.主函数包含其他模块头文件并初始化;

3.复制定时器中断函数到main函数下:

4.定义变量,秒计数、分、小时并显示:

5.代码综合

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"unsigned char Sec,Min,Hour;
void main()
{LCD_Init();//³õʼ»¯Timer0_Init();LCD_ShowString(1,1,"CLOCK:");LCD_ShowString(2,1,"  :  :");while(1){LCD_ShowNum(2,1,Hour,2);LCD_ShowNum(2,4,Min,2);LCD_ShowNum(2,7,Sec,2);}
}void Timer0_Routine() interrupt 1  
{static unsigned int T0Count; TL0 = 0x66;		TH0 = 0xFC;		T0Count++;if(T0Count>=1000)   {T0Count=0;Sec++;if(Sec>=60){Sec=0;Min++;if(Min>=60){Min=0;Hour++;if(Hour>=24){Hour=0;}}}}}

8-1串口介绍

1)介绍

2)向单片机发送数据(下面框),返回(上框)

3)DB9串口传输数据(注意使用的电压是否一致)使用RS232或RS485电平

4)知识点

①硬件电路

注:最少需要三根线实现双向通信:TXD,RXD,GND。VCC不一定需要,可独立供电。

②电平标准 

 

 差分信号优点:传送距离远(1km+)   TTL与RS232(10m)

③常见通信接口比较

 CAN总线:常用于汽车领域,因为使用的是差分信号传输,传输距离远、稳定。

通信方式的相关术语:

④51单片机里的UART串口 

 

 

   中间部分用来控制波特率,依靠定时器来约定速率,T1的溢出率通过分频后来控制收发器的采样时间。

  SBUF:收发数据后,会产生相应的TI(发送中断)/RI(接收中断),继而进入中断函数,进行相应的中断函数内部的操作。

 配置ES、EA,PS此时不需要配置,因为只有一个中断,不需要进行优先级判断。

 配置好SCON和PCON,读SBUF,配置定时器T1,打开EA和ES,即串口可以开始工作。

8-2.实际配置串口 

1)将延迟函数复制过来并导入工程里面;

2)配置串口控制寄存器,配置模式1最常用,REN允许接收给1,不允许接收给0(也可以给1外面不给发就行);

3)TI、RI发送完置1(硬件只负责),但必须软件复位置0;

 故SCON=0x40

PCON

4)配置定时器

这里定时器1,没有定时器0,所有要把高位修改(不影响高低位配置用“”& |“”这两个方式)

选择8位自动重载模式

5)可以直接用STC-isp来配置串口 

系统频率根据板子选择,波特率4800,波特率发生器选择8位自动重载,时钟12T

6)发送数据的函数

7)发送单项数据

8)模块化

9)数据显示模式 

8-3.串口实例实现 

1)每一秒发送一个递增的数字

 2)电脑通过串口控制LED灯,并且返回电脑读入的数据

1.需要打开串口的中断功能

SCON = 0x50;  EA=1;ES=1; 

注:要分清这里是禁止了定时器1的中断功能,只是让它的溢出率去开启串口收发的功能,中断的产生是由于串口收发数据产生的中断。

2.编写串口中断函数

串口中断函数模板:

void UART_Routine() interrupt 4
{if(RI==1){RI=0;   //复位清0}
}

3.整体代码

9-1LED点阵屏

1.介绍:


2.显示原理

3.相关图

①:led矩阵图——经测试,P0控制列,D控制行

②:开发版引脚对应关系:

③:74HC595 

 加-,低电平有效

OE: 使能,output enable,接低电平工作,高电平不工作。

RCLK:寄存器时钟,register clock

SRCLR:串行清零端

SRCLK:串行时钟 

SER:串行数据

运行方式:类似队列

④:总结:使用步骤:进行行列的选择——列由P0口控制,因此给P0赋值就能控制列。行需通过74HC595来间接控制。

9-2.点阵屏的驱动代码 

示例代码1-点阵屏显示图形

1)sfr与sbit,可位寻址与不可位寻址。

2) 进行位声明,方便操作。

3)编写子函数——控制74HC595把字节数据输出给D的8个引脚。

4) 编写LED矩阵显示的子函数

5)  自己设计图形,调用函数输入数据,即可显示;

示例代码2-点阵屏显示动画

1)把示例1的代码模块化
2)定义要显示的动画的数组,并初步检测是否显示正常

3)实现动态显示

 

上述代码实现的是流水式的动画,也可以改变offset去实现逐帧动画。

4)定义的Animation是放在RAM中的,有空间限制,浪费RAM空间。所以可以加个code,把它放在flash里,但此时不可在主函数里改变数组内容。

10-1 DS1302实时时钟介绍

1.介绍

定时器计时的缺点:1.精度不高  2.消耗单片机的CPU  3.断电不能继续计时

而时钟芯片精度高,且有备用电源,掉电可以用备用电源继续计时。

2.时钟芯片的引脚定义和应用电路

①:两种封装模式:直插封装和贴片封装  ②:分为三部分:电源部分,时钟部分,数据交互部分

3. 内部结构框图

4.内部寄存器的定义

秒,分,时,日,月,年,星期,年,wp(write protect,写保护),涓流充电

前两列的为 :命令字——

5. 时序图

前八为指定读还是写,后八位读出或者写入指定的数据。

上升沿写入,下降沿读出。

6.BCD码

10-2 实例代码

1.时钟

1)创建工程,cvLCD1602的文件,并开始模块化编写DS1302的模块

2) DS1302模块的子函数编写

3)初步测试 

结果会发现,数字到9后会直接到16……,这是因为寄存器数据是以BCD码存储的,只需将Second改为Second/16*10+Second%16,就可以转化成十进制,正常显示。

4) 定义一下各个寄存器的地址,方便操作;再定义一个存储时间的数组;
5) 编写DS1302的另外两个子函数——①:设定时间 ②:读出时间     并声明为外部可调用的函数和数组;

6) 编写主函数,调用函数在LCD显示屏上显示时间

2.功能化时钟——可以用独立按键设置要显示的时间

1)需要用到的模块

DS1302模块,LCD1602模块,独立按键key模块,定时器Timer0模块,延时函数模块;

2)编写主函数

主要分为四大部分:时钟模式选择,显示时间,设置时间(选择设置的时间位置,调整时间大小,利用定时器中断去实现选择的时间的位置的动态显示),更新显示新的时钟。

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer0.h"
#include "Delay.h"unsigned char KeyNum,MODE,TimeSetSelect,TimeFlashFlag;/*** @brief  显示时间* @param 无* @retval 无*/
void TimeShow(void)
{DS1302_ReadTime();LCD_ShowNum(1,1,DS1302_Time[0],2);LCD_ShowNum(1,4,DS1302_Time[1],2);LCD_ShowNum(1,7,DS1302_Time[2],2);LCD_ShowNum(2,1,DS1302_Time[3],2);LCD_ShowNum(2,4,DS1302_Time[4],2);LCD_ShowNum(2,7,DS1302_Time[5],2);
}/*** @brief  设置时间,按键2选择设置的时间位置,按键3让时间++,按键4让时间--* @param  无* @retval 无*/
void TimeSet(void)
{if(KeyNum==2){TimeSetSelect++;TimeSetSelect %= 6;}if(KeyNum==3){DS1302_Time[TimeSetSelect]++;if(DS1302_Time[0]>99){DS1302_Time[0]=0;}if(DS1302_Time[1]>12){DS1302_Time[1]=1;}if(DS1302_Time[1]==1 || DS1302_Time[1]==3 ||DS1302_Time[1]==5 ||DS1302_Time[1]==7 || DS1302_Time[1]==8 || DS1302_Time[1]==10 ||DS1302_Time[1]==12){if(DS1302_Time[2]>31){DS1302_Time[2]=1;}}else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 ||DS1302_Time[1]==5 ||                     DS1302_Time[1]==9 || DS1302_Time[1]==11){if(DS1302_Time[2]>30){DS1302_Time[2]=1;}}else if(DS1302_Time[1]==2){	if(DS1302_Time[0]%100!=0&&DS1302_Time[0]%4==0||DS1302_Time[0]%100==0&&DS1302_Time[0]%400==0){if(DS1302_Time[2]>29){DS1302_Time[2]=1;}}else if(DS1302_Time[2]>28){DS1302_Time[2]=1;}}if(DS1302_Time[3]>23){DS1302_Time[3]=0;}if(DS1302_Time[4]>59){DS1302_Time[4]=0;}if(DS1302_Time[5]>59){DS1302_Time[5]=0;}}if(KeyNum==4){DS1302_Time[TimeSetSelect]--;if(DS1302_Time[0]<0){DS1302_Time[0]=99;}if(DS1302_Time[1]<0){DS1302_Time[1]=12;}if(DS1302_Time[1]==1 || DS1302_Time[1]==3 ||DS1302_Time[1]==5 || DS1302_Time[1]==7 || DS1302_Time[1]==8 || DS1302_Time[1]==10 ||DS1302_Time[1]==12){if(DS1302_Time[2]<1){DS1302_Time[2]=31;}if(DS1302_Time[2]>31){DS1302_Time[2]=1;}}else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 ||DS1302_Time[1]==5 || DS1302_Time[1]==9 ||	DS1302_Time[1]==11){if(DS1302_Time[2]<1){DS1302_Time[2]=30;}if(DS1302_Time[2]>30){DS1302_Time[2]=1;}}else if(DS1302_Time[1]==2){if(DS1302_Time[0]%100!=0&&DS1302_Time[0]%4==0||DS1302_Time[0]%100==0&&DS1302_Time[0]%400==0){if(DS1302_Time[2]<1){DS1302_Time[2]=29;}if(DS1302_Time[2]>29){DS1302_Time[2]=1;}}else {if(DS1302_Time[2]<1){DS1302_Time[2]=28;}if(DS1302_Time[2]>28){DS1302_Time[2]=1;}}}if(DS1302_Time[3]<0){DS1302_Time[3]=23;}if(DS1302_Time[4]<0){DS1302_Time[4]=59;}if(DS1302_Time[5]<0){DS1302_Time[5]=59;}}//动态显示选择位if(TimeSetSelect==0 && TimeFlashFlag==1 ){LCD_ShowString(1,1,"  ");}else {LCD_ShowNum(1,1,DS1302_Time[0],2);}if(TimeSetSelect==1 && TimeFlashFlag==1 ){LCD_ShowString(1,4,"  ");}else {LCD_ShowNum(1,4,DS1302_Time[1],2);}if(TimeSetSelect==2 && TimeFlashFlag==1 ){LCD_ShowString(1,7,"  ");}else {LCD_ShowNum(1,7,DS1302_Time[2],2);}if(TimeSetSelect==3 && TimeFlashFlag==1 ){LCD_ShowString(2,1,"  ");}else {LCD_ShowNum(2,1,DS1302_Time[3],2);}if(TimeSetSelect==4 && TimeFlashFlag==1 ){LCD_ShowString(2,4,"  ");}else {LCD_ShowNum(2,4,DS1302_Time[4],2);}if(TimeSetSelect==5 && TimeFlashFlag==1 ){LCD_ShowString(2,7,"  ");}else {LCD_ShowNum(2,7,DS1302_Time[5],2);}
}void main()
{Timer0_Init();LCD_Init();DS1302_Init();DS1302_WriteByte(0x8e,0x00);  LCD_ShowString(1,1,"  -  -  ");LCD_ShowString(2,1,"  :  :  ");DS1302_SetTime();while(1){//通过按键1控制时钟的模式,模式0为显示时钟,模式1为设置时间KeyNum=key();if(KeyNum==1){if(MODE==0){MODE=1;TimeSetSelect=0;}else if(MODE==1) {MODE=0;DS1302_SetTime();}}switch(MODE){case 0:TimeShow();break;case 1:TimeSet();break;}}}//利用定时器中断来动态显示选择的时间位置
void Timer0_Routine() interrupt 1  
{static unsigned int T0Count; TL0 = 0x66;		TH0 = 0xFC;		T0Count++;if(T0Count>=1000)   {T0Count=0;TimeFlashFlag=!TimeFlashFlag;}
}

11.蜂鸣器

1)介绍

 NPN:高电平导通     PNP:低电平导通

由P15的高低电平取反控制BZ的高低电平

 2)乐理知识

①:介绍C1-C2升高8度。往右升高,往左降低:相邻半音黑白,1对应中央C1,i表示升即C2部分,降低8度下面加一个点,降低2个8度,下面加两个点(白键);相邻两个键为半音#:升高半音,b:降低半音。

②:-表示时长,如图中的665-,其中5占两个节拍,

③:音符

 一般以四分音符为一个基准

④:音符频率对照

⑤:以a440hz为基准,到另一个a,中间等比12频分,
 ⑥:单片机晶振芯片每秒震荡的次数称为时钟频率,震荡一次所需时间称为振荡周期。12个震荡周期是一个机器周期,机器频率=晶振频率/12,计时周期=1/机器周期,即每过一个计时周期,定时器计数+1;
给定时器的TL和TH赋重装载值,使定时器每过所需周期的一半时计数+1(因为需要给震荡信号,故计数周期=原周期的二分之一),从而使蜂鸣器发出对应频率的声音。

3)实例代码

1.蜂鸣器鸣响
①:蜂鸣器模块函数

②:主函数——按下独立按键,在数码管上显示按的第几个键,并且蜂鸣器鸣响。

 

2.蜂鸣器演奏音乐—有时间再补

12.AT24C02,I2C总线

1.存储器介绍

RAM:存储速度快,但是掉电丢失   ROM:掉电不丢失,但是速度慢。

2.AT24C02介绍

引脚及应用电路

 

3. I2C总线

 

I2C通信 时序结构:

 

 

 

 

 

 

4.示例程序

1——用独立按键设置想要写入的数据,并读出显示在LCD上,断电不丢失。
①:程序编写整体思路:编写I2C模块,AT24C02模块,main模块

②:编写I2C模块

先进行位声明,再分别编写子函数,开始,结束,发送和接受一个字节,发送和接收应答位

 

③:编写AT24C02模块

先定义一下AT24C02的地址,写是0xA0,读是0xA1;

再用I2C里的函数去编写写入一个字节和读出一个字节的函数

 

④:编写main模块

用独立按键控制想要写入的数据,并读出显示在LCD上,断电不丢失。

 

2——秒表(用定时器扫描数码管)
①:先创建新的工程,包含所需的模块——独立按键,数码管,延迟函数,定时器,AT,I2C
②:改造独立按键模块——用定时器扫描独立按键

这样就不用像原来一样在检测时停在while死循环里,影响主函数进程

 

③:改造数码管模块——改造成用定时器扫描数码管

先在main模块的中断函数里加上一个计数定时器的T0Count2,这样每隔一段时间就会调用一下NixieLoop函数,而NixieLoop函数会不断扫描并在数码管上显示每一位数字。NixieSetBuf函数会根据输入的位置和数字改变Buf数组里的值,继而让NixieLoop扫描显示对应的值。

 

④: 编写主函数
#include <REGX52.H>
#include "Timer0.h"
#include "key.h"
#include "Delay.h"
#include "Nixie.h"
#include "AT24C02.h"unsigned char KeyNum;
unsigned char Min,Sec,Minisec;
unsigned char Runflag;void main()
{Timer0_Init();while(1){KeyNum=Key();if(KeyNum==1)   //按键1控制开始和停止计时{Runflag=!Runflag;}if(KeyNum==2)    //按键2清0{Min=0;Sec=0;Minisec=0;}if(KeyNum==3)  //按键3将数据写入AT{AT24C02_WriteByte(0,Min);Delay(5);AT24C02_WriteByte(1,Sec);Delay(5);AT24C02_WriteByte(2,Minisec);Delay(5);}if(KeyNum==4)   //按键4读出数据{Min=AT24C02_ReadByte(0);Sec=AT24C02_ReadByte(1);Minisec=AT24C02_ReadByte(2);}Nixie_SetBuf(1,Min/10);Nixie_SetBuf(2,Min%10);Nixie_SetBuf(3,11);Nixie_SetBuf(4,Sec/10);Nixie_SetBuf(5,Sec%10);Nixie_SetBuf(6,11);Nixie_SetBuf(7,Minisec/10);Nixie_SetBuf(8,Minisec%10);}
}//计时中断函数
void Sec_Loop()
{if(Runflag){Minisec++;if(Minisec>=100){Minisec=0;Sec++;if(Sec>=60){Sec=0;Min++;if(Min>=60){Min=0;}}}
}
}void Timer0_Routine() interrupt 1  //ÖжϺ¯Êý
{static unsigned int T0Count1,T0Count2,T0Count3; TL0 = 0x66;		//ÉèÖö¨Ê±Æ÷³õÖµTH0 = 0xFC;		//ÉèÖö¨Ê±Æ÷³õÖµT0Count1++;if(T0Count1>=20)  {T0Count1=0;Key_Loop();}T0Count2++;if(T0Count2>=2)   {T0Count2=0;Nixie_Loop();}T0Count3++;if(T0Count3>=10){T0Count3=0;Sec_Loop();}
}

13.1 DS18B20——温度传感器

1.介绍

 2.引脚及应用电路

3.内部结构框图

最后一列分别是:温度传感器(内部的模拟温度传感器,能进行数据的转换),存储高报警位的EEPROM,存储低报警位的EEPROM,调节精度,校验码

前两个字节分别存储数据的低位和高位

总体思路:先发送温度转换的指令,再发送读数据的指令。因此,我们接下来要学习,如何通过单总线来发送数据和接收数据。

4.单总线介绍

①:介绍

  ②:时序结构

 

5.DS18B20操作流程

 本节需要的指令SKIP ROM,CONVERT T:让温度转换器进行数据的转换,READ SCRATCHPAD:读暂存器,依次读出每一个字节。

 

 

包括符号,整数部分,小数部分,其中负数以补码形式存储

13.2示例代码

1-DS18B20温度读取

①:整体思路——先写OneWire模块(包括初始化,发送一位,读出一位,发送一个字节,接收一个字节),再写DS18B20模块(包括温度转换指令函数,读取数据函数),最后编写main函数。

②:OneWire模块编写

③:DS18B20模块编写

④:main函数

实例代码2-DS18B20温度报警器

①:要用到的模块:AT24C02,Delay,DS18B20,LCD1602,OneWire,I2C,key,Timer0
②:main函数
#include <REGX52.H>
#include "DS18B20.h"
#include "key.h"
#include "LCD1602.h"
#include "Delay.h"
#include "AT24C02.h"
#include "Timer0.h"float T,TShow;
char TLow,THigh;
unsigned char KeyNum;void main()
{DS18B20_ConverT();Delay(1000);THigh=AT24C02_ReadByte(0);TLow=AT24C02_ReadByte(1);if(THigh>125 || TLow<-55 || THigh<=TLow){THigh=20;TLow=15;}LCD_Init();LCD_ShowString(1,1,"T:");LCD_ShowString(2,1,"TH:");LCD_ShowString(2,9,"TL:");LCD_ShowSignedNum(2,4,THigh,3);LCD_ShowSignedNum(2,12,TLow,3);Timer0_Init();while(1){KeyNum=Key();/*温度读取及显示*/DS18B20_ConverT();T=DS18B20_ReadT();if(T<0){LCD_ShowChar(1,3,'-');TShow=-T;}else {LCD_ShowChar(1,3,'+');TShow=T;}LCD_ShowNum(1,4,TShow,3);LCD_ShowChar(1,7,'.');LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);/*阈值判断及显示*/if(KeyNum){if(KeyNum==1){THigh++;if(THigh>125){THigh=125;}}if(KeyNum==2){THigh--;if(THigh<=TLow){THigh++;}}if(KeyNum==3){TLow++;if(TLow>=THigh){TLow--;}}if(KeyNum==4){TLow--;if(TLow<-55){TLow=-55;}}LCD_ShowSignedNum(2,4,THigh,3);LCD_ShowSignedNum(2,12,TLow,3);AT24C02_WriteByte(0,THigh);Delay(5);AT24C02_WriteByte(1,TLow);Delay(5);}if(T>THigh){LCD_ShowString(1,13,"OV:H");}else if(T<TLow){LCD_ShowString(1,13,"OV:L");}else {LCD_ShowString(1,13,"OV: ");}}
}void Timer0_Routine() interrupt 1  //中断函数
{static unsigned int T0Count; TL0 = 0x66;		TH0 = 0xFC;		T0Count++;if(T0Count>=20)   {T0Count=0;Key_Loop();}
}

为防止定时器扫描按键时会打断OneWire的传送与接收

可以在OneWire里先关闭EA,再打开EA。

14-1 LCD1602液晶显示屏

1.介绍

 2.引脚及应用电路

   3.内部结构框图

 4.存储器结构

 5.时序结构

 6.LCD1602指令集

 

7.LCD1602操作流程

14-2 功能代码编写

之后可以在main函数里调用流动的指令,实现流动字幕

15-1 直流电机

1.介绍

2.电机驱动电路

大功率器件直接驱动:只能使电机朝着一个方向转,不具备调换电机正反方向的功能。

H桥驱动:可以控制电机正反转。

3.电机调速——PWM介绍

给电全速转,不给电不转,利用惯性,可以设置一个在周期内高电平与低电平的时间,使之呈现中间速度

 

15-2 示例代码

1.LED呼吸灯——用来理解PWM

2.电机调速 

①:创建新工程,需要用到的模块:Delay,Timer0,Nixie,key
②:main函数编写
#include <REGX52.H>
#include "Delay.h"
#include "key.h"
#include "Nixie.h"
#include "Timer0.h"sbit Motor=P1^0;  //位声明unsigned char Counter,Compare;
unsigned char KeyNum,Speed;void main()
{Timer0_Init();while(1){KeyNum=Key();if(KeyNum==1){Speed++;Speed%=4;if(Speed==0){Compare=0;}if(Speed==1){Compare=50;}if(Speed==2){Compare=75;}if(Speed==3){Compare=100;}}Nixie(1,Speed);}
}void Timer0_Routine() interrupt 1  
{TL0 = 0xA4;		TH0 = 0xFF;		Counter++;if(Counter>=100) {Counter=0;}if(Counter<Compare){Motor=1;}else{Motor=0;}
}

16-1 AD/DA

1.介绍

2.硬件电路模型

3.实际硬件电路

4.运算放大器

四大运算放大器的经典电路

5.DA原理

6.AD

7.AD/DA性能指标

8.XPT2046

SPI通信:CS:片选,DCLK:时钟,DIN:数据输入,DOUT:数据输出

每个从机单独有个CS与主机连接,剩下三根线共用

16-2.实例代码

1.AD模数转换——在LCD上显示滑变,热敏电阻,光敏电阻的值

①:需要的模块:Delay,LCD,XPT2046
②:XPT2046模块的编写

先进行位声明,再写读取AD值的函数,读AD值,要给一个命令字,说明以什么模式读取的什么部位的AD值

#include <REGX52.H>
#include "Delay.h"sbit XPT2046_CS=P3^5;
sbit XPT2046_DCLK=P3^6;
sbit XPT2046_DIN=P3^4;
sbit XPT2046_DOUT=P3^7;unsigned int XPT2046_ReadAD(unsigned char Command)
{unsigned char i;unsigned int ADValue;XPT2046_DCLK=0;XPT2046_CS=0;for(i=0;i<8;i++){XPT2046_DIN=Command&(0x80>>i);XPT2046_DCLK=1;Delay(1);XPT2046_DCLK=0;}for(i=0;i<16;i++){XPT2046_DCLK=1;Delay(1);XPT2046_DCLK=0;if(XPT2046_DOUT) {ADValue|=(0x8000>>i);}}XPT2046_CS=1;if(Command&0x08){return ADValue>>8;}else{return ADValue>>4;}
}

③:main函数

2.DA数模转换——实现呼吸灯

①:用PWM的工程改造即可
②:换IO口,把Motor换成DA的口,再结合PWM调速,即可实现。

17-1 红外遥控

1.介绍

2.硬件电路

3.基本发送与接收

4.NEC编码

5.51单片机的外部中断

17-2.实例代码

1.红外遥控显示按键键码

①:配置外部中断INT0,并编写设置定时器时间和读取定时器时间,以及控制定时器开启的子函数

②:编写红外遥控模块IR
#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"unsigned int IR_Time;
unsigned char IR_State;unsigned char IR_Data[4];  //数据缓存器
unsigned char IR_pData;   //指向存储的位置unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;void Int0_Routine(void) interrupt 0
{if(IR_State==0){Timer0_SetCounter(0);Timer0_Run(1);IR_State=1;}else if(IR_State==1){	IR_Time=Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time>12442-500 && IR_Time<12442+500)  //根据时间来判断是否是start信号{IR_State=2;}else if(IR_Time>10368-500 && IR_Time<10368+500)  //判断是否是repeat信号{IR_RepeatFlag=1;Timer0_Run(0);IR_State=0;}else   //其它未知的出错情况{IR_State=1;}}else if(IR_State==2){IR_Time=Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time >1032-500 && IR_Time<1032+500){IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));IR_pData++;}else if(IR_Time >2074-500 && IR_Time<2074+500){IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));IR_pData++;}else {IR_pData=0;IR_State=1;}if(IR_pData>=32){IR_pData=0;if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]) ){IR_DataFlag=1;IR_Address=IR_Data[0];IR_Command=IR_Data[2];}Timer0_Run(0);IR_State=0;}}
}

③:编写main
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Int0.h"
#include "IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();IR_Init();LCD_ShowString(1,1,"ADDR  CMD  NUM");LCD_ShowString(2,1,"00    00   000");while(1){if(IR_GetDataFlag() || IR_GetRepeatFlag())  //可实现连加连减功能{Address=IR_GetAddress();Command=IR_GetCommand();LCD_ShowHexNum(2,1,Address,2);LCD_ShowHexNum(2,7,Command,2);if(Command==IR_VOL_MINUS){Num--;}if(Command==IR_VOL_ADD){Num++;}LCD_ShowNum(2,12,Num,3);}}
}

2.红外遥控控制电机调速

①:改造电机调速的文件
②:因为按键和红外遥控都用了定时器0,因此我们先把原本按键的定时器0改为定时器1

main函数部分做对应调整

③:Motor模块封装

④:加入红外模块,改造main函数

相关文章:

单片机学习笔记——入门51单片机

一、单片机基础介绍 1.何为单片机 单片机&#xff0c;英文Micro Controller Unit&#xff0c;简称MCU 。内部集成了中央处理器CPU、随机存储器ROM、只读存储器RAM、定时器/计算器、中断系统和IO口等一系列电脑的常用硬件功能 单片机的任务是信息采集&#xff08;依靠传感器&a…...

Docker Run使用方法及参数详细说明

Docker Run使用方法及参数详细说明 基本语法常用参数使用示例总结Docker Run是Docker中最基本的命令之一,用于创建并启动一个新的容器。通过Docker Run,用户可以基于指定的镜像创建一个容器实例,并且可以配置容器的各种参数,如网络设置、存储选项等。下面将详细介绍Docker …...

面试场景题系列:设计限流器

首先看看使用API限流器的好处。 •预防由拒绝服务攻击(Denial of Service&#xff0c;DoS)引起的资源耗尽问题。大型科技公司发布的所有API几乎都强制执行某种形式的限流操作。例如&#xff0c;推特限制每个用户每3小时最多发300条推文。谷歌文档API的默认限制是每个用户每60秒…...

【蓝桥杯——物联网设计与开发】拓展模块3 - 温度传感器模块

目录 一、温度传感器模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;STS30-DIS-B &#x1f319;引脚分配 &#x1f319;通信 &#x1f319;时钟拉伸&#xff08;Clock Stretching&#xff09; &#x1f319;单次触发模式 &#x1f319;温度数据转…...

网狐旗舰版源码搭建概览

简单的列一下&#xff1a; 服务端源码内核源码移动端源码核心移动端源码AI控制工具源码多款子游戏源码前端、管理后台、代理网站源码数据库自建脚本UI工程源码配置工具及二次开发帮助文档 编译环境要求 VS2015 和 Cocos3.10 环境&#xff0c;支持移动端 Android 一键编译&am…...

vue3中使用vuedraggable实现拖拽

包安装方式 yarn add vuedraggablenext npm i -S vuedraggablenext属性说明 如果下面的属性说明未能完全看明&#xff0c;可以看左边的对应的菜单查看详细说明和例子。 完整例子 <template><div class"itxst"><div><draggable:list"s…...

leetcode 7. 整数反转

class Solution { public: int reverse(int x) { long long n0; if(x0) return 0; while(x%100) { xx/10; } while(x!0) { nn*10x%10; xx/10; } if(n<-2147483648||n>2147483647) return 0; return n; } };...

Nginx单向链表 ngx_list_t

目录 基本概述 数据结构 接口描述 具体实现 ngx_list_create ngx_list_init ngx_list_push 使用案例 整理自 nginx 1.9.2 源码 和 《深入理解 Nginx&#xff1a;模块开发与架构解析》 基本概述 Nginx 中的 ngx_list_t 是一个单向链表容器&#xff0c;链表中的每一个节…...

go语言中的字符串详解

目录 字符串的基本特点 1.字符串的不可变性 2.其他基本特点 字符串基本操作 1. 创建字符串 2. 获取字符串长度 3. 字符串拼接 4. 遍历字符串 5. 字符串比较 字符串常用函数 1. 判断子串 2. 查找与索引 3. 字符串替换 4. 分割与连接 5. 修剪字符串 6. 大小写转换…...

Windows脚本清理C盘缓存

方法一&#xff1a;使用power文件.ps1的文件 脚本功能 清理临时文件夹&#xff1a; 当前用户的临时文件夹&#xff08;%Temp%&#xff09;。系统临时文件夹&#xff08;C:\Windows\Temp&#xff09;。 清理 Windows 更新缓存&#xff1a; 删除 Windows 更新下载缓存&#xff0…...

分布式协同 - 分布式事务_2PC 3PC解决方案

文章目录 导图Pre2PC&#xff08;Two-Phase Commit&#xff09;协议准备阶段提交阶段情况 1&#xff1a;只要有一个事务参与者反馈未就绪&#xff08;no ready&#xff09;&#xff0c;事务协调者就会回滚事务情况 2&#xff1a;当所有事务参与者均反馈就绪&#xff08;ready&a…...

永磁同步电机负载估计算法--自适应扩张状态观测器

一、 原理介绍 在线性扩张观测器中&#xff0c;LESO观测器增益ω0 决定了观测器的跟踪速度&#xff0c;ω0 越大&#xff0c;观测器估计精度越高&#xff0c; 抗干扰能力越强&#xff0c;瞬态响应速度加快&#xff0c;过大则会引入高频噪声使系统不稳定。为使观测器在全速域内…...

【HarmonyOS应用开发——ArkTS语言】购物商城的实现【合集】

目录 &#x1f60b;环境配置&#xff1a;华为HarmonyOS开发者 &#x1f4fa;演示效果&#xff1a; &#x1f4d6;实验步骤及方法&#xff1a; 1. 在src/main/ets文件中创建components文件夹并在其中创建Home.ets和HomeProduct.ets文件。​ 2. 在Home.ets文件中定义 Home 组…...

Python二维码生成器qrcode库

要在Python中生成二维码&#xff0c;你可以使用 qrcode 库。这个库非常方便&#xff0c;允许你生成并保存二维码图像。下面是一个简单的示例&#xff0c;展示了如何使用 qrcode 库生成二维码。 首先&#xff0c;你需要安装 qrcode 库。你可以使用 pip 来安装它&#xff1a; s…...

Python:模拟(包含例题:饮料换购 图像模糊 螺旋矩阵)

模拟题&#xff1a;直接按照题目含义模拟即可&#xff0c;一般不涉及算法 注意&#xff1a; 1.读懂题&#xff1a;理清楚题目流程 2.代码和步骤一一对应&#xff1a;变量名&#xff0c;函数名&#xff0c;函数功能 3.提取重复的部分&#xff0c;写成对应的函数&#xff08;…...

git分支与部署环境的关系以及开发规范

一 某金融机构 1.1 分支分类以及作用 1.master master分支为主分支,用于部署生产环境的分支,无论任何时候都要确保master分支的稳定性;master分支由feature及hotfix分支合并,任何时间都不能直接修改代码。目前用于老仿真和老生产,暂时不动。 2.prod 主分支,是master…...

2024最新鸿蒙开发面试题合集(一)-HarmonyOS NEXT Release(API 12 Release)

1. HarmonyOS应用打包后的文件扩展名是? 打包后的文件扩展名为.hap&#xff08;HarmonyOS Ability Package&#xff09;&#xff0c;这是HarmonyOS应用的标准包格式 2. 页面和自定义组件生命周期有哪些? 页面和自定义组件生命周期说明 有Entry装饰器的component组件的生命…...

【mybatis】详解 # 和 $ 的区别,两者分别适用于哪种场景,使用 $ 不当会造成什么影响

# 和 $ 的区别 在MyBatis中&#xff0c;# 和 $ 是用来处理参数的两种不同方式&#xff0c;它们之间有一些重要的区别&#xff1a; # 符号&#xff1a; # 是用来进行参数占位符的&#xff0c;它会进行 SQL 注入防护。使用 # 时&#xff0c;MyBatis 会将参数值进行预处理&…...

Java面试题,数据结构,图的最短路径算法应用于社交网络分析

图的最短路径算法应用于社交网络分析 在一个大型社交网络中&#xff0c;用户想要找到连接两个特定用户的最短路径。假设你已经有了这个社交网络的数据模型&#xff0c;其中节点代表用户&#xff0c;边代表用户之间的关系。请设计一个解决方案&#xff0c;以找出两个用户之间的…...

Tree数据处理

文章目录 一、Tree数据重置二、Tree拆分成二级数据1、过滤数据2、二级数据 Tree组件的数据处理往往需要使用递归&#xff0c;本文归纳一下常见的数据处理情景&#xff0c;持续更新&#xff1b; 一、Tree数据重置 递归的标志就是寻找子元素的集合字段&#xff0c;一般为children…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]

报错信息&#xff1a;libc.so.6: cannot open shared object file: No such file or directory&#xff1a; #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

SOC-ESP32S3部分:30-I2S音频-麦克风扬声器驱动

飞书文档https://x509p6c8to.feishu.cn/wiki/SKZzwIRH3i7lsckUOlzcuJsdnVf I2S简介 I2S&#xff08;Inter-Integrated Circuit Sound&#xff09;是一种用于传输数字音频数据的通信协议&#xff0c;广泛应用于音频设备中。 ESP32-S3 包含 2 个 I2S 外设&#xff0c;通过配置…...

解密鸿蒙系统的隐私护城河:从权限动态管控到生物数据加密的全链路防护

摘要 本文以健康管理应用为例&#xff0c;展示鸿蒙系统如何通过细粒度权限控制、动态权限授予、数据隔离和加密存储四大核心机制&#xff0c;实现复杂场景下的用户隐私保护。我们将通过完整的权限请求流程和敏感数据处理代码&#xff0c;演示鸿蒙系统如何平衡功能需求与隐私安…...