蓝桥杯2024/1/23练习笔记

练习内容:

示例代码:

/*头文件声明区*/
#include <STC15F2K60S2.H>
#include <stdio.h>
#include <intrins.h>

/*变量声明区*/
unsigned char flag = 0;//要求2LED流水灯按键标志位
unsigned char flag1 = 0;//赋值为2数码管正计时,赋值为3数码管倒计时,赋值为4按键每按下一次加一0-9的循环
unsigned char count = 0;
int k1=0;
code unsigned char Seg_Table[] = {0xc0,0xf9,0xa4, 0xb0,0x99,0x92,0x82, 0xf8,0x80,0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e };//共阳数码管段码表,这个code是把这个数据存放在另一个区,可以存放较大的数据

/*延时函数*/
void Delay500ms()        //@11.0592MHz,延时500ms
{
    unsigned char i, j, k;

//    _nop_();//这个复制过来的函数需要加相应的头文件,这里用不到可以删掉,不然会报错
//    _nop_();
    i = 22;
    j = 3;
    k = 227;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}
void Delay10ms()        //@11.0592MHz,延时10ms
{
    unsigned char i, j;

    i = 108;
    j = 145;
    do
    {
        while (--j);
    } while (--i);
}

void Delay2ms()        //@11.0592MHz,延时2ms
{
    unsigned char i, j;

    _nop_();
    _nop_();
    i = 22;
    j = 128;
    do
    {
        while (--j);
    } while (--i);
}

void Latch(unsigned char Yn,unsigned char value)//锁存器函数,使用锁存器可以调用这个函数
{
    if(Yn < 4 || Yn > 7)//判断锁存器是否合法,这里实际只用到了Y4—Y7
    {
        return;//关闭所以不返回值
    }
    P0 = value;
    P2 = P2 & 0x1f |(Yn << 5);//打开锁存器7,想打开哪一个锁存器就修改到对应的值
    P2 = P2 & 0x1f;
}
void SEG(unsigned char wei,unsigned char duan)//数码管显示函数
{
    Latch(7,Seg_Table[duan]);
    Latch(6,0x01<< (wei - 1));
    Delay2ms();
    
}

void Timer0()//定时器
{
    AUXR &= 0x7f;//12T模式
    TMOD &= 0xf0;//16位自动重装载模式
    TH0 = (65536-46083) / 255;//计时50ms
    TL0 = (65536-46083) % 255;
    TF0 = 0;
    TR0 = 1;
    EA = 1;
    ET0 = 1;
}
void LED_dalay1()//实现流水灯两种方式循环
{
    int i;
    P0 = 0x10;
    P2 = P2 & 0x1f | 0x80;//打开锁存器
    //0000 0001 << 1 = 0000 0010
    for(i=0;i<8;i++)
    {
        if(flag == 0)
        {
                P0 = ~(0x01 << i);//每次循环亮一个灯
                Delay500ms();
        }
        if(flag == 1)
        {
                P0 = (0x01 << i);//每次循环灭一个灯
                Delay500ms();
        }
        
    }
}

void LED_dalay2()//LED闪烁的两种方式,可以注释掉另一种方式进行使用
{
    int i;
    P0 = 0x10;
    P2 = P2 & 0x1f | 0x80;//打开锁存器
    //0000 0001 << 1 = 0000 0010
    for(i=0;i<8;i++)
    {
        //0101 0101奇数亮
        P0 =0x55;
        Delay500ms();
//        //1010 1010偶数亮
//        P0 =0xaa;
//        Delay500ms();
    }
}

void scan()//按键控制函数
{
    if(P33 == 0)
    {
        Delay10ms();
        if(P33 == 0)//确定按下S4按键
        {
            flag = 0;
        }
            
    }
    if(P32 == 0)
    {
        Delay10ms();
        if(P32 == 0)//确定按下S5按键
        {
            flag = 1;
            flag1 = 4;//要求4按键标志位
            k1=k1+1;
            if(k1>9)k1=0;                
            SEG(1,k1);
            Delay500ms();
        }
    }
    if(P31 == 0)
    {
        Delay10ms();
        if(P31 == 0)//确定按下S6按键
        {
            //SEG(1,2);
            flag1 = 2;//数码管正计时
        } 
            
    }
    if(P30 == 0)
    {
        Delay10ms();
        if(P30 == 0)//确定按下S7按键
        {
            //SEG(1,9);
                flag1 = 3;//数码管倒计时
        
        }
  }

}
void Timer_server() interrupt 1//定时器中断服务函数
{
    count++;
    if(count == 20)//计时1s
    {
        count = 0;
    }
}

void main()
{
//    //1111 1110
//    //P0 = 0xfe;
//    //P27 = 1;P26 = 0;P25 = 0;
//    P0 = 0x10;//0001 0000 低电平点亮,灯呈现的状态
//    //X & 0 = 1;
//    //X | 1 = 1;与0为0,或1为1
//    //0001 1111 0x1f
//    //1000 0000 0x80
//    P2 = P2 & 0x1f | 0x80;
    Latch(5,P0 & ~(5 << 4));//拉低P06和P04关闭,蜂鸣器和L10提示灯关闭
    Timer0();
    while(1)
    {
        scan();
        
//        //LED_dalay2();
//        //LED_dalay1();

        if(flag1 == 2)
            {
                int k;
                Delay500ms();
                for(k=0;k<10;k++)
                {
                    SEG(1,k);
                    Delay500ms();
                }    
            }
        
        if(flag1 == 4)
            {
//                int k;//这部分放在这里实际会一直循环显示达不到效果,放到按键控制函数
//                k=k+1;
//                SEG(1,k);
//                Delay500ms();
                
            }
            
            if(flag1 == 3)
            { 
                int k;
                for(k=9;k>=0;k--)
                {
                    SEG(1,k);
                    Delay500ms();
                }    
            }
            
    }    
                
}

问题记录:

问题1:

问题2:

这个else会抢占运行,从而使后面运行的代码出现逻辑问题,每次显示5之后才开始9-0的循环倒计时,实际不应该出现这个5,与预期显示9-0的倒计时效果不一致。

问题3:

k1=k1+1;

if(k1>9) k1=0;

正确的使用判断为:先+,后判断;就可以实现k1大于9之后就等于0的循环;显示的数码管断码就为0。

if(k1>9) k1=0;

k1=k1+1;

先判断,后+;就会一直加到>9则为10->显示A;才会触发k1=0,按下+1显示1一直循环。这样会出现判断有误,此处错误的现象为0的显示为A,实际想要呈现的效果为按下每次加一0-9的循环。

关于这个定时器的使用:

结合这些资料可以看出定时器的代码编写,以及这个定时器初值计算为什么是减去46083这个值。也可以用STC软件直接生成c代码使用,这里简略介绍一下使用方法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值