基础知识(总)

预备知识📖

一、单片机基本常识和学习习惯

一、点亮一个IED灯

1.IED

原理图

原理

低电平灯亮

实践代码

以下代码跑马灯均接到P1口

  1. 点亮第一个灯

    #include<reg52.h>
    
    sbit D = P1^0;
    
    //点亮第一个灯
    void main()
    {
       D = 0;
    }
    
  2. 总线点亮第二个灯

    #include<reg52.h>
    
    sbit D = P1^0;
    
    //总线点亮第二个灯
    void main()
    {
      P1 = 0xFD;
    	/*
    	  D7 D6 D5 D4 D3 D2 D1 D0
    	  1   1   1    0   1   1   1   1  
    	
    	  P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
    	  1   1   1   1   1   1   0   1
      */
    }
    
  3. 依次点亮各个灯

    #include<reg52.h>
    
    #define uchar unsigned char
    #define uint unsigned int 
    
    sbit D = P1^0;
    /**
    * 0xFE 1111 1110 最低位为0,即亮最低位对应的灯
    * 0xFD 1111 1101 
    * 0xFB 1111 1011
    * 0xF7 1111 0111
    * 0xEF 1110 1111
    * 0xDF 1101 1111
    * 0xBF 1011 1111
    * 0x7F 0111 1111
    * 可以看到0从最低位移动到最高位,实现了依次点亮
    */
    uchar array[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
    //1111 11110 -->0111 1111
    uint a = 0;
    
    //依次点亮各个灯
    void main()
    {
    	int i = 0;
    	while(1)
        {		
    		for (i = 0; i<8; i++)
          {
    			a = 5100;
    			P1 = array[i];
                //sec = 0.4999s
    			while(a--);//延时
    		}
    	}
    }
    
  4. 灯闪烁

    #include<reg52.h>
    #define uchar unsigned char
    #define uint unsigned int
    sbit K10 = P1^0;
    uint a ;
    //灯闪烁
    void main()
    {
    	while(1)
       {
    		a = 50000;
    		K10 = 0;
    		while(a--);//延时
            
    		a = 50000;
    		K10 = 1;
    		while (a--);	
    	}
    }
    
  5. _crol_()函数实现流水灯的依次点亮

    • _crol_()函数在#include<intrins.h>中,函数原型是unsigned char _crol_(unsigned char c,unsigned char b),表示变量c左移b

    • #include<intrins.h>中还有

    #include<reg52.h>
    #include<intrins.h>
    
    #define uchar unsigned char
    #define uint unsigned int 
    
    uchar temp = 0xFE;//中间变量
    void delay();//函数声明
    
    //用_crol_()函数实现流水灯的依次点亮
    void main(){
    
        while(1)
        {
            P1 = temp;
            temp = _crol_(temp ,1);//中间变量左移
            delay();
        } 
    }
    
    //延时函数
    void delay()
    {
        uint x,y;
        //100 * 570
        for (x =100;  x>0; x--)
            for (y = 570;  y>0; y--);
        
    }
    

2.蜂鸣器

原理图

原理

P00 为高电平时,Q2导通,蜂鸣器响;

(有的单片机P00为低电平时,Q2导通,这取决于蜂鸣器的原理图)

实践代码

  1. 蜂鸣器伴随着流水等间断的闪

    #include<reg52.h>
    #include<intrins.h>
    
    #define uchar unsigned char
    #define uint unsigned int 
    
    //定义变量
    uchar temp = 0xFE;//中间变量
    sbit beep = P3^4;
    
    //函数声明
    void delay();
    
    //蜂鸣器伴随着流水等间断的闪
    void main()
    {
        
        while(1)
        {
            P1 = temp;//跑马灯接在P1口
            
            beep = 1;//响
            temp = _crol_(temp ,1);//中间变量左移
            delay();
            
            beep = 0;//不响
            delay();
        } 
    }
    
    //延时函数
    void delay()
    {
        uint x,y;
        //100*2000
        for (x =100;  x>0; x--)    
            for (y = 570;  y>0; y--);
    }
    

二、数码管

1.中央控制器(CPU)原理图

2.LED显示器原理图

引脚图

如果想要显示1,就得让b、c为1,所以段选码为0000 0110,即0x06;

如果想要显示2,就得让a、b、g、e、d为1,所以段选码为0101 1011,即0x5B;

其他数字同理。

原理

  1. 锁存端是高电平的时候,输入端和输出端是相通的;

  2. 锁存端是低电平的时候,输入端和输出端是断开的,输出端保持原来的值。

  3. P13口是数码管总开关,P15是位选开关,P14是端选开关

  4. 位选是选数字显示的位置,段选是选具体的数字

具体过程(数码管从左往右第二位显示“2”)

  1. 定义sbit dula = P1^3;,sbit wela = P1^4;;(P1.3、P1.4口分别是控制段选和位选的的IO口)

  2. 首先数码管总开关打开 K1 = 0;,让P0 = 0xFD;,然后打开位选开关wela = 1;,这样P0的值就会送入,wela = 0;开关关闭,P0的值被”关起来“了(锁存),这样就确定了数码管在从左往右第二位显示数字

  3. P0 = 0x5B;,然后打开段选开关dula = 1;,这样P0的值就会送入,dula = 0;开关关闭,P0的值锁存,这样就确定了显示的数字是“2”。

3.display

博主自己定义的、常用来数码管显示的函数

数码管显示定义成函数有助于功能模块化、清晰化

//数码管显示
void display(int position, int n)
{
    //异常检查
    if(n < 0 || n > 17) return ;    
    if(position < 0 || position > 7) return ;
    
    //“总开关”打开
    K13 = 0;
    
    //消隐
    dula = 1;
    P0 = 0x00;
    dula = 0;
    
    //位选
    P0 = positions[position];
    wela = 1;//高电平数据直通    
    wela = 0;//低电平锁存 
    
    //段选  
    P0 = table[n]; 
    dula = 1;
}

段选码、位选码

  • 段选码 0~9 + A~F + "-" + "." 表示数码管显示的内容
  • 位选码 1-8 表示数码管显示内容的位置
//段选
uchar table[18]= 
{
    0x3F,0x06,0x5B,0x4F,
    0x66,0x6D,0x7D,0x07,
    0x7F,0x6F,0x77,0x7c,
    0x39,0x5e,0x79,0x71,
    0x80,0x40
 };//0x80是小数点,0x40是“-”

//位选
uchar positions[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};

实践代码

  1. 点亮第一个数码管,并让其保持常亮

    #include<reg52.h>
    #include<intrins.h>
    
    #define uchar unsigned char
    #define uint unsigned int 
    
    //定义变量
    sbit K1 = P1^3;
    sbit K2 = P1^4;
    sbit K3 = P1^5;
    
    //点亮第一个数码管,并让其保持常亮
    void main()
    {
        K1 = 0;//打开数码管
        
        //位选
        K3 = 1;//高电平数据直通 
        P0 = 0xFE;//1111 1110
        K3 = 0;//低电平锁存 
        
        //段选
        P0 = 0x06; //0000 0110    
        K2 = 0;  
    
        while(1);
        
    }
    
  2. 依次循环0~9

    #include<reg52.h>
    #include<intrins.h>
    
    #define uchar unsigned char
    #define uint unsigned int 
    #define length 10
    
    //变量定义
    sbit K1 = P1^3;
    sbit K2 = P1^4;
    sbit K3 = P1^5;
    int i = 0;
    int j = 0;
    
    //段选 0~9
    uint array[length] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
    //位选 1~8
    uchar position[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
    
    //函数声明
    void delay();
    
    //依次循环0~9
    void main()
    {
        K1 = 0;//打开数码管
        while(1)
        {
            for (i = 0; i < length; i ++)
            {           
                if (j >= 8) j = 0;
                //位选
                K3 = 1;
                P0 = position[j];
                K3 = 0;
                //段选
                P0 = array[i];
                K2 = 1;
                K2 = 0;
                j ++;
                delay();
            }        
        }        
    }
    
    //延时
    void delay()
    {
        uint x,y;
        //100 * 570
        for (x =100;  x>0; x--)    
            for (y = 570;  y>0; y--);
        
    }
    
  3. 使用display函数显示数字

    #include<reg52.h>
    #include<intrins.h>
    
    #define uchar unsigned char
    #define uint unsigned int 
    #define length 9
    
    //变量定义
    sbit K13 = P1^3;
    sbit dula = P1^4;
    sbit wela = P1^5;
    int i = 0;
    //段选
    uint table[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
    //位选
    uchar positions[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
    
    //函数声明
    void delay();
    void display(int position, int n);
    
    //依次循环0~9
    void main()
    {
        while(1)
        {
            for (i = 0; i < length; i ++)
            {                     
               display(i,i);//数码管显示
               delay();//延时
            }        
        }        
    }
    
    //延时函数
    void delay()
    {
        uint x,y;
        //100 * 570
        for (x =100;  x>0; x--)    
            for (y = 570;  y>0; y--);   
    }
    
    
    //数码管显示
    void display(int position, int n)
    {
        //异常检查
        if(n < 0 || n > 17) return ;    
        if(position < 0 || position > 7) return ;
        
        //“总开关”打开
        K13 = 0;
        
        //消隐
        dula = 1;
        P0 = 0x00;
        dula = 0;
        
        //位选
        P0 = positions[position];
        wela = 1;//高电平数据直通    
        wela = 0;//低电平锁存 
        
        //段选  
        P0 = table[n]; 
        dula = 1;
    }
    

三、中断

四、定时

五、按键

六、D/A A/D转换器及其单片机接口

七、串行口的工作原理及其应用

1、SCON

2、TI、RI

3、波特率

代码部分

1、通过串口调试助手发送数据并显示到跑马灯上

#include<reg52.h>
//函数声明
void init();
//主函数
void main()
{
    init();
    while(1)
    {        
        if(RI == 1)
        {
            RI = 0;
            P2 = SBUF;           
        }                
    }        
}

//初始化
void init()
{
    TMOD = 0X20;//设置定时器1为8位的常数自动装载的定时器/计数器
    TH1 =  0XFD;
    TL1 = 0XFD;    
    SM0 = 0;
    SM1 = 1;
    
    REN = 1;
    TR1 = 1;  
}

2、通过串口调试助手发送数据并显示到跑马灯上

(利用到了串行口中断)

#include<reg52.h>
//函数声明
void init();
//主函数
void main()
{
    init();
    while(1);       
}
//窗口中断
void ser() interrupt 4
{
     RI = 0;
     P2 = SBUF;       
}
//初始化
void init()
{
    TMOD = 0X20;//设置定时器1为8位的常数自动装载的定时器/计数器
    
    /*设置波特率位9600 */
    TH1 =  0XFD;
    TL1 = 0XFD;
    
    /*8位异步收发,波特率可变*/    
    SM0 = 0;
    SM1 = 1;
    
    REN = 1;//允许串行口接受数据
    TR1 = 1;//打开定时器1  
    EA = 1;//总中断允许
    ES = 1;
}

3、自发收

#include<reg52.h>
//函数声明
void init();
//主函数
void main()
{
    init();
    while(1);     
}
//串口中断
void ser() interrupt 4
{
     RI = 0;
     P2 = SBUF;
     SBUF = P2;
     TI = 0;    
}

//初始化
void init()
{
    TMOD = 0X20;//设置定时器1为8位的常数自动装载的定时器/计数器
    
    /*设置波特率位9600 */
    TH1 =  0XFD;
    TL1 = 0XFD;
    
    /*8位异步收发,波特率可变*/    
    SM0 = 0;
    SM1 = 1;
    
    REN = 1;//允许串行口接受数据
    TR1 = 1;//打开定时器1  
    EA = 1;//总中断允许
    ES = 1;
}
posted @ 2021-09-04 01:46  六月琳  阅读(23)  评论(0)    收藏  举报