51单片机入门(更新7.24)

LED灯

接口:P2_1=0(低电平)

P2=0x3C 放在循环外更高效

点亮:直接用P2=0x3C

闪烁:加延迟

流水灯:每个都亮一次+延迟

延迟设置:12MHz,1毫秒,Y1(51系列)

定义头文件:<INTRINS.H>

——任意数值延迟

void Delay1ms(unsigned int xms)        //@12.000MHz
{
    unsigned char i, j;
    while(xms)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
        xms--;
    }
}

独立按键

接口:P3_1==0(低电平)

单个使用

void main()
{
    while(1)
    {
        if(P3_0==0)
        {
            Delay(20);
            while(P3_0==0);
            Delay(20);  //消抖
            
            P2_1=~P2_1; //需要操作的按键
        }
    }
}

多个使用的模块化处理

        Key.c          

#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;

         Key.h          

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif

main.c 主程序使用该功能

#include <REGX52.H>
#include "Delay.h"

unsigned char Key();
unsigned char KeyNum;

void main()
{
    while(1)
    {
        KeyNum=Key();
        if(KeyNum)
            {
                if(KeyNum==1)P2_1=~P2_1;
                if(KeyNum==2)P2_2=~P2_2;
                if(KeyNum==3)P2_3=~P2_3;
                if(KeyNum==4)P2_4=~P2_4;
            }
    }
}


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;
}

静态数码管

        显示一个数字

unsigned char a[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

/*共阴极,高电平有效,分别是0,1,2,3,4,5,6,7,8,9*/


void NT(unsigned char loc,num)  //什么位置,显示什么数字
{
    switch(loc)  //什么位置
    {
    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; 

/*P2_4是最高位,P2_2是最低位,高电平有效,想要显示*/
    }
    P0=a[num];  //显示什么数字,在上面的数组里0~9
}

void main()
{
    NT(6,8);  //什么位置,显示什么数字
    while(1)
    {
    
    }
}

        显示多个数字

                加上延迟即可

unsigned char a[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

/*此处调用延迟函数*/ 

void NT(unsigned char loc,num)
{
    switch(loc)
    {
    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=a[num];
    Delay(1);
    P0=0x00;   
//消影
}

void main()
{
    
    while(1)
    {
            NT(1,1);
            Delay(1);    
            NT(2,4);
            Delay(1);    
            NT(3,7);

            Delay(1);

     }

补充:模块化

创建 .c 项目文件

        记录函数

创建 .h 项目文件

        

#ifndef __函数名_H__
#define __函数名_H__

        函数; //.c的函数

#endif

 主文件:

开头处引用函数

        例如:#include "shuma.h"  //内部引用使用双引号

液晶屏LCD1602 

         使用前提:需要有LCD1602.c和LCD1602.h文件,并在开头处调用(模块化知识)

void main()
{
    LCD_Init();  //上电初始化,必写
    LCD_ShowChar(1,1,'B');  //行,列,显示字符
    LCD_ShowString(1,3,"hello");  //行,列,显示字符串
    LCD_ShowNum(1,9,123,3);  //行,列,显示数字,位数
    LCD_ShowSignedNum(1,13,-66,2);  //行,列,有符号数字,位数(不包括符号)
    while(1)
    {


    }
}

        计数器功能

#include "LCD1602.h"
#include "Delay.h"

int result=0;  //赋初值
void main()
{
    LCD_Init();
    while(1)
    {
        result++;  //自加
        Delay(1000);  //延迟一秒
        LCD_ShowNum(1,1,result,3);  //反复显示,放在循坏外则无变化
    }
}

矩阵键盘 

        由于引脚冲突,采用逐列扫描

        MatrixKey.c         

#include <REGX52.H>
#include "Delay.h"

unsigned char MatrixKey()
{
    unsigned char KeyNumber=0;
    
    P1=0xFF;  //赋初值:1111 1111
    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;
}

        MatrixKey.h          

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey();

#endif

         密码锁功能 

unsigned char KeyNum;
unsigned int password,count;

void main()
{
    LCD_Init();  //上电初始化


    LCD_ShowString(1,1,"password");  //第一行,第一列,显示"password"


        while(1)
        {
        KeyNum=MatrixKey();  //键盘输入
            if(KeyNum!=0)
            {
                if(KeyNum<=10)
                {
                    if(count<4)  //计数,小于4次,意思是四位密码
                    {
                    password*=10;  //密码左移一位;
                    password+=KeyNum%10;  //1~9对10取余还是本身;
                    count++;
                    }
                }
                LCD_ShowNum(2,1,password,4);
            }


                if(KeyNum==11)  //“确认”功能
                {
                        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)  //手动“清零”功能
                {
                password=0;
                count=0;  //清零
                LCD_ShowNum(2,1,password,4);  //更新显示
                }
        }


    }

定时器

        内部定时器:三个(T0,T1,T2)

        有四种工作模式,常用模式1:16位定时器/计数器

        细分三个部分:时钟——计数——中断

        (每来一个时钟脉冲就进行计数,加到溢出就申请中断,中断结束回到主程序)         

        时钟部分:

                若接T0 pin_外部引脚:计数器

                只用内部晶振_12MHz:定时器

相关寄存器

        关于寄存器的理解:

        灯和开关的关系,开关可以简单理解为是个寄存器。

        具体配置需要阅读手册,查看每个位的功能进行配置,把二进制转化为十六进制进行置位。

        可位寻址:可以单个位赋值;不可位寻址:只能整体赋值

        定时器的寄存器:

                TCON 定时器/计数器中断控制寄存器:可位寻址

                        TF0=0;//清除TF0标志

                        TR0=1;  //定时器开始工作

                TMOD 定时器/计数器工作模式寄存器:不可位寻址

                        “与或式赋值法”,操作某一位而不影响其他位:模式1

                        TMOD=TMOD&0xF0  //高四位保持不变,低四位清零

                        TMOD=TMOD|0x01  //高四位保持不变,第四位置1

                TL0/TH0 定时器0,高位和低位计数单元:赋初值_1毫秒

                        TH0=0x18  //高位

                        TL0=0xFC  //低位

                TL1/TH1 定时器1,高位和低位计数单元:使用计数器0时,此定时器用不上

        中断寄存器:        

                IE 中断允许寄存器:

                        ET0=1;

                        EA=1;

                IP 中断优先级中断寄存器: 

                        PT0=0;

        定时器功能

        Timer0.c            //定时器0初始化,1毫秒

void Timer0_Init(void)
{
    TMOD &= 0xF0;    
    TMOD |= 0x01;    
    
    TF0 = 0;        
    TR0 = 1;
    
    TL0 = 0x18;    
    TH0 = 0xFC;        
    
    ET0=1;
    EA=1;
    PT0=0;  //中断


}

/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
        static unsigned int T0count;
        TL0 = 0x18;   //定时初值 
        TH0 = 0xFC; //定时初值       
        T0count++;
        if(T0count>=1000)  //1秒
        {
            T0count=0;  //清零
            执行某个任务;
        }
}*/

        Timer0.h          

#ifndef __TIMER0_H__
#define __TIMER0_H__

        void Timer0_Init(void);

#endif

main主函数 :

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"  //所需的头文件(前文有提到)

unsigned char sec=55,min=59,hour=23;  //赋初值,秒分时

        /*主函数*/

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 = 0x18;  //定时初值  
        TH0 = 0xFC; //定时初值       
        T0count++;
        if(T0count>=1000)  //1秒
        {
            T0count=0;  //清零


            sec++;
            if(sec>=60)
            {
                sec=0;
                min++;
                if(min>=60)
                    {
                        min=0;
                        hour++;
                    if(hour>=24)
                    {
                        hour=0;
                    }
                    }
            }
        }


}

串口

        89C52有1个UART(UART是常用的接口,引脚定义TXD,RXD)

        有四种工作模式,常用的是模式1:8位UART,波特率可变

相关寄存器

        串口部分:

                SCON 串行控制寄存器: 模式1

                        SCON=0x40(01000000)

                PCON 电源控制寄存器:前两位控制串口

                        PCON=PCON|0x80

                SBUF 串行口缓存寄存器:

                        void UART_SendByte(unsigned char Byte)
                        {
                            SBUF=Byte;  //SBUF在等号左边:写入
                            while(TI==0);  //判断“发送中断请求标志位”是否为1
                            TI=0;  //一旦为1,就要置0,完成数据发送
                        }

        定时器部分:

                TMOD 定时器/计数器工作模式寄存器:不可位寻址

                        定时器1模式2(串口专用)

                        TMOD=TMOD&0x0F  //低四位保持不变,高四位清零

                        TMOD=TMOD|0x20  //低四位保持不变,第三位置1

                TL0/TH0 定时器1,高位和低位计数单元:波特率设置

                        TH1=0xF3  //设定定时初值

                        TL1=0xF3  //设定定时器重装值

                IE 中断允许寄存器:

                        ET1=0;

                TCON 定时器/计数器中断控制寄存器:可位寻址

                        TR1=1;  //定时器开始工作

模块化处理

         UART.c          

#include <REGX52.H>

void UART_Init(void)        //串口初始化,4800bps@11.0592MHz
{
    PCON &= 0x7F;        
    SCON = 0x50; //0x50能够接收数据,0x40只能发不能接收       
    TMOD &= 0x0F;        
    TMOD |= 0x20;        
    TL1 = 0xFA;        
    TH1 = 0xFA;        
    ET1 = 0;        
    TR1 = 1;        
}

void UART_SendByte(unsigned char Byte)  //串口发送一个字节的数据
{
    SBUF=Byte;  
    while(TI==0);
    TI=0;
}

          UART.h          

#ifndef __UART_H__
#define __UART_H__

void UART_Init(void);
void UART_SendByte(unsigned char Byte);

#endif

功能实现

                功能1:单片机向电脑发送数据

模块化处理后,只需要调用UART_SendByte()函数

void main()
{
    UART_Init();
    UART_SendByte(0x66);  //单向发送数据
    while(1)
    {
    
    }
}

                功能2:电脑向单片机发送数据

 模块化处理后,需要配置中断

void main()
{
    UART_Init();
    while(1)
    {

    }
}

void UART_Routine() interrupt 4
{
    if(RI==1)
    {
        P2=~SBUF;  //点亮LED灯
        RI=0;
    }
}

 LED点阵屏显示

74HC595

                类型:串行输入并行输出的位移寄存器

        SER:串行数据输入

        SERCLK:移位寄存器时钟

        RCLK:存储寄存器时钟

                工作模式:输入数据到SER,SERCLK中每来一个高电平就会往前移一位,RCLK中来一个高电平就会实现位移

        模块化处理 

          Matrix_LED.c          

#include <REGX52.H>
#include "Delay.h"

sbit RCK=P3^5;
sbit SCK=P3^6;
sbit SER=P3^4;

#define MATRIX_LED_PORT    P0

void _74HC595_WriteByte(unsigned char Byte)
{
        unsigned char i;
        for(i=0;i<8;i++)
        {
            SER=Byte&(0x80>>i);
            SCK=1;
            SCK=0;
        }
            RCK=1;
            RCK=0;
}

void MatrixLED_Init()
{
        SCK=0;
        RCK=0;

}

void MatruxLED_showcolum(unsigned char Column,Date)  //列,显示的数字
{
        _74HC595_WriteByte(Date);
        MATRIX_LED_PORT=~(0x80>>Column);
        Delay(1);
        MATRIX_LED_PORT=0xFF;
}

          Matrix_LED.h          

#ifndef __MATRIX_LED_H__
#define __MATRIX_LED_H__

void _74HC595_WriteByte(unsigned char Byte);
void MatrixLED_Init();
void MatruxLED_showcolum(unsigned char Column,Date);

#endif

                功能:斜对角点亮LED点阵屏 

void main()
{    

    MatrixLED_Init();

    while(1)
    {
    MatruxLED_showcolum(0,0x3C);
    MatruxLED_showcolum(1,0x42);
    MatruxLED_showcolum(2,0xA9);
    MatruxLED_showcolum(3,0x85);
    MatruxLED_showcolum(4,0x85);
    MatruxLED_showcolum(5,0xA9);
    MatruxLED_showcolum(6,0x43);
    MatruxLED_showcolum(7,0x3C);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值