第十五届蓝桥杯单片机模拟考试|

第十五届蓝桥杯单片机模拟考试|

目录

第十五届蓝桥杯单片机模拟考试|

一、基本要求

二、硬件框图

三、功能描述

3.1基本功能描述

3.2显示功能

3.3按键功能

3.4记录功能

3.5LED指示灯功能

3.6初始状态

四、代码示例

五、题目网址:


一、基本要求

1、将IAP15F2K61S2单片机内部振荡器频率设定为12MHZ。 2、键盘工作模式跳线J5配置为KBD矩阵按键模式。 3、扩展方式跳线J13配置为I0模式

二、硬件框图

三、功能描述

3.1基本功能描述

1)通过读取DS1302 RTC芯片,获取时间数据;

2)通过EEPROM实现数据记录功能;

3)通过LED指示灯完成试题要求的状态指示功能;

4)通过数码管、按键完成试题要求的数据显示和界面切换功能;

3.2显示功能

1)时间界面 时间界面如图2所示,显示内容包括时、分、秒数据和间隔符"”时、分、秒数据固定占2 位显示宽度,不足2 位补 0。

2)输入界面

输入界面如图3所示,由标识符(C)和一个4位数据组成,4位数据通过4位数码管显示,每输入一位数据,数码管显示向左移动一位,直到完成4位数据的输入。

3)记录界面

记录界面如图4所示,由标识符(E)和输入4位数据的起始时和分数据以及时、分数据的间隔符(-)。

4)显示要求

按照题目要求的界面格式和切换方式进行设计。数码管显示无重影、闪烁、过暗、亮度不均匀等严重影响显示效果的缺陷。

3.3按键功能

1)功能说明

① S4:定义为“切换”,按下S4按键,切换“时间界面”、“输入界面”和“记录界面”。

② S5:定义为“清除”,在输入界面下,按下S5,清除当前输入的数据,显示输入数据的4位数码管全部熄灭。

③ S6、S10、S14、S18、S9、S13、S17、S8、S12、S16分别对应数值“0-9”,在“输入界面”下,按下对应按键,实现一位对应数据的输入,显示格式及要求如图3所。若当前4位数据输入完成,按键继续输入不影响当前已输入完成的4位数据。

2)按键要求

按键应做好消抖处理,避免出现一次按键动作导致功能多次触发。 按键动作不影响数码管显示等其他功能。 按键 S5、S6、S10、S14、S18、S9、S13、S17、S8、S12、S16仅在"输入界面”有效。

3.4记录功能

每次进入记录界面时,将4位数据和输入数据的起始时间保存到E2PROM,存储位置要求如下:

输入数据起始时间(时):E2PROM内部地址0:

输入数据起始时间(分):E2PROM内部地址1;

输入数据(高字节):E2PROM内部地址2;

输入数据(低字节):E2PROM内部地址3; ​ 注意: ​ E2PROM写入操作发生在切换到记录界面时,其它时间不写入。

输入数据以HEX编码写入E2PROM,例如数据数据为1234,E2PROM内部地址2中应保存04H,内部地址3中保存D2H。

3.5LED指示灯功能

1、界面指示灯

1)时间界面下,指示灯L1 点亮,否则指示灯 L1 熄灭。

2)输入界面下,指示灯 L2 点亮,否则指示灯 L2 熄灭。

3)记录界面下,指示灯 L3 点亮,否则指示灯 L3 熄灭。

2、记录指示灯 若本次记录的4位数据较上一次记录的4位数据大,则指示灯L4点亮,否则指示灯熄灭。

3.6初始状态

请严格按照以下要求设计作品的上电初始状态。 1)处于时间界面。

2)指示灯L1点亮,其余指示灯熄灭。

四、代码示例

// Header:      
// File Name: 
// Author:
// Date:
/********************预编译、宏和变量********************************************/
#include "main.h"
#include <stdio.h>
​
#include "key.h"
#include "ds1302.h"
#include "iic.h"
/*************************************************************
                     宏定义区域
**************************************************************/
#define CONTROL(x,y)    P0=y;P2=x;P2=0      //为锁存器的引脚操作封装一个带参宏
​
enum PERIPHERAL
{
    LED = 0x80,
    DEVICE = 0xa0,
    BIT = 0xc0,
    SEG = 0xe0
};
​
/*******************************************************************************
                     变量定义
********************************************************************************/
/********************模板驱动变量****************************/
//控制LED0~7的开关量,正逻辑
bit LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7;
//控制蜂鸣器的自定义变量,正逻辑
bit Buzzer;
//控制继电器的自定义变量,正逻辑
bit Relay;
//Dsp_Bit是数码管显示的字符串数组,考虑到小数点的同位显示,所以字符串长度最长为16
uchar Dsp_Bit[16] = {0};
//数码管显示的各位段码内容,由 Dsp_Bit 通过函数Seg_Tran转换更新
uchar Dsp_Code[8] = {0};
//定时器计数
uint    Tick;
​
​
​
​
/********************中断区域***************************************************/
/*******************************************************************************
函数名程:   void Timer_2Init(void)
函数功能:   定时器T2 中断 1ms 配置
参数列表:   
返回值  :
*******************************************************************************/
void Timer_2Init(void)      //1000微秒@12.000MHz
{
    AUXR |= 0x04;       //定时器时钟1T模式
    T2L = 0x20;         //设置定时初值
    T2H = 0xD1;         //设置定时初值
    AUXR |= 0x10;       //定时器2开始计时
​
    IE2 |= 0x04;        //ET2 = 1;
    EA = 1;
}
​
/*******************************************************************************
函数名程:   void Timer2_Service() interrupt 12
函数功能:   定时器T2 中断 1ms 中断处理
参数列表:   
返回值  :
*******************************************************************************/
void Timer2_Service() interrupt 12
{
    static uchar dsp_com;
​
    //定时任务
    Tick++;     
    /***********控制外设的引脚操作*****/
    //更新LED的引脚操作
    CONTROL(LED,~((uchar)LED0|(uchar)LED1<<1|(uchar)LED2<<2|(uchar)LED3<<3|(uchar)LED4<<4|(uchar)LED5<<5|(uchar)LED6<<6|(uchar)LED7<<7));
    //更新蜂鸣器、继电器的引脚操作
    CONTROL(DEVICE,(uchar)Buzzer<<6|(uchar)Relay<<4);   
    //更新一位数码管的引脚操作
    CONTROL(BIT,0);                                 //消影
    CONTROL(SEG,Dsp_Code[dsp_com]);     //放入要显示的数字到段选锁存
    CONTROL(BIT,1 << (dsp_com));                //选择对应的位选锁存
    if(++dsp_com > 7)                               //显示完一次后自增位选,位选到8之后回到1
            dsp_com = 0;
}
​
/*******************************************************************************
函数名程:   void Seg_Tran(void)
函数功能:   将Dsp_Bit[]的内容,转换成对应的段码放入Dsp_Code[];
参数列表:   
返回值  :
*******************************************************************************/
void Seg_Tran(void)
{
  unsigned char i, j=0, temp;
  for (i=0; i<8; i++, j++)
  {
    switch (Dsp_Bit[j]) 
    { // 低电平点亮段,段码[MSB...LSB]对应码顺序为[dp g f e d c b a]
      case '0': temp = 0xc0; break;
      case '1': temp = 0xf9; break;
//    case '1': temp = 0xcf; break;
      case '2': temp = 0xa4; break;
      case '3': temp = 0xb0; break;
//    case '3': temp = 0x86; break;
      case '4': temp = 0x99; break;
//    case '4': temp = 0x8b; break;
      case '5': temp = 0x92; break;
      case '6': temp = 0x82; break;
//    case '6': temp = 0x90; break;
      case '7': temp = 0xf8; break;
//    case '7': temp = 0xc7; break;
      case '8': temp = 0x80; break;
      case '9': temp = 0x90; break;
//    case '9': temp = 0x82; break;
      case 'A': temp = 0x88; break;
      case 'B': temp = 0x83; break;
      case 'C': temp = 0xc6; break;
      case 'D': temp = 0xA1; break;
      case 'E': temp = 0x86; break;
      case 'F': temp = 0x8E; break;
      case 'H': temp = 0x89; break;
      case 'L': temp = 0xC7; break;
      case 'N': temp = 0xC8; break;
      case 'P': temp = 0x8c; break;
      case 'U': temp = 0xC1; break;
      case '-': temp = 0xbf; break;
      case ' ': temp = 0xff; break;
      case '^': temp = 0xfe; break; // 1 1 1 1 1 1 1 0
      case '_': temp = 0xf7; break; // 1 1 1 1 0 1 1 1
        default: temp = 0xff;
    }
    if (Dsp_Bit[j+1] == '.')
    {
      temp = temp&0x7f;             // 点亮小数点
      j++;
    }
    Dsp_Code[i] = temp;
  }
}
​
​
​
​
​
​
/********************应用层变量****************************/
//两个参数
char KeyNum;
//界面
uchar Page;
//起始时间
uchar Time[6]={2,3,0,9,5,9};
//输入的值
uint Value,Last_Value,Pre_Value;
//记录的时和分
uchar Hour,Min;
​
​
/*******************************************************************************
函数名程:   void Display_Task(void)
函数功能:   显示内容执行任务,0.5s刷新一次显示内容
参数列表:   
返回值  :
*******************************************************************************/
void Display_Task(void)
{
    static uint Display_Tick;
    
    if((Tick - Display_Tick) > 500)
    {   
        Display_Tick = Tick;
        switch (Page)
            {
                case 0://时间界面
                    LED0=1;LED1=0;LED2=0;
                    sprintf(Dsp_Bit, "%02bd-%02bd-%02bd",Time[0]*10+Time[1], Time[2]*10+Time[3],Time[4]*10+Time[5]);
                    break;
                case 1://输入界面
                    LED0=0;LED1=1;LED2=0;
                    if(Value)
                        sprintf(Dsp_Bit, "C   %4hu", Value);
                    else
                        sprintf(Dsp_Bit, "C              ");
                    
                    break;
                case 2://记录界面
                    LED0=0;LED1=0;LED2=1;
                    sprintf(Dsp_Bit, "E  %02bd-%02bd", Hour,Min);
                    break;
                default:
                    break;
            }   
        //sprintf(Dsp_Bit, "%9.2f", (float)KeyNum);
​
    }
    Seg_Tran();
}
​
/*******************************************************************************
函数名程:   void Key_Task(void)
函数功能:   按键执行任务,每2ms执行一次
参数列表:   
返回值  :
*******************************************************************************/
void Key_Task(void)
{
    static uint Key_Tick;                           
    char Key_Value;                         
    
    if((Tick - Key_Tick) > 2)
    {
        Key_Tick = Tick;
        
        Key_Value = MatKeyScan_4x4();
        switch (Page)
            {
                case 0://时间界面
                    switch (Key_Value)
                    {
                        case 4://切换到输入界面
                            Page=1; 
                        break;
                        default:
                            break;
                    }
                    break;
                case 1://输入界面
                    switch (Key_Value)
                    {
                        case 4://切换到记录界面
                            Page=2;
                            Hour=Time[0]*10+Time[1];
                            Min=Time[2]*10+Time[3];
                            Last_Value=Pre_Value;
                            //记录
                            AT24C02_WriteBuffer(&Hour,0, 1);
                            AT24C02_WriteBuffer(&Min,1, 1);
                            AT24C02_WriteBuffer((unsigned char*)&Value,2, 2);
                            LED3 =  (Value > Pre_Value) ? 1 : 0;    
                            Pre_Value=Value;
                        
                            //LED3=(Last_Value>Pre_Value)?1:0;//若本次记录的4位数据较上一次记录的4位数据大,则指示灯L4点亮,否则指示灯熄灭。
                            break;
                        case 5://清除按键
                            Value=0;
                            break;
                        case 6://显示0
                            Value=(Value>999)?Value:(Value*10+0);
                            break;
                        case 10://显示1
                            Value=(Value>999)?Value:(Value*10+1);
                            break;
                        case 14://显示2
                            Value=(Value>999)?Value:(Value*10+2);
                            break;
                        case 18://显示3
                            Value=(Value>999)?Value:(Value*10+3);
                            break;
                        case 9://显示4
                            Value=(Value>999)?Value:(Value*10+4);
                            break;
                        case 13://显示5
                            Value=(Value>999)?Value:(Value*10+5);
                            break;
                        case 17://显示6
                            Value=(Value>999)?Value:(Value*10+6);
                            break;
                        case 8://显示7
                            Value=(Value>999)?Value:(Value*10+7);
                            break;
                        case 12://显示8
                            Value=(Value>999)?Value:(Value*10+8);
                            break;
                        case 16://显示9
                            Value=(Value>999)?Value:(Value*10+9);
                            break;
                        default:
                            break;
                    }
                
                    break;
                case 2://记录界面
                    switch (Key_Value)
                    {
                        case 4://切换到时间界面
                            Page=0;         
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }   
    }
}   
​
/*******************************************************************************
函数名程:   void Data_Task(void)
函数功能:   定时处理数据的采集、处理、传输任务
参数列表:   
返回值  :
*******************************************************************************/
void Data_Task(void)
{
    static uint Data_Tick;
    
    if((Tick - Data_Tick) > 500)
    {   
        Data_Tick = Tick;
        Ds1302_ReadTime(Time);
    }
​
}
​
/*******************************************************************************
函数名程:   void Data_Task(void)
函数功能:   定时按一定逻辑执行任务
参数列表:   
返回值  :
*******************************************************************************/
void Logic_Task(void)
{
    static uint Logic_Tick;
    
    if((Tick - Logic_Tick) > 500)
    {   
        Logic_Tick = Tick;
    }
​
}
​
/*******************************************************************************
函数名程:   void P_Init(void)
函数功能:   外设初始化
参数列表:   
返回值  :
*******************************************************************************/
void P_Init(void)               //外设初始化
{
    CONTROL(LED,0xff);      //初始化LED熄灭
    CONTROL(DEVICE,0x00);   //初始化所有外设不工作
    CONTROL(BIT,0x00);      //初始化数码管位选无效
    CONTROL(SEG,0xff);      //初始化数码管段选无效
    //定时器T2时基1ms初始化
    Timer_2Init();
}
​
/*************************************************************
                      主函数
**************************************************************/
void main(void)
{
/********************初始化********************************************/
    P_Init();
    AT24C02_ReadBuffer(&Hour,0, 1);
    AT24C02_ReadBuffer(&Min,1, 1);
    AT24C02_ReadBuffer((unsigned char*)&Value,2, 2);
    Ds1302_SetTime(Time);
/********************功能函数*******************************************/
    while(1)
    {
        Display_Task();
        Key_Task();
        Data_Task();
        Logic_Task();
    }        
}

五、题目网址:

第十五届蓝桥杯单片机模拟考试I (4t.wiki)

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第十三届蓝桥杯单片机模拟题是一个使用单片机来实现一定功能的题目。具体要求如下: 题目要求使用单片机控制一个LED灯,根据输入的数字进行闪烁的频率控制。在开始时,需要通过按键输入一个0-9之间的数字,该数字代表了闪烁的频率,数字越大表示闪烁的频率越快。然后,用一个LED灯来表示这个输入的数字。 解决这个题目的思路如下: 首先,我们需要配置单片机的IO口,将一个IO口连接到LED灯上,用于控制LED的亮灭。 然后,我们需要添加中断功能,使得按键输入可以被响应。当按键被按下时,会触发一个外部中断,进入中断服务函数。 在中断服务函数中,我们可以通过读取按键的状态得到输入的数字,并将该数字储存起来。 接下来,我们使用定时器来控制LED灯的闪烁频率。我们设置一个定时器,周期性地执行一个中断服务函数。在这个中断服务函数中,我们可以控制LED灯的亮灭状态。利用先前输入的数字,可以确定LED灯的闪烁频率。 最后,我们需要在主函数中进行一些初始化操作,如配置IO口、中断和定时器,并进入一个无限循环中。在循环中,程序将一直等待按键输入,并根据输入的数字进行相关操作。 总结起来,第十三届蓝桥杯单片机模拟题通过按键输入一个数字来控制LED灯的闪烁频率。通过配置IO口、中断和定时器,我们可以实现这个功能。这道题目考察了对单片机的基本操作和中断定时器的使用,是一个综合性较强的题目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值