51单片机学习原理笔记

918 阅读15分钟

一、单片机cpu和各部件的原理及其控制

1.单片机的介绍

  • 单片机的广义介绍 QQ图片20220221152248.png

  • stc89c52狭义介绍单片机介绍 QQ图片20220221152244.png

  • stc89c52单片机的结构图,了解其内资源的功能与关系 QQ图片20220221152235.png

  • 所有单片机最小系统工作由 晶振+电源+单片机+(复位电路)组成,只有这样单片机才能工作 QQ图片20220221152230.png

2.单片机与其他外设的关系

  • 0& 单片机里的外设,其内外设连接在其内部的总线上,且让其工作则直接有这#include <REGX52.H>里面的所定义好的寄存器,配置就行,是不需要接在外部单片机所引出的引脚上
  • 1& 单片机之外的外设,首先明白单片机与现在我所用的单片机开发板的区别就行

3.不同的芯片区别点在哪里,主要分为如下

  • 0&其内部资源的不同,代表功能越丰富,更强大,可以实现很多复杂程序
  • 1&其引出的引脚数量上的不同,数量越多,其扩展的东西,功能就越多
  • 2&ROM和RAM的不同,就可以以32位进行处理数据

3.学习要求

学会了单片机实现功能的原理,外设结构和原理,通讯结构和原理,如何转化编程来实现问题,学会看数据手册了解功能及原理,掌握一些电路知识和计算机基础

手中单片机开发板其实就是,CPU+通讯+外设

  • 0&cpu学习就是里面的结构学习+配置io口寄存器+单片机的编程

  • 1&通讯学习,就是学习几种通讯方式+通讯的原理+如何转化编程实现

  • 2&外设学习,就是了解其内部结构+可以用的资源功能+实现原理

三者息息相关,懂了结构,懂了原理,才能用合适的编程算法去实现

一、编程原理

1.寄存器也就相当于内存条(但寄存器是存储0和1);

1.我们进行编程都是对于单片机上的寄存器实行赋值的,进而来控制我们的电压大小。当我们编程完毕后,下载到单片机的CPU上,CPU就会识别寄存器上的0或者1(这个识别过程很复杂,不讨论),来控制相应的脚线的电压传输,从而达到外设硬件有电压差,进而产生电流,工作。

1,控制高电压,0,控制低电压

二、LED灯

1、其原理图

根据图中原理图,知寄存器中P2_赋值实现导电,发光 屏幕截图 2022-01-02 180133.png

2、如何编程使LED发光的

根据左端都连接vcc,则哪一位赋值0,则就发光,赋1,就不发光(位寻址可整体赋值,也可单独赋值)

3、LED灯闪烁的延时问题

三、独立按键

1、位运算符

2、练手三种独立按键

四、数码管

1、原理

  • 单个数码管 存在两种类型,38脚线共阳极,38脚线共阴极;(由二极管正向导电原理易得)

屏幕截图 2021-12-22 212537.png 所以根据有两类数码管,则在编程中对于单片机P2_2(3/4)寄存器(连接74HC138译码器上的I/O口)和单片机上P2寄存器(连接74HC245),将会有不一样的赋值。

  • 如何控制3.8脚线上的电压(共同) 首先明白,P2(3/4)口当被赋不同的值时,输出到ABC的电压不同,而ABC收到不同的电压会对相应右侧的Y控制(控制其输入高低电压)。

1.如何控制右侧Y的单脚线
看原理图,我们现实认为的第一个数码管,连接的是LED8,而LED8的脚线连接在Y7上(所以我就匪夷所思,商家的脑子....)
规则:以第2个数码管为例(现实第2个),则控制Y6,6则就对应二进制110,而P2(3/4)口,我们需要从高到低(事实上,对于所有的寄存器二进制排序均为高位到低位),则P2_4=1,P2_3=1,P2_2=0;,

屏幕截图 2021-12-22 214027.png

  • 如何控制二极管上的电压(单个) 1.74HC245相当于一个过渡,可以有电压(电流)放大器的功能,更好实现LED发光的稳定性
    2.由于我们这套为共阴极,所以给LED赋值1才会发光 假如我们想产生 数字6,则6对应的是acdefg发光,则连接acdfg的脚线,所对应连接的P2_寄存器赋值1即可,所以二进制为10111110(abcdefg(dp)的顺序),而我们对于这种共寄存器规则,即我们要从高位起进行赋值,则二进制对应0111((dp)gfe) 1101(dcba),所以只需赋值P2=0x7D

屏幕截图 2021-12-22 195947.png

1、静态数码管

2、动态数码管

五、串口

1.介绍

屏幕截图 2022-02-23 201058.png

硬件电路和引脚定义

QQ图片20220223201854.png

QQ图片20220223201858.png

内部结构和功能和原理

QQ图片20220223201925.png

QQ图片20220223201931.png

需要配置的相关寄存器

image.png

时序,数据帧(这个由于串口的硬件电路集成实现了,所以不需要管)

波特率的理解

1、是两者约定时间收发数据的保证 2、波特率配置就是利用定时器,来计算时间发送,然后另一个设备也用相同的时间接收,就可以达到目的了,这其实和那个红外线接收原理差不多

image.png

五、定时器

1.单片机里的定时器资源

2.定时器T0(T1)介绍

四种模式

屏幕截图 2022-01-01 181004.png 由控制寄存器来选择模式,我们常用16位模式,即模式一

三部分功能组成定时器
  • 工作原理及组成部分 屏幕截图 2022-01-01 182038.png

  • 对中断系统的理解

屏幕截图 2022-01-01 170416.png

3.定时器里面的寄存器

由于我们需要软件编程对硬件实行控制,那么必然是通过配置寄存器这一媒介。
1.定时器中的寄存器分两类:定时器/计数器里面0/1的相关寄存器 和 中断系统中的相关寄存器 2.其里面又有多个寄存器组成来共同实现想要功能

屏幕截图 2022-01-01 180243.png

定时器/计数器里面0/1的相关寄存器
  • 控制寄存器 其里面分为这几个寄存器 内部中断定时器TF(溢出标志位,由硬件管理),TR(为定时器控制位,置1启动),外部中断IE(请求中断源,由硬件管理),IT类型(进入中断的方式选择位)

屏幕截图 2022-01-01 180401.png

其各类存储器里的功能

image.png

屏幕截图 2022-01-01 180522.png

其寄存器在硬件中的大概位置

屏幕截图 2022-01-01 180954.png

  • 模式寄存器 主要有M(M0,M1计数模式选择,下面有讲解,且一般用16位),GATE,C/T类

image.png

不可寻址表示无法单个赋值,只能整体赋值
且高位为定时器1,低位为定时器0

所以其单独使用一个定时器时:
    定时器0:TMOD=0x01//即00000001;
    定时器1:TMOD=0x10//即00010000;
当同时使用两个定时器时
    定时器0:TMOD&=0xF0;//低位清零,高位不变
            TMOD|=0x01;//最低位置1,高位不变
            则最后低位无论如何就会变为0001,而不影响定时器2了

其各类型寄存器功能如下 屏幕截图 2022-01-01 180842.png 屏幕截图 2022-01-01 180739.png

  • 其他的寄存器
中断系统中的相关寄存器

屏幕截图 2022-01-01 181325.png

4.定时器和定时器中断和UART和外部中断的配置寄存器总结

六、点阵屏


点阵屏的介绍

QQ图片20220123153131.jpg

点阵屏的显示原理

QQ图片20220123153137.jpg

  • 也是根据二极管的导通原理来亮和熄灭,逐列或逐行进行扫描

74H595

QQ图片20220123153140.jpg

QQ图片20220123153217.png

  • 易知共阳极的寄存器由我们的74HC595的串转并输入数据
  • 编程配置时,则就只需对我们的P0口和P3_5(->RCLK),P3_6(SRCLK),P3_4(SER)口进行操作。P0_0置0,D7置1,则会亮
  • 74HC595的取数据
       for(i=0;i<8;i++)//获取数据,然后使每列得到数据
	{
		SER=Bety&(0x80>>i);//一位一位进行取,从*高位*开始取
		SCK=1;//每次置1,数据下降
		SCK=0;
	}
	
	RCK=1;//当8位全部置满后,置1并行输出给DP
	RCK=0;

整个的实现过程

  • 通过编程配置P0口和P3_5(->RCLK),P3_6(SRCLK),P3_4(SER)口进行操作,这个可以得到每列(每行)有哪几个会发光,然后进行每列每列的进行扫描,只要速度够快,则可以使其全部发光。

  • 编程分为:

      1、主函数:主要实现对哪一列,列中的发光位置进行选择,
                 调用74HC595函数时(哪一列,列的发光数据),然后循环逐列扫描即可,
      2、74HC595模块:主要实现每列的发光
    

七、DS1302时钟芯片


1、为什么要用芯片

  • 因为之前用代码,定时器弄得时钟精度不高,且不易实现调节功能,而该芯片精度十分高,可易调节

2、时钟芯片操作原理:

  • 通过写相应的代码,来对芯片里的寄存器进行操作,然后芯片里的功能是实现1s高精度累加,达到实现可调时钟

3、原理

芯片

  • 引脚图和电路

QQ图片20220123115544.jpg

  • 芯片内部结构图 QQ图片20220123115605.png

  • 内部时钟寄存器

QQ图片20220123115609.png

  • CE SCLK IO将数据所对应的对芯片进行操作的原理

屏幕截图 2021-12-03 132113.png

  • BCD码

QQ图片20220123115616.png

芯片与CPU连接部分

image.png

4、实际中我们真正实现的过程

  • 首先我们编程对CPU寄存器P3_5(->CE),P3_4(->IO),P3_6(->SCLK)进行编程操作,来发送相应指令和数据给时钟芯片,然后时钟芯片接受命令和数据来对自身的寄存器进行操作,改变其里面的值(内置功能即为寄存器的值1s累加)。然后我们将这里面数据取出来,取出来这也是通过CE,IO,SCLk操作进行取出然后将其数据显示在LCD上即可。

蜂鸣器

乐理知识(识谱-简谱)

  • 音高

      1.数字上加一点,表示升高一个8度。数字上下一点,表示下降一个8度,,两点,则下降两个8度
      2.#,升半音,b,降半音
      
      
      3.钢琴中,每两个键之间差半音
      4.钢琴中一组之间有12个音高,即7个白键,5个黑键,单片机中只需知道有三组即可,低,中,高即可
      5.简谱中的数字都是白键,黑键只能用#,b加数字表示
     
    
  • 每个音高时长

      分为全音符,半音符,四分音符,8分音符,16分音符,32分音符的时长:
      每个乐谱的基准音高不同速度也不同,,所以无法直接判断各个音高的时长,但其上述音节的
      时长是以上述从左到右依次以倍递减的
      
      1.数字左边加-,表示延长四分音符的时值
      2.再下边-,--表示该基准的音节时长以倍(几倍是横杠的数量)下降时值
      3.附点 *,表示再加上该基准的音节时值的一半
      4,延音线,是同个音节的连接,本质就是分开了音节,使得谱子更加简明,读懂
    

QQ图片20220127170810.png

  • 谱中 1=D 4/4
    ♪= 120

含义:该乐谱1=D表示D调,4/4表示以四分音符为为基准,每小节有四拍,一拍的时长为四分音符的时长,♪=120表示每分钟120拍,即一拍时长500ms,则就是基准音符的时长。
所以简谱中的单纯数字都是为中音,时长为基准音符的时长,其他在数字上进行变化就是以上面进行变化即可

00e93901213fb80ef75da66136d12f2eb83894fc.jpg

蜂鸣器如何产生音乐

  • 原理:

      首先问题:想要蜂鸣器发出音乐的节奏和声音
      ->则音乐由 音高 和 每个音高时长 和 节奏 组成
      ->声音的音高由其震动频率决定。音高的时长就是其这个音高所要持续的时间。
      节奏就是哪时候会停顿(音乐产生的原理)
      ->如何用单片机进行实现,由于音高是频率,而蜂鸣器就是以电流导通的周期
      可以产生不同频率的声音,发声时长我们也可以进行操作,
      ->然后想要蜂鸣器产生不同频率的声音,则我们就是要根据每个不同的音高对
      电流导通的周期进行计算,而发声时间我们可以用定时器和延时函数来组合进行
      ->电流导通蜂鸣器周期是一个个电流波段组成,则我们只需对P2_5进行特定时
      间内翻转就可得到特定的音高
      ->根据音高的频率得到一系列的音高的电流周期(P2_5翻转的时间)之后,则
      我们根据音乐音播放时音高出现的顺序来进行排列使得根据顺序依次发声,每个
      音高发声的时长也要确定。则就得到了音乐了
      
      总言:音乐->音高和时长->频率->周期->蜂鸣器的电流波段->P2_5的翻转周期->编程
      
    
  • 蜂鸣器原理图 image.png (配置的地方也就是BEEP,经过五四步进电机的芯片处理 ,最终对应CPU的寄存器P2^5,即对P2^5进行操作即可)

  • P2_5的翻转周期计算过程及思路

QQ图片20220127170834.jpg QQ图片20220127170838.jpg

温度显示DS18B20芯片


原理

通过串口通讯(单总线)来读取DS18B20中的温度数据,然后得到的数据显示再LCD上即可

  • 引出的问题

      1.了解单总线如何进行通讯及电路规范问题
      2.了解DS18B20的工作原理和其中的功能
      3.了解DS18B20与单总线与主机之间的交流
      4.了解其内涉及到的相关寄存器
      
    

DS18B20

  • 介绍

QQ图片20220213171814.png

  • DS18B20与单总线和CPU之间的引脚连接,清楚知道编程时配置的寄存器

QQ图片20220213171843.png

  • DS18B20的内部结构

QQ图片20220213171925.png 如图主要是三大块区域,然后通过图片就明白了我们(CPU)通过单总线先要找到DS18B20,则64——BItRom就存着该设备的密令一样,当主机发送一段数据通过规则与密令对应上,就知道是DS18B20了,然后CPU就可以通过单总线与其中的暂存器进行数据交互了,这就是大概的过程了

  • DS18B20中的存储器

QQ图片20220213171929.png

   解释: Byte 0-1为温度数据
              2-3为越阀值
              4为精度
              5-7是空白的,可以自己写入其他数据,但作用不大

这些寄存器都是与主机进行交互数据的真正地方
我们现在只需要温度数据即可,则我们又可以知道只需把前两个字节给读取出来,然后根据其规则转化为阿拉伯数字,再显现到LCD上即可
所以现在大致了解了DS18B20情况,则我们就继续了解单总线的原理即可

单总线

  • 单总线的电路规范 QQ图片20220213171938.png 开漏输出模式作用:达到总线上可以挂多个设备,使得通讯时互不干扰

  • 时序部分 开始时序,发送/接收一位的时序,发送/接收一个字节的时序。(由于我们使用DS18B20的功能单一其中只有发送指令的,接收数据,所以不需要指令模块,数据模块分开,一起发送/接收一个字节的时序,区别于LCD1602的原理)

QQ图片20220213171942.png

QQ图片20220213171953.png

QQ图片20220213171947.png

QQ图片20220213171957.png

DS18B20的数据帧

  • 了解温度是如何转换并存储在寄存器中的规则 QQ图片20220213204756.png
        //获取数据
        LSB=OneWire_RecieveByte(); 
	MSB=OneWire_RecieveByte();
        //转换阿拉伯数字
	Temp=(MSB<<8)|LSB;	//拼接,最终得到的前四位为符号位,后四位为小数位
        Temperture=Temp/16.0;	//使后四位变成小数部分 Temperture为浮点型,
                                //想一下为啥这样 就可以把符号,整数,小数给分开了
  • DS28B20的一些指令及地址 QQ图片20220213172000.png

  • DS18B20的数据帧 QQ图片20220213204500.png

代码

  • DS18B20部分
#include <REGX52.H>
#include "Delay.h"
#include "OneWire.h"
#include "LCD1602.h"
void DS18B20_ConverT(void)
{
	OneWire_Init();	//单总线的开始
	//指令
	OneWire_SendByte(0xCC);	//跳过大门,直接通讯,设备一个的情况下
	OneWire_SendByte(0x44);	//进行温度转换
	//Delay(1000);
}

float DS18B20_ReadT()
{
	int Temp;//有符号的两个字节
	float Temperture;
	unsigned char LSB,MSB;
	
	OneWire_Init();
	//指令
	OneWire_SendByte(0xCC);//跳过大门
	OneWire_SendByte(0xBE);//读取指令

	//数据,读取DS18B20的规则,连续读取其每个寄存器,第一次读为Byte0,第二次为Byte1...
	LSB=OneWire_RecieveByte(); 
	MSB=OneWire_RecieveByte();

	Temp=(MSB<<8)|LSB;	//拼接,最终得到的前四位为符号位,后四位为小数位
	Temperture=Temp/16.0;	//使后四位变成小数部分
	
	return Temperture;
}
  • 单总线
#include <REGX52.H>
sbit OneWire_DS=P3^7;
#include "Delay.h"
bit OneWire_Init(void)
{
	unsigned char i=0;
	unsigned char AckOne;
	OneWire_DS=1;
	
	OneWire_DS=0;
	i = 227;while (--i);		//Delay 500us,us的特殊延时方法,不是非常的准确,大概的
	OneWire_DS=1;
	i = 29;while (--i);		//Delay 70us
	AckOne=OneWire_DS;	//响应接收
	i = 227;while (--i);		//Delay 500us
	return AckOne;
}

void OneWire_SendBit(bit Bit)
{
	unsigned char i=0;
	OneWire_DS=1;
	
	//发送0或1的特殊方法,绝,节约if语句
	OneWire_DS=0;
	i = 4;while (--i);		//Delay 10us
	OneWire_DS=Bit;
	i = 22;while (--i);		//Delay 50us
	OneWire_DS=1;//
	
}

bit OneWire_RecieveBit(void)
{
	bit Bit=0;
	unsigned char i=0;
	OneWire_DS=1;
	
	OneWire_DS=0;
	i = 2;while (--i);		//Delay 5us
	OneWire_DS=1;
	i = 2;while (--i);		//Delay 5us
	Bit=OneWire_DS;		
	i = 22;while (--i);		//Delay 50us
	
	return Bit;
}

void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i=0;
	for(i=0;i<8;i++)
	{
		OneWire_SendBit(Byte&(0x01<<i));		//从最低位开始发送
	}
}

unsigned char OneWire_RecieveByte(void)
{
	unsigned char i=0,Byte=0x00;
	for(i=0;i<8;i++)
	{
		if(OneWire_RecieveBit()){Byte|=(0x01<<i);}	//从最低位开始接收
	}
	return Byte;

LCD1602显示原理