藍橋杯比賽 單片機組 做題模板及模塊使用總結
- 前言
- 直接上代碼!
- 最后
前言
? 省賽將近,小伙伴們都在抓緊時間準備做省賽真題,今天宸哥用了一天的時間總結了一份適用于所有的題目的模板并把所有模塊的代碼都放到了一起,希望對大家比賽有幫助!!
直接上代碼!
# 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;
}
//國賽可能需要精確到小數點后幾位
/*if ((temp & 0xf800) == 0x0000)
{
temp = temp >> 4;//先把小數位都移走
temp = temp * 10;
temp = temp + (LSB & 0x0f) * 0.0625 * 10; //擴大十倍后的整數部分加上小數部分(小數部分每一個數表示0.0625 C)
}*/
}
//============================================================
//=======================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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/272951.html
標籤:其他
