当前位置: 首页 > news >正文

【提分必看!】蓝桥杯单片机提分技巧(国一经验分享)

目录

  • 前言
  • PCA可编程计数器阵列
    • PCA_Timer.c
    • PCA_Timer.h
  • 按键状态检测
  • 两种计时按键
  • PWM输出逻辑
  • 外部中断(以外中断0为例)
  • 数码管闪烁

前言

本人在(2024年)第十五届蓝桥杯竞赛单片机赛道中取得了全国一等奖的成绩。本文我将会和读者们分享蓝桥杯单片机竞赛可能会用到的提分技巧,帮读者们叩开国一的大门!
官方资料获取(已整合):
蓝桥杯单片机资源包(含指导手册和考点大纲)
优质教程推荐:
蚂蚁工厂科技蓝桥杯单片机教程
小蜜蜂蓝桥杯单片机基础技能与进阶强化教程
其他相关文章:
【国一超全代码分享!】蓝桥杯单片机各模块代码整合

PCA可编程计数器阵列

IAP15F2K61S2单片机只有定时器0、定时器1和定时器2三个定时器,有时我们会遇到定时器资源不够用的情况:NE555频率测量占用了定时器0,超声波测距占用了定时器1,定时器2用作了串口波特率发生器。这时我们会发现没有定时器进行周期计数为我们的业务逻辑提供(周期)中断服务。为了解决这个问题,我们要启动单片机中的PCA模块。

这里简单介绍一下PCA:
PCA(可编程计数器阵列Programmable Counter Array)有5个16位的捕获/比较模块与之相连,由高字节(PCA0H)和低字节(PCA0L)组成。
在这里我们只需要知道:PCA可以充当16位重装载的“定时器”使用

PCA_Timer.c

// PCA初始化
void PCA_TimerInit(void)
{// 这些只能背!CMOD |= 0x01;//初始化为系统时钟12分频 允许CCON中的CF中断CCON &= 0x00;// CF=0;CR=0;CL=0x18;CH=0xFC;  // 这里的值根据需要的定时时间手动设置CR=1;// 开启计数
}//中断回调函数
void PCA_isr() interrupt 7
{if(CF){CF=0;// 需要手动(软件)清零溢出标志位CL=0x18;// 需要手动重装载,定时器是自动重装载CH=0xFC;// 需要手动重装载,定时器是自动重装载// 下面添加自己的代码}
}

PCA_Timer.h

#include "STC15F2K60S2.H"void PCA_TimerInit(void);

按照以上操作,我们就可以把PCA当做定时器来用,这样就可以很大程度上解决编程过程中“定时器不够用”的问题。

按键状态检测

按键的底层代码参考:【国一超全代码分享!】蓝桥杯单片机各模块代码整合

// 声明四种状态
unsigned char Key_Value;  // 按键当前状态,0为低电平,1为高电平
unsigned char Key_Down;  // 下降沿
unsigned char Key_Up;  // 上升沿
unsigned char Key_Old;  // 按键的上一状态,0为低电平,1为高电平//
Key_Value = Read_KBD();  // 读取按键当前状态(这里KBD对应矩阵键盘)
Key_Down = Key_Value&(Key_Old^Key_Value);
Key_Up = ~Key_Value&(Key_Old^Key_Value);
Key_Old = Key_Value;

两种计时按键

近两年赛题都会涉及到按键长短按的考点,下面提供一个写法给大家。

// 注意tick和flag,最好都创建独立的,避免冲突
// 按下按键超过时间,LED直接亮
// Key_Value:检测按键保持高电平或低电平
// Key_Up:检测按键上升沿(即按下到松开的那一瞬间)
if(Key_Value==4 && led1_flag==0)
{if(led1_tick++>2000){led1_tick=0;led1_flag=1;ucLed^=0xF0;}
}
else
{if(led1_flag==0)  led1_tick=0;else if(led1_flag==1 && Key_Up==4)  led1_flag=0;
}// 按下按键超过时间,松开了按键,LED才亮
if(Key_Value==5 && led2_flag==0)
{if(led2_tick++>2000){led2_tick=0;led2_flag=1;}
}
else
{if(led2_flag==0)  led2_tick=0;else if(led2_flag==1 && Key_Up==5)  {led2_flag=0;ucLed^=0xF0;}
}

PWM输出逻辑

十三届国赛真题(如果没有记错的话)出了一次PWM输出的考点,要求某个引脚输出频率为1kHz,占空比为20%的PWM信号。之后大家在做到这道题的时候会发现,输出PWM信号并不难,但是输出PWM的代码一旦没写好,就很容易影响到其他模块(比如影响到温度读取或者时钟显示等)。以下是我的处理方法,通过这种处理能正常输出PWM信号,也可以不影响其他模块的正常使用。

if(pwm_flag==1)
{pp2_flag=0;if(pwm_tick<8){if(pp1_flag==0){pp1_flag=1;P0|=0x20;P2=P2&0x1F|0xA0;P2=P2&0x1F;}}else{if(pp1_flag==1){pp1_flag=0;P0|=0x00;P2=P2&0x1F|0xA0;P2=P2&0x1F;}}if(++pwm_tick==10)  pwm_tick=0;
}
else if(pwm_flag==0)
{pp1_flag=0;if(pwm_tick<2){if(pp2_flag==0){pp2_flag=1;P0|=0x20;P2=P2&0x1F|0xA0;P2=P2&0x1F;}}else{if(pp2_flag==1){pp2_flag=0;P0|=0x00;P2=P2&0x1F|0xA0;P2=P2&0x1F;}}if(++pwm_tick==10)  pwm_tick=0;
}

外部中断(以外中断0为例)

// 外部中断(这两句要写在main中)
IT0 = 0;                    //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX0 = 1;                    //使能INT0中断//-----------------------------------------
//中断服务程序
void exint0() interrupt 0       //INT0中断入口 INT0对应的应该是按键S5
{// 下面写要执行的任务ucLed ^= 0xff;
}

数码管闪烁

sprintf(seg_string,"P1    %2d"(unsigned int)dist);
if(shan_tick<2)  // 200ms亮灭闪烁
{seg_string[6]=' ';seg_string[7]=' ';
}
if(++shan_tick==4)  shan_tick=0;

http://www.mrgr.cn/news/15639.html

相关文章:

  • git 更改分支名称
  • SLAM的详细介绍,包括其基本原理、主要组件、算法类型、应用场景以及面临的挑战
  • 92. UE5 RPG 使用C++创建GE实现灼烧的负面效果
  • 使用手机挖掘IDOR漏洞赚取1500美元赏金
  • k8s声明式管理方式(yaml文件实现)
  • 20. Java中的fail-fast机制是什么?它是如何在集合中实现的?
  • Spring Bean加载耗时采集工具
  • python-带空格的数字层三角形
  • macos 系统 降级, 重装, 升级图文教程
  • 论文阅读——Compact Single-Feed Dual-Mode Antenna for Active RFID Tag Application
  • 华硕天选Air:开学季的性价比之巅
  • 无缝 CI/CD:如何在 Windows 环境中使用 Docker 和 Jenkins 自动化部署 .NET 应用
  • 数学符号-西格玛
  • 文件上传漏洞详解(持续更新…)
  • 加油卡系统开发,为什么加油卡系统这么受欢迎
  • Unity SceneView 相机聚焦到指定位置
  • Docker续5:docker部署nmt(mysql,nginx,tomcat)
  • 精选算法编程题
  • 《炉石传说》国服9月25日回归 预约活动上线:送金卡、皮肤
  • 金融上云方案中,国产虚拟化产品选型的重点考虑因素、自动化运维建设步骤及如何进行保障数据中心安全需求的存储设计等问题及解决方法|金融行业数字化QA合集③