UAV2201~UAV2205编程与仿真51MCU初学者训练

练习001:51单片机Proteus仿真:点亮一个灯

1、器件清单

Proteus关键词元器件
CAP 固定电容
CAP-ELEC 电解电容
AT89C51 AT89C51单片机
CRYSTAL 晶振
BUTTON 复位按键
RES 电阻
RESPACK 排阻
LED-YELLOW 黄色发光二极管

2、电路

 

   3、代码

//例子01
#include <reg52.h>   //单片机头文件
sbit LED=P2^0;       //定义LED为端口P2^0
void main()          //主程序
{
    while(1)         //无限循环
    {
        LED=0;       //P0^0输出低电平,发光二极管点亮
        //LED=1;     //P0^0输出高电平,发光二极管关闭
    }
}
//例子02
#include <reg52.h> sbit D7 = P2^7; unsigned int a; void main() { while(1) { D7 = 0; a = 20000; while(a--); D7 = 1; a = 20000; while(a--); } }
//例子03
#include <reg52.h>

void delay() { unsigned int z=20000; while(z--); } void main() { while(1) { P2 = 0XFE; delay(); P2 = 0xFF; delay(); } }
//例子04
#include <reg52.h>

void delay(unsigned int z) { while(z--); } void main() { while(1) { P2 = ~((1<<0)|(1<<2)|(1<<7)); delay(27765);//精确延迟250ms,在12MHz时钟 P2 = 0xFF; delay(27765); } } 
//例子05
#include <reg52.h>

void delay(void)
{
    unsigned int x,y;
    for(x=100;x>0;x--)
    {
        for(y=600;y>0;y--)
        {
            ;
        }
    }
}
    
void main()
{
    while(1)
    {
        P2 = 0x55;//01010101
        delay();  //延迟480ms
        P2 = 0xaa;//10101010
        delay();  //延迟480ms
    }
}
//例子06
#include <reg52.h>
void delay(void);
    
void main()
{
    while(1)
    {
        P2 = ~P2;
        delay();
    }
}

void delay(void)
{
    unsigned int x,y;
    for(x=100;x>0;x--)
        for(y=600;y>0;y--);

}
//例子07
#include <reg52.h>
void delay(unsigned int z);
    
void main()
{
    while(1)
    {
        P2 = 0xF0;
        delay(100);//精确延迟1s
        P2 = 0x0F;
        delay(100);//
    }
}

void delay(unsigned int z)//z=1,精确度10ms
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}

 

//高精度延迟函数适用于STC89系列单片机
void
Delay500ms() //@12.000MHz { unsigned char data i, j, k; _nop_(); i = 4; j = 205; k = 187; do { do { while (--k); } while (--j); } while (--i); }

 

练习002:51单片机Proteus仿真:流水灯

1、器件清单(参考练习001)

2、电路

 

1、画一条总线

2、将线路连接到总线

按住ctrl划线,画斜线连接线需要把”自动连接器”也称“自动连线”按钮放开。

3、将相应节点一一连接

Tool–Property Assignment Tool属性赋值工具

3、代码

 

//例子01、基础移位法
#include <reg52.h> void delay(unsigned int z); void main(void) { while(1) { P2 = ~(1<<0); delay(20); P2 = ~(1<<1); delay(20); P2 = ~(1<<2); delay(20); P2 = ~(1<<3); delay(20); P2 = ~(1<<4); delay(20); P2 = ~(1<<5); delay(20); P2 = ~(1<<6); delay(20); P2 = ~(1<<7); delay(20); } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//例子02、for语句移位
void
main(void) { unsigned char i; while(1) { for(i=0;i<8;i++) { P2 = ~(1<<i); delay(50); } } }
//例子03、if语句
void
main(void) { unsigned char a; while(1) { if(a==0x00)a=0x01; P2 = ~a; a=a<<1; delay(20); } }

 

//例子04、流水灯右移
#include <reg52.h> //单片机头文件 void Delay(); //延时子程序说明 void main() //主程序 { unsigned char i,temp; P2=0xff; //二进制1111 1111 while(1) //无限循环 { temp=0x80; //二进制10000000 for(i=0;i<8;i++) { P2=~temp; //取反0111 1111 Delay(); //延时函数 temp=temp>>1; //右移一位 } } } /*延时子程序使LED在变化时有一个停留时间,通过一个外循环和内循环的空操作,共循环255×255次*/ void Delay() { unsigned char i,j; for(i=0;i<255;i++) //外循环255次 for(j=0;j<255;j++); //内循环255次 }

 

//例子05、流水灯左移
#include <reg52.h> void delay(unsigned int z); void main(void) { unsigned char i,temp; while(1) { temp=0xfe; for(i=0;i<8;i++) { P2 = temp; delay(30); temp =(temp<<1)|0x01;//右移编写temp = (temp>>1)|0x80; } } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//例子06、流水灯采用C51内部移位子函数
#include <reg52.h> #include <intrins.h> void delay(unsigned int z); void main(void) { unsigned char temp=0xfe; while(1) { P2 = temp; delay(30); temp =_crol_(temp,1);//循环左移函数_crol_循环右移函数_cror_ } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }

 

//例程07 流水灯运用数组调用实现
#include <reg52.h>
unsigned char Tab[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
 
void delay(unsigned int xms)
{
    unsigned int i,j;
    for(i=xms;i>0;i--)
        for(j=123;j>0;j--);
 }

void main()
{
    unsigned char i;
    while(1)
    {
         for(i=0;i<8;i++)
        {
             P2 = ~Tab[i];
             delay(100);
         }
    }
}

 

//例子08、流水灯运用一维数组实现,反向显示跑马灯
#include <reg52.h> void delay(unsigned int z); void main() { unsigned char display1[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; unsigned char display2[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; unsigned char i,j; while(1) { for(i=0;i<8;i++) { P2=display1[i]; delay(30); } for(j=0;j<8;j++) { P2 = display2[j]; delay(30); } } }

//例子08、花样年华流水灯,任意LED动态显示(略)

练习003:51单片机Proteus仿真:一位数码管计数

1、器件清单

Proteus关键词元器件
AT89C51 AT89C51单片机
RES 电阻
BUTTON 按键
7SEG-COM-AN-GRN 数码管(绿色)

 数码管接线结构图

数码管有两种,共阴和共阳,很好区分的,公共端在上边的就是共阳的,习惯上画VCC时是放在上边的,公共端在下边的就是共阴了,画地时习惯上放在下边的。再说数码管的7段,从上边的横开始起叫A,按顺时针方向依此为ABCDEFG,最后说左边的引脚,从上边开始向下,依此是ABCDEFG。这样就对应上了,根据显示数字的需要在各段加有效电平就显示出相应的数字了。如下面的图是一种测试方法。左边的两个就是共阳的,右边的一个就是共阴的。

 2、电路(左图自动,右图手动)

  3、代码

//例子01、单个数码管循环显示字符0-F,运用if语句(自动计数0-9)
#include <reg52.h>

unsigned char smg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极8段
void delay(unsigned int z);

void main(void)
{
    unsigned char i;
    while(1)
    {
        P2 = smg[i];//送相应数码管段表值
        delay(50);
        i++;
        if(i>=16)i=0;//if(i>9) i=0; 
    }
}
void delay(unsigned int z) //当z=1,延迟时间10ms
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}
//例子02、1位数码管自动计数,运用for语句,包含小数点
#include <reg52.h>
unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99,0x92,
0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表
bit point_on = 0;//点亮小数点

void delay(unsigned int z) //当z=1,延迟时间10ms
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}

void main(void)
{
    unsigned char i=0;
    while (1)
    {
        for (i=0;i<=9;i++)
        {
            P2 = Tab[i];
            if (point_on) 
            {
                P2 &= 0x7f;
            }
            delay(50);
        }
        point_on = ~point_on;
    }
}

 

 

//例子03、4位数码管,动态扫描方法,显示0123
#include <reg52.h>
unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99,0x92,
0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表

void delay(unsigned int z) //当z=1,延迟时间10ms
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}

void main(void)
{
    unsigned char i=0;
    while (1)
    {
        for (i=0;i<4;i++)
        {
            P2 = Tab[i];
            P1 = ~(1<<i);
            delay(1);
            P1 = 0xff;
        }
    }
}
//例子04、4位数码管,动态扫描法,独立编写显示子函数,显示任意数1314
#include <reg52.h>
unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99,0x92,
0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表

void delay(unsigned int z) //当z=1,延迟时间10ms
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}
void display()
{
    P2 = Tab[8];  //输入需要显示的数字
    P1 = ~(1<<0); //选择显示位
    delay(1);
    P1 = 0xff;
    
    P2 = Tab[5];  //输入需要显示的数字
    P1 = ~(1<<1); //选择显示位
    delay(1);
    P1 = 0xff;
    
    P2 = Tab[2];  //输入需要显示的数字
    P1 = ~(1<<2); //选择显示位
    delay(1);
    P1 = 0xff;
    
    P2 = Tab[0];  //输入需要显示的数字
    P1 = ~(1<<3); //选择显示位
    delay(1);
    P1 = 0xff;
                
}
void main(void)
{
    while (1)
    {
        display();
    }
}

 

//例子05、4位数码管,显示函数封装为子函数,可以显示任意的四位数

void display(unsigned int dat)
{
    P2 = Tab[dat/1000%10];  //显示数字千位
    P1 = ~(1<<0); //选择显示位
    delay(1);
    P1 = 0xff;
    
    P2 = Tab[dat/100%10];  //显示数字百位
    P1 = ~(1<<1); //选择显示位
    delay(1);
    P1 = 0xff;
    
    P2 = Tab[dat/10%10];  //显示数字十位
    P1 = ~(1<<2); //选择显示位
    delay(1);
    P1 = 0xff;
    
    P2 = Tab[dat%10];  //显示数字个位
    P1 = ~(1<<3); //选择显示位
    delay(1);
    P1 = 0xff;
}

void main(void)
{
    while(1)
    {
        display(1314);
    }
}

 练习004:51单片机Proteus仿真:按键控制流水灯、按键控制数码管

1、器件清单

2、电路图

3、源代码

//例子01、按键控制,按键P00和P01按下后,流水灯左右移动(含软件消抖)
#include <reg52.h>

unsigned char smg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极8段
void delay(unsigned int z);
sbit key1=P0^0;   //定义按键位置
sbit key2=P0^1;
sbit key3=P0^2;
sbit key4=P0^3;

void main(void)
{
    char i;
    while(1)
    {
        if(key1==0)         //判断KEY1是否按下
        {
            delay(3);       //延时20ms,屏蔽抖动区
            if(key1==0)     //再次判断KEY1是否按下
            {
                P2 = ~(1<<i);
                if(++i>=8)i=0;    
            }
            while(!key1);   //等待按键释放
        }
        else if(!key2)
        {
            delay(3);
            if(!key2)
            {
                P2 = ~(1<<i);
                if(i--<=0)i=8;    
            }
            while(!key2);        
        }
        else
        {
             P2 &= 0xff;
        }

    }
}
void delay(unsigned int z) //当z=1,延迟时间10ms
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}

//例子02、按键控制,按键P00和P01按下后,数码管计数(含软件消抖),键盘读取编写子函数
#include <reg52.h>

unsigned char smg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极8段
void delay(unsigned int z);
sbit key1=P0^0;   //定义按键位置
sbit key2=P0^1;
sbit key3=P0^2;
sbit key4=P0^3;

unsigned char readkey(void)
{
    if(!key1)                   //判断KEY1是否按下
    {
        delay(3);           //延时20ms,屏蔽抖动区
        if(!key1)               //再次判断KEY1是否按下
        {
            while(!key1);       //等待按键释放
            return 1;           //返回键值1
        }
    }
    else if(!key2)              //判断KEY2是否按下
    {
        delay(3);              //延时20ms,屏蔽抖动区
        if(!key2)               //再次判断KEY2是否按下
        {
            while(!key2);       //等待按键释放
            return 2;           //返回键值2
        }
    }
    return 0;                 //没有按键按下,返回键值0
}

void main(void)
{
    unsigned char num,temp;
    while(1)
    {
        temp = readkey();
        if(temp == 1)         //判断KEY1是否按下
        {
            num++;
            if(num==10)num=0;
        }
        else if(temp == 2)
        {
            if(num==0)num=10;
            num--;
        }
        else
        {
             ;
        }
        P2 = smg[num];
    }
}
void delay(unsigned int z) //当z=1,延迟时间10ms
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}

 练习004:51单片机Proteus仿真:外部中断控制演示

1、器件清单

2、电路图

3、源代码

//例子01、1位数码管手动计数代码,采用外部中断法
#include <reg52.h>
unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99,
0x92,0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表
unsigned char p=1;
void Delay()//简单延时子程序
{
    unsigned char i;
    for(i=300;i>0;i--);
}

void main()//主程序
{
    EA=1;//开总允许开关
    IT0=1;EX0=1;//开外部中断0和外部中断0允许分开关
    IT1=1;EX1=1;//开外部中断1和外部中断1允许分开关
    while(1)
    {
        P2=Tab[p]; //输出码段表
        Delay();
    }
}
void intersvr0(void) interrupt 0 using 1 //外部中断0处理子程序
{
    p++;
    if(p>9) p=9;
}
void intersvr1(void) interrupt 2 using 1 //外部中断1处理子程序
{
    p--;
    if(p<1) p=1;
}

 

//例子02、中断演示。正常主程序每隔0.5s,数码管依次显示0-F中的1个;当按键K2被按下时,流水灯流动
#include <reg52.h>
unsigned char Tab[]={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
void delay(unsigned int z) 
{
    unsigned char i,j,k;
    for(i=z;i>0;i--)
        for(j=4;j>0;j--)
            for(k=248;k>0;k--);
}
void main(void)
{
    unsigned char i;
    EA=1;
    EX1=1;
    IT1=0;
    while(1)
    {
        P0=Tab[i];
        P1=0XC0;
        if(++i>9)i=0;
        delay(50);
    }
}
void intl(void) interrupt 2
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        P2=~(1<<i);
        delay(20);
    }
}    

 

posted on 2023-10-09 21:59  一郎哥哥  阅读(2163)  评论(0编辑  收藏  举报

导航