实验室考核复习(一)----51单片机(基础模块)

0x00 前言

  6月份实验室考核,考核的内容我也不知道(估计是 51,c,加点电分,或者数据结构?不知道),虽然是一些入门的东西,不过为了万无一失(谁也不敢说会不会出一些犄角旮旯的东西),还是从头捋一遍。(菜鸡瑟瑟发抖),先51看一下吧。我就拿

普中-51-A3的举例了

本文全当博主的复习,主要是结合 小蜜蜂51普中51

0x01 最小系统板:

1.电源电路 2.复位电路 3.时钟电路 4.下载电路

MCU

 

4个广角,P0 P1 P2 P3 对应就行。

复位

RST 网络标号  跟上述单片机的9脚相连,

1)当按键按下后,电源会经过按键,接入RST引脚进行复位(51单片机是进行高电频复位)

2)不按的化,通过R与电容组成的RC充放电电路,进行复位

晶振电路

 

可以看出来是采用12兆晶振,两边c12 c13电容,接在单片机的18 19 脚。

电源电路 && 下载电路

通过下面的usb接口,接入电源,经过滤波电容进行滤波(图中红框处),紧接这连接D5V的开关,送到VCC,之后各部分才有电,当没有按下开关时,这个DIN5VS(5伏)只是和 CH340 这个芯片来识别串口,并没有供电

P5短接板

CH340用的也是12兆晶振

下载时就利用RTS 和DTR高低电频的变化,进行下载复位(STM就需要人为了)

注意:CH340的位置一定要接地,不然会发烫。

0x02 LED

1.定义:LED,即发光二极管,是一种半导体固体发光器件。(写上吧,万一考呢)

2.LED的工作原理。           LED的符号为:      LED的工作是有方向性的,只有当正级接到LED阳极,负极接到LED的阴极的时候才能工作,如果反接LED是不能正常工作的。

3.原理图

正入负出,所以阳极都接到了VCC(高电平)上,阴极串联一个电阻接到了P2口,所以点亮的话把对应的P2口拉低就行。

流水:

#include <REGX51.H>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;


void delay(u16 i)
{
	while(i--);//ͨ¹ýËÀÑ­»·Õ¼ÓÃcpuÔËËãʱ¼äÀ´ÑÓʱ
}
		
void LED_WATER()
{
	int i;
	
	for (i = 0 ; i < 7; i++)
	{
		P2 = ~(0x01 << i);
		delay(25000);
	}

	for (i = 0 ; i < 7; i++)
	{
		P2 = ~(0x80 >> i);
		delay(25000);
	}
}


void main()
{
	P2 = ~(0x01);
	delay(25000);
	while(1)
	{
		LED_WATER();
	}
}

(下面的代码只写关键部分)

0x03 蜂鸣器

有电路板的是无源蜂鸣器,没有电路板的是有缘蜂鸣器(用黑胶封闭)

有源:在IO里输出一个电平就行         无源:电平 + 一定频率脉冲

电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。     接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。     接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。     多谐振荡器由晶体管或集成电路构成,当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。

 声音

改变单片机引脚输出波形的频率,就可以调整控制蜂鸣器音调,产生各种不同音色、音调的声音。

大小

改变输出电平的高低电平占空比,则可以控制蜂鸣器的声音大小。、

原理图

 

可以看到蜂鸣器BEEP接到了ULN2003D上,对应的是P2^5

ULN2003

放大电路,放大驱动电流

(下面是套话)

ULN2003 是高耐压、大电流达林顿陈列,由七个硅NPN 达林顿管组成。 ULN2003是大电流驱动阵列,多用於单片机、智能仪表、PLC、数字量输出卡等控制电路中。可直接驱动蜂鸣器、继电器等负载 。

代码

sbit bee = P2 ^ 5;  //因为是无源,所以要  脉冲+电平

void main()
{
    bee = ~bee;  //产生脉冲
    delay(10);
}

 

0x04 数码管

(因为是复习,就不分静态和动态了)

显示器&&接口

LED显示器有两种:段显示(7段,米字型等)和点阵显示

LED数码管根据LED的不同接法可分为2类:共阴和共阳。

(A3里没有单个的,这是别人的图)

共阴就是阴极接地,所以要是亮就得输入高电平

共阳就是阳极接vcc,所以要是亮就得输入低电平

共阳极数码管编码表:
unsigned char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
共阴极数码管编码表:
unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

原理图:

引脚对应着 P0,看一眼P0口:

共阳,低电平有效

注意:P0口是露底开路的,如果不加上拉电阻(VCC)的话,对P0无法进行输入输出的控制。

使能

锁存器:74HC245 (一般是74HC573,这个普中A3的板子有点神奇)

简单地说锁存器就是一个缓存器,它能保存上一次的状态,自带使能端口,清零端口。当使能端有效时,则左右两端导通,否则断开。

74HC245:

 

 

 

7HC573 :通常配合或非门(74HC02)使用

138译码器

74HC138 简单地说138译码器将一个特殊的编码翻译成一个状态。

代码:(因为普中这个板子,138译码器,接的是P2^2,P2^3,P2^4,有些麻烦,为了直观代码如下)

sbit lsa=P2^2;
sbit lsb=P2^3;
sbit lsc=P2^4;

void wei_poc(u8 poc)
{
    switch(poc)
		{
			case 0:
				lsa=1;lsb=1;lsc=1;break;
                        case 1:
				lsa=0;lsb=1;lsc=1;break;
			case 2:
				lsa=1;lsb=0;lsc=1;break;
                        case 3:
				lsa=0;lsb=0;lsc=1;break;
                        case 4:
				lsa=1;lsb=1;lsc=0;break;
                        case 5:
				lsa=0;lsb=1;lsc=0;break;
			case 6:
				lsa=1;lsb=0;lsc=0;break;
			case 7:
				lsa=0;lsb=0;lsc=0;break;
		}

}

在蓝桥杯里有方便的写法。

 

动态数码管

动态显示的特点是将所有数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。

说白了就是利用视觉残留,让多个静态数码管循环亮起。

代码

u8 code DUANXUAN[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8.
void SMC_Bit(u8 dat, u8 poc)
{
    P0 = ~DUANXUAN[dat];//段
    wei_poc(poc);//位
}

void SMC_Display()
{
    SMC_Bit(1,0);
    delay(500);
    SMC_Bit(0,0);//消影
    
    SMC_Bit(2,1);
    delay(500);
    SMC_Bit(0,1);//消影
    
    SMC_Bit(3,2);
    delay(500);
    SMC_Bit(0,2);//消影
    
    SMC_Bit(4,3);
    delay(500);
    SMC_Bit(0,3);//消影
   
    SMC_Bit(5,4);
    delay(500);
    SMC_Bit(0,4);//消影
    
    SMC_Bit(6,5);
    delay(500);
    SMC_Bit(0,5);//消影
    
    SMC_Bit(7,6);
    delay(500);
    SMC_Bit(0,6);//消影
    
    SMC_Bit(8,7);
    delay(500);
    SMC_Bit(0,7);//消影
}

(代码要结合前文,注意一下自己的是共阴还是共阳)

 

0x05 独立按键

按键的两个引脚,一端通过电阻上拉到高电平,另一端接地。

没有按键按下时,输入引脚为高电平。

有按键按下时,输入引脚为低电平。

扫描:通过反复读取按键输入引脚的信号,然后识别高低电平来判断是否有按键触发。

去抖动

(别人的图)

首次检测到输入引脚有低电平后,稍做延时,再次读取该引脚,如果确实是低电平,则触发,否则就是干扰信号。

原理图:

代码:

-------------------------------------
按键按下,L1灯亮;
按键松开,L1灯灭;
-------------------------------------
sbit K1 P3^1;
sbit L1 P2^0;

void ScanKeys_Alone()
{
    if (K1 == 0)
    {
        delay(100);
        if(K1 == 0)
        {
            L1 = 0;          //按键按下,L1灯亮
            while(K1 == 0);  //分界线
            L1 = 1;          //按键松开,L1灯灭
        }
    }
}

要注意,按下和松开的位置。

 

0x06 矩阵按键

小蜜蜂老师这篇写得很仔细:https://www.cnblogs.com/ALittleBee/p/8411771.html

下面是我摘抄的一些:

与独立按键不同的是,按键的两个引脚都分别连接的单片机的I/O端口,一个作为行信号,另外一个作为列信号。我们以4X4的矩阵键盘为例,试着探讨其工作方式和扫描思路。

 

在上面的矩阵键盘中,要识别出黄色按键的按下状态,应该怎么做呢?
    对与矩阵键盘,我们只能逐行扫描,然后读取列的状态信号。如果R3行输出低电平,那么黄色按键如果有按下动作的话,那读取C2列信号也应该为低电平,而该行上其他没有按下动作的按键的列信号则为高电平。因此,我们可以得到矩阵键盘的基本扫描步骤:
    <1> R1输出点电平,R2、R3、R4输出高电平,逐个读取判断列信号,如果都为高电平则R1行上没有按键按下。
    <2> R2输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
    <3> R3输出点电平,R1、R2、R4输出高电平,发现C2列信号为低电平,那么可以判断得R3行的C2列的按键有按下动作。
    <4> R4输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
    如此循环往复,扫描的按键的状态。
    我们知道有按键按下动作,那么又怎么知道是哪一个按键按下呢?这时,我们最好定义一个键值全局变量,给矩阵行列上的每一个的按键编一个唯一的号码。当扫描的某一行某一列的按键动作后,把对应的编号复制给键值变量,这样我们判断这个键值,就知道是那个按键有触发动作了。

代码:

原理图:

sbit R1 = P1^7;
sbit R2 = P1^6;
sbit R3 = P1^5;
sbit R4 = P1^4;

sbit C1 = P1^3;
sbit C2 = P1^2;
sbit C3 = P1^1;
sbit C4 = P1^0;

void ScanKeys()
{
        keyNum = 16;//黑屏
        R1 = 0;
        R2 = R3 = R4 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 0;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 1;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 2;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 3;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        
        R2 = 0;
        R1 = R3 = R4 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 4;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 5;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 6;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 7;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        
        R3 = 0;
        R2 = R1 = R4 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 8;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 9;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 10;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 11;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        
        R4 = 0;
        R2 = R3 = R1 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 12;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 13;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 14;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 15;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
}

按键扫描有很多种写法,这是一种好理解,引脚比较灵活,但是笨笨的写法。

下面这种,需要引脚比较规则时比较方便:

void KeyDown()   
{
	io_Key=0x0f;      //行
	if(io_Key !=0x0f) //判断是否按下
	{
		delay(1000);     //去抖动
		if(io_Key !=0x0f)
		{
			io_Key =0x0f; //行
			switch(io_Key)
			{
				case 0x07:
					KeyValue=0;break;
		                case 0x0b:
					KeyValue=1;break;
	                        case 0x0d:
					KeyValue=2;break;
		                case 0x0e:
					KeyValue=3;break;
			}
		        io_Key =0xf0; //列
			switch(io_Key)
			{
				case 0x70:
					KeyValue=KeyValue;break;
		                case 0xb0:
					KeyValue=KeyValue+4;break;
	                        case 0xd0:
					KeyValue=KeyValue+8;break;
		                case 0xe0:
					KeyValue=KeyValue+12;break;
			}
			while((a<50) && io_Key!=0xf0)
			{
				delay(1000);
				a++;
			}
		}
	}
}

0X07 中断系统

参考文章https://bbs.21ic.com/icview-2477100-1-1.html(小蜜蜂老师赛高)

在执行cpu当前程序时,由于系统中出现了某种急需处理的情况,cpu暂停正在执行的程序,转而去执行另外一段特殊的程序来处理出现的紧急事务,处理结束后,CPU自动返回到原来暂停的程序中去继续执行。这种程序在执行过程中由于外界的原因而被中间打断的情况,成为中断。

图解:

引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统

中断服务函数:内核响应中断后执行的相应处理程序。
中短向量:中断服务函数的入口地址。每个中断源都对应一个固定的入口地址。当内核响应中断请求时,就会暂停当前的程序执行,然后跳转到该入口地址执行代码。

注意:有中断请求不一定能打断主程序。

 

   随着计算机技术的应用,人们发现中断技术不仅解决了快速主机与慢速I/O设备的数据传送问题,而且还具有如下优点: 分时操作。CPU可以分时为多个I/O设备服务,提高了计算机的利用率;

实时响应。CPU能够及时处理应用系统的随机事件,系统的实时性大大增强;

可靠性高。CPU具有处理设备故障及掉电等突发性事件能力,从而使系统可靠性提高。

 (以上看一眼了解一下,万一考呢,下面说正事)

中断系统

 

一般来说,51单片机有5个中断源(忽略定时/计数器2),分2个优先级,这个5个中断源按照自然优先级从高到低依次为:
    外部中断0INT0
    定时/计数器0TF0
    外部中断1INT1
    定时/计数器1TF1    
    串口中断RI/TI

(图一)

每个中断源都对应着一个固定的入口地址,也就是中断向量,它们依次是:
    0    0x0003:  INT0
    1    0x000B:  TF0
    2    0x0013:  INT1
    3    0x001B:  TF1
    4    0x0023:  RI/TI
    也就是说,不管主程序执行到什么地方,只要外部中断1产生请求,内核要响应该中断,就会到0x0013这个地址去执行代码。如果你是在使用汇编语言进行程序开发的时候,你需要记住每个中断源对应的地址;如果你使用的是C语言,你只需要记住中断源的顺序就可以了,也就是最左边的中断号

寄存器

中断相关的寄存器有4个,每个寄存器都是可以位寻址的,这该编程带来了方便。    其中2个为控制寄存器:IE寄存器IP寄存器

 

另外2个为中断请求标志:TCON寄存器SCON寄存器

代码

/////////////////////////////==中断0==///////////////
void Init_INT0()//触发方式
{
	IT0 = 1;//下降沿触发
	EX0 = 1;//中断使能打开
	EA = 1;//总中断打开
}

void ServiceINT0() interrupt 0
{
	......//终端服务函数的编写
}
///////////////////////////==中断0_end==////////////

(Init_INT0()函数结合 图一 去看)

0x08 定时/计数器

参考文章:https://bbs.21ic.com/icview-2477676-1-1.html

作为定时器时,计数信号的来源选择周期性的内部时钟脉冲;用作计数器时,计数信号的来源选择非周期性的外部输入信号

本质上都是计数器

计算:

51单片机有两个定时/计数器T0和T1,为16位加法计数器,由低8位TLx和高8位THx两个寄存器组成,最大计数值为65535个计数脉冲

原理: 每接收到一个计数脉冲,计数器就会加1,当计数值累计至全为1时(8位255,13位8191,16位65535),再输入一个计数脉冲,计数器便会溢出回零,并且计数器的溢出是TCON寄存器的TF0或TF1位置1,同时向内核提出中断请求。如果定时/计数器工作于定时模式,则表示间隔定时时间到,如果工作与计数模式,则表示计数值已满。

     假设单片机的外部晶振为12MHz,那么,经过12分频后输入计数器的计数脉冲为1MHz,即每个脉冲的周期为1us。因此定时器T0的16位工作模式最大的定时时间为65535us,65.5ms。如果要定时10ms的话,计数器就不能够从0开始计数了,必须给它一个计数初值。怎么计算这个初值呢?
    要定时10ms,则相当于计数10000个脉冲后计数器的值就到达65535了,那么开始计数的这个地方就是计数初值。
    65535 - 10000 = 55535 = 0xd8ef
    把这个计算得到的初值写入TH0和TL0寄存器即可:
    TH0 = 0xd8;或者 TH0 = (65535 - 10000) / 256;
    TL0 = 0xef; 或者  TL0 = (65535 - 10000) % 256;

当然明白了,上述文章中还有个例题,也是同样的计算方法(具体见上述文章)。

寄存器

除了除了计数初值寄存器THxTLx之外,还有TMOD寄存器和TCON寄存器

(小蜜蜂的图)

TCON:见上段落(中断)所写。

代码:

void Init_T0()//需要配置TMOD THX TLX ET0 EA TR0
{
	//TMOD: GATE = 0; c/t = 0; M1,M0 = 0x01
	TMOD = 0X01;
	//初值5ms * 100 = 0.5s
	TH0 = (65535 - 50000) / 256;//高8位
	TL0 = (65535 - 50000) % 256;//低8位
	//打开使能
	ET0 = 1;
	//总中断
	EA = 1;
	TR0 = 1;
}

void ServiceT0() interrupt 1
{
	//因为没有打开自动重装载,所以要重新配置
	TH0 = (65535 - 50000) / 256;//高8位
	TL0 = (65535 - 50000) % 256;//低8位
        ......//编写服务函数
}
	

(定时器通常与全局变量相结合来编写)

 

0x09 串口通信

串口通信的概念有很多,这里只讲述博主认为重要的(重要的意思就是感觉能考的(手动滑稽))

一些概念:

串行 && 并行:

串行通信:是将数据字节分成一位一位的形式在 一条传输线上逐个地传送。

串行通信的特点:传输线少,长距离传送时成本低,且可以利用电话网等现成的设备,但数据的传送控制比并行通信复杂。  

 

并行通信:通常是将数据字节的各位用多条数据线同时进行传送 。

并行通信的特点:并行通信控制简单、传输速度快;由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难。

 

通信种类:

在51中一般是串行,在此不谈并行,串行通信有SPI,IIC,UART,大多数,串行通信指的就是UART.

传输方向:

单工是指数据传输仅能沿一个方向,不能实现反向传输。

半双工是指数据传输可以沿两个方向,但需要分时进行。

全双工是指数据可以同时进行双向传输。

通信方式:

异步通信:通信中双方的比特率要保持一致。以字符为单位进行数据帧传输,一次一帧。

 

同步通信:需要同一个时钟,以数据块传输。

比特率:

串口每秒传输的位数。

在51中有4种模式:

模式1,3,由定时器1的溢出率决定,波特率可变

通常用模式2 因为是由定时器1的8位自动重装载产生,当TH1溢出时,自动装到TL1去。

波特率怎么算的就大致看一下把(了解为主)主要是图中后两行话

串口通信有2个缓冲寄存器SBUF,一个发送,一个接收,物理上完全独立,字节寻址(99h).

发送:自动发完之后,TI标志位置1。

SBUF = 0x00; //发送

接收:自动接收之后,RI标志位置1。

变量 = SBUF; //接收到一个变量里

SCON

(小蜜蜂的图)

记住SCON = 0x50,类似蓝桥杯的板子还需要设置AUXR,普中A3就不用了。

代码:

// sfr AUXR=0x8e;   //蓝桥杯要用            
//--------------------------------------
unsigned char tmpRecv;
void Init_Uart()
{
    TMOD=0x20;       
    TH1=0xfd;        
    TL1=0xfd;       
            
    TR1=1;           
    SCON = 0x50;     
    ES=1;             
    EA=1;             
   // AUXR &= 0x40; //蓝桥杯要用
}
/*==============发送一个字节===============*/
void SendByte(unsigned char dat)
{
    SBUF = dat;            
    while(TI == 0);       
    TI = 0;                
}
/*=============服务函数================*/
void Sevice_Uart() interrupt 4
{
    if(RI == 1)                
    {
        RI = 0;               
        tmpRecv = SBUF;//接收
        SendByte(tmpRecv + 1);//再发出去  (接收的值 + 1)
    }
}

当然这里也给出穿字符串的写法:

void Send_Byte(u8 dat)
{
	SBUF = dat;//发送
	while(TI == 0);
	TI = 0;
}

void Send_Str(u8* str)
{
	while(*str != '\0')
	{
		Send_Byte(*str++);
	}
}

 

0x0A 总结

因为篇幅的原因,51单片机的外设芯片,pwm之类的放到下一章去写,本文是博主的复习,借用了小蜜蜂和普中的一些素材。

因为是复习,所以点了一些博主觉得会考的知识点,放了一些博主用惯了的代码。如有不正确的地方,请路过的大佬斧正,希望可以帮助到各位看官,(下一篇是外设芯片篇)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章