蓝桥杯比赛 单片机组 做题模板及模块使用总结
- 前言
- 直接上代码!
- 最后
前言
省赛将近,小伙伴们都在抓紧时间准备做省赛真题,今天宸哥用了一天的时间总结了一份适用于所有的题目的模板并把所有模块的代码都放到了一起,希望对大家比赛有帮助!!
直接上代码!
# include "reg52.h"
# include "iic.h"
# include "onewire.h"
# include "ds1302.h"
# include "intrins.h" //延时函数基本单元_nop_() ——超声波模块
typedef unsigned char uchar;
typedef unsigned int uint;
sfr AUXR = 0x8e;
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;
sbit TX = P1^0; //发射接收超声波,T0,R1
sbit RX = P1^1;
uchar duanma[10] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar duanmadot[10] = { 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //由duanma高四位减去8得到
uchar Writeaddr [7] = { 0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
uchar Readaddr [7] = { 0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
uchar Timer[7] = { 0x00};//秒 分 时 日 月 周 年
//注意定义变量的类型,其他变量定义根据下面函数需要定义就可
uchar rb2 = 0;
uint count = 0;
bit smg_f = 0;
//===============矩阵键盘============== //J5脚KBD(打通P44)
sfr P4 = 0xC0;
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;
//=======================锁存器选择===========================
void SelectHC573(uchar n)
{
switch (n)
{
case 4:
P0 = (P0 & 0x1f) | 0x80;break;
case 5:
P0 = (P0 & 0x1f) | 0xa0;break;
case 6:
P0 = (P0 & 0x1f) | 0xc0;break;
case 7:
P0 = (P0 & 0x1f) | 0xe0;break;
case 0:
P0 = (P0 & 0x1f) | 0x00;break;
}
}
//============================================================
//====================LED、蜂鸣器、继电器=====================
//led 0有效
//蜂鸣器和继电器 1 有效
//============================================================
//=====================初始化函数=============================
void InitSystem ()
{
SelectHC573(4);
P0 = 0xff;
SelectHC573(5);
P0 = 0x00;
SelectHC573(0);
}
//============================================================
//=========================PCF8591============================
//读取电位器Rb2(03)或者光敏电阻rd1(01)
void ReadRd1 ()
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
rb2 = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
}
//PCF实现D/A、A/D
void PCFADC ()
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
rb2 = IIC_RecByte(); //(用的时候*1.961)
IIC_SendAck(1);
IIC_Stop();
}
void PCFDAC (uchar dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat); //输入255对应输出为5V
IIC_WaitAck();
IIC_Stop();
}
//============================================================
//=======================AT24C02==============================
uchar Read24c02 (uchar addr)
{
uchar temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void Write24c02 (uchar addr,uchar dat) //注意两次写入之间要延时1000(注意Delay的必须是uint类型的);还要注意写入和读取出来的数据都是小于255,否则需要处理才能写入
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
//============================================================
//=======================DS18B20==============================
void Read_Temp () //如果读取的温度有问题,那么应该将onewire.c中的延时时间统一扩大10倍
{
uchar LSB;
uchar MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
tem = (MSB << 8) | LSB;
if ((tem & 0xf800) == 0x0000) //省赛足以
{
tem = tem >> 4;
}
//国赛可能需要精确到小数点后几位
}
//============================================================
//=======================DS1302===============================
void Write_Timer () //需要Writeaddr[7]、Readaddr[7]、Timer[7]三个数组 //Timer[7]用数码管显示的需要/16
{
uchar i;
Write_Ds1302_Byte(0x8e,0x00);
for (i = 0;i <= 7;i++)
{
Write_Ds1302_Byte(Writeaddr[i],Timer[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
void Read_Timer ()
{
uchar i;
for (i = 0;i <= 7;i++)
{
Timer[i] = Read_Ds1302_Byte(Readaddr[i]);
}
}
//时钟BCD码加
uchar BCD_add(uchar dat)
{
dat = dat + 1;
switch (dat)
{
case 10:dat = 16;break;
case 26:dat = 32;break;
case 42:dat = 48;break;
case 58:dat = 64;break;
case 74:dat = 80;break;
case 90:dat = 0;break;
}
return dat;
}
//时钟BCD码减
uchar BCD_minus(uchar dat)
{
dat = dat - 1;
switch (dat)
{
case -1:dat =89;break;
case 79:dat = 73;break;
case 63:dat = 57;break;
case 47:dat = 41;break;
case 31:dat = 25;break;
case 15:dat = 9;break;
}
return dat;
}
//============================================================
//=========================定时器=============================
//T1(16位计时)定时100us,T0(8位自动重装计数)用作NE555 NE555自动输出一定频率的信号到SIGNAL引脚,用跳帽连接P34(T0),然后用定时器的T0计数功能
void InitTime ()
{
TMOD = 0x16;
TH1 = (65535 - 100) / 256;
TL1 = (65535 - 100) % 256;
TH0 = 0xff;
TL0 = 0xff;
TR0 = 1;
TR1 = 1;
ET0 = 1;
ET1 = 1;
EA = 1;
}
void ServiceT0 () interrupt 1
{
f_c ++;
}
void ServiceT1 () interrupt 3
{
TH1 = (65535 - 100) / 256;
TL1 = (65535 - 100) % 256;
count++;
if (count >= 10000)
{
dat_f = f_c;
count = 0;
f_c = 0;
}
//数码管实现秒闪
count++;
if (count >= 10000)
{
count = 0;
smg_f = ~smg_f;
}
//pwm脉宽调制 //共一百份,下面的函数给pwm_t赋值,pwm_f作为控制开关
pwm_c ++;
if (pwm_c >= pwm_t)
{
pwm_f = 0;
if (pwm_c >= 100)
{
pwm_c = 0;
pwm_f = 1;
}
}
}
//============================================================
//=======================外部中断=============================
void InitINT0 ()
{
IT0 = 1;
EX0 = 0;
EA = 1;
}
void ServiceINT0 () interrupt 0
{
//L8 = 0;
//Delay (60000);
//L8 = 1;
}
//============================================================
//===========================串口通信========================= //=================================================
void InitUart ()
{
TMOD = 0x21;
TH1 = 0xfd; //只能用T1口
TL1 = 0xfd;
TR1 = 1;
ES = 1;
EA = 1;
AUXR = 0x00;
SCON = 0x50;
}
void ServiceUart () interrupt 4
{
if (RI == 1)
{
command = SBUF;
RI = 0;
}
}
void SendByte (uchar dat)
{
SBUF = dat;
while (TI == 0);
TI = 0;
}
void SendString (uchar* addr)
{
uchar i = 0;
while (*addr != '\0')
{
SendByte(*addr);
addr = addr + 1;
}
}
void ExecuteCommand ()
{
if (command != 0x00)
{
switch (command & 0xf0)
{
case: 0xa0:
//
command = 0x00;
break;
case: 0xb0:
//
command = 0x00;
break;
//...
}
}
}
//============================================================
//====================数码管显示函数==========================
void Delay_SMG (uint t)
{
while (t--);
}
void ShowSMG_Bit (uchar pos,uchar dat)
{
SelectHC573(7);
P0 = 0xff;
SelectHC573(6);
P0 = 0x01 << pos - 1;
SelectHC573(7);
P0 = dat;
SelectHC573(0);
}
void All_SMG (uchar dat)
{
SelectHC573(6);
P0 = 0xff;
SelectHC573(7);
P0 = dat;
}
void ShowSMG ()
{
if (k4 == 0)
{
ShowSMG_Bit(1,0xc1);
Delay_SMG (500);
ShowSMG_Bit(6,duanmadot[dat_u / 100]);
Delay_SMG (500);
ShowSMG_Bit(7,duanma[(dat_u / 10) % 10]);
Delay_SMG (500);
ShowSMG_Bit(8,duanma[dat_u % 10]);
Delay_SMG (500);
}
else if (k4 == 1)
{
ShowSMG_Bit(1,0x8e);
Delay_SMG (500);
if (dat_f > 99999)
{
ShowSMG_Bit(3,duanma[(dat_f / 100000) % 10]);
Delay_SMG (500);
}
if (dat_f > 9999)
{
ShowSMG_Bit(4,duanma[(dat_f / 10000) % 10]);
Delay_SMG (500);
}
if (dat_f > 999)
{
ShowSMG_Bit(5,duanma[(dat_f / 1000) % 10]);
Delay_SMG (500);
}
if (dat_f > 99)
{
ShowSMG_Bit(6,duanma[(dat_f / 100) % 10]);
Delay_SMG (500);
}
if (dat_f > 9)
{
ShowSMG_Bit(7,duanma[(dat_f / 10) % 10]);
Delay_SMG (500);
}
ShowSMG_Bit(8,duanma[(dat_f / 1) % 10]);
Delay_SMG (500);
}
All_SMG(0xff);
}
//============================================================
//====================浏览(独立)按键========================
void DelayKey (uchar t)
{
while (t--);
}
void ScanKey ()
{
if (S4 == 0)
{
DelayKey (100);
if (S4 == 0)
{
while (S4 == 0)
{
}
//
}
}
if (S5 == 0)
{
DelayKey (100);
if (S5 == 0)
{
while (S5 == 0)
{
}
//
}
}
if (S6 == 0)
{
DelayKey (100);
if (S6 == 0)
{
while (S6 == 0)
{
}
//
}
}
if (S7 == 0)
{
DelayKey (100);
if (S7 == 0)
{
while (S7 == 0)
{
}
//
}
}
}
//============================================================
//=======================矩阵键盘=============================
void Scanjuzhenjianpan (void)
{
R1 = 0;
R2 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
//S7被按下
}
else if (C2 == 0)
{ }
else if (C3 == 0)
{ }
else if (C4 == 0)
{ }
R2 = 0;
R1 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
//S7被按下
}
else if (C2 == 0)
{ }
else if (C3 == 0)
{ }
else if (C4 == 0)
{ }
//....
}
//============================================================
//==========================超声波=============================
void Delay12us() //@12.000MHz //烧录软件生成的软件精准延时函数(stc_Y5)
{
unsigned char i;
_nop_();
_nop_();
i = 33;
while (--i);
}
void SendWave () //40KHZ,8组方波脉冲,TX发射
{
uchar i;
for (i = 0;i < 8;i++)
{
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
void DistanceMeasure () //定时器TH0,TL0从空开始计时
{
TMOD &= 0x0f; //TMOD = 0x00;
TH1 = 0x00; //定时器0也可以,到时候根据需要选择即可
TL1 = 0x00;
//ET1 = 1;
//EA = 1;
SendWave ();
TR1 = 1;
while ((RX == 1) && (TF1 == 0)); //如果没有溢出也没有接收到那就一直等,RX为低有效
TR1 = 0;
if (TF1 == 1)
{
distance = 999;
TF1 = 0; //溢出之后要把标志位恢复
}
else
{
time = (TH1 << 8) | TL1;
distance = time * 0.0172; //0.0172cm/us (来回)
}
}
void Delay (uchar n) //多次显示,效果更好一点
{
while (n--)
{
ShowSMG ();
}
}
//=========================================================
//========================主函数==============================
void main ()
{
while (1)
{
Delay(10);
}
}
//============================================================
最后
有了这个任何一个题目都可以写完2/3了,剩下的就是各部分之间的逻辑处理了,这个就考验个人能力了哦,毕竟这个比赛的目的就是培养选手独立处理实际问题的能力的~
创作不易,点个赞支持一下吧,抱拳了!!!
除此之外,有需要的小伙伴可以随时评论或者私信我,讨论学习过程中的问题,我会尽我所能提供一些帮助的
温馨提示: 后期我计划会发一个分享的视频,关注我不容易让文章走丢哦!
其他蓝桥杯相关内容参见——https://blog.csdn.net/weixin_45386875/article/details/113861559