第十一届蓝桥杯单片机模拟题

    科技2024-11-03  12

    个人自己写的程序,为当届比赛的一员,放在这里 ,希望能够检查出不足,或程序的优化,有更多的想法,希望评论(理性)

    程序代码

    库函数(include)iic协议AT24C02主程序ENABLE138代码矩阵键盘数码管显示 试题主要内容 跳跃键-试题内容. 主要时判断输入6个密码是否正确以及修改密码的操作,和AT24c02的编写。(个人理解)下面代码走起!

    库函数(include)

    #ifndef _INCLUDE_H_ #define _INCLUDE_H_ #define u16 unsigned int #define u8 unsigned char #define LED 4 #define ULN 5 #define WEI 6 #define DUAN 7 #include <STC15F2K60S2.H> #include <intrins.h> #include "smg.h" #include "jp.h" #include "iic.h" #include "enable138.h" #include "at24c02.h" extern u16 timer; extern u8 led; extern bit door; extern u16 count; #endif

    iic协议

    #include "iic.h" #define DELAY_TIME 5 #define SlaveAddrW 0xA0 #define SlaveAddrR 0xA1 sbit SDA = P2^1; /* 数据线 */ sbit SCL = P2^0; /* 时钟线 */ void IIC_Delay(unsigned char i) { do{_nop_();} while(i--); } void IIC_Start(void) { SDA = 1; SCL = 1; IIC_Delay(DELAY_TIME); SDA = 0; IIC_Delay(DELAY_TIME); SCL = 0; } void IIC_Stop(void) { SDA = 0; SCL = 1; IIC_Delay(DELAY_TIME); SDA = 1; IIC_Delay(DELAY_TIME); } void IIC_SendAck(bit ackbit) { SCL = 0; SDA = ackbit; // 0应答,1非应答 IIC_Delay(DELAY_TIME); SCL = 1; IIC_Delay(DELAY_TIME); SCL = 0; SDA = 1; IIC_Delay(DELAY_TIME); } bit IIC_WaitAck(void) { bit ackbit; SCL = 1; IIC_Delay(DELAY_TIME); ackbit = SDA; SCL = 0; IIC_Delay(DELAY_TIME); return ackbit; } void IIC_SendByte(unsigned char byt) { unsigned char i; for(i=0; i<8; i++) { SCL = 0; IIC_Delay(DELAY_TIME); if(byt & 0x80) SDA = 1; else SDA = 0; IIC_Delay(DELAY_TIME); SCL = 1; byt <<= 1; IIC_Delay(DELAY_TIME); } SCL = 0; } unsigned char IIC_RecByte(void) { unsigned char i, da; for(i=0; i<8; i++) { SCL = 1; IIC_Delay(DELAY_TIME); da <<= 1; if(SDA) da |= 1; SCL = 0; IIC_Delay(DELAY_TIME); } return da; }

    AT24C02

    #include "at24c02.h" void Delay5ms() //@12.000MHz { unsigned char i, j; i = 59; j = 90; do { while (--j); } while (--i); } void at24c02_write(u8 add, u8 dat) //add为地址 dat为数据 { EA = 0; IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_SendByte(dat); IIC_WaitAck(); IIC_Stop(); EA = 1; Delay5ms(); } u8 at24c02_read(u8 add) { u8 dat; EA = 0; IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_Start(); IIC_SendByte(0xa1); IIC_WaitAck(); dat = IIC_RecByte(); IIC_SendAck(1); EA = 1; return dat; } //写入多个数据 void at24c02_writestr(u8 start,u8 *pbuff, u8 num) { while(num) { at24c02_write(start,*pbuff); start++; pbuff++; num--; } } //读出多个数据 void at24c02_readstr(u8 start, u8 *pbuff, u8 num) { while(num) { *pbuff = at24c02_read(start); start++; pbuff++; num--; } }

    主程序

    #include "include.h" u16 timer = 0; u8 led = 0xff; u8 nkey; bit door = 0; //0¹ØÃÅ 1¹ØÃÅ u16 count = 0; void Timer0Init(void) { AUXR &= 0x7F; TMOD &= 0xF0; TL0 = 0x30; TH0 = 0xF8; TF0 = 0; TR0 = 1; ET0 = 1; EA = 1; //打开总开关 } void allint() //初始化 { P0 = 0xff; //led全熄灭 enable(LED); P0 = 0x00; //继电器,蜂鸣器关闭 enable(ULN); P0 = 0x00; enable(WEI); P0 = 0xff; enable(DUAN); } void led_run() //led显示 { P0 = led; enable(LED); } void main() { Timer0Init(); allint(); at24c02_writestr(0x00,mima,6); //将密码写入EEPROM buff_change(32,32,32,32,32,32,32,32); //将数码管熄灭 while(1) { nkey = jp_buff(); //判断键值 _nop_(); _nop_(); if (nkey != 0) //存在按下 nkey不为0 jp_choose(nkey); //进行选择 if (scan) //输入密码时的显示 { if (nnum == 0) { buff_change(36,32,32,32,32,32,32,32); } else if(nnum == 1) { buff_change(36,32,32,32,32,32,32,nmima[0]); } else if (nnum == 2) { buff_change(36,32,32,32,32,32,nmima[0],nmima[1]); } else if (nnum == 3) { buff_change(36,32,32,32,32,nmima[0],nmima[1],nmima[2]); } else if (nnum == 4) { buff_change(36,32,32,32,nmima[0],nmima[1],nmima[2],nmima[3]); } else if (nnum == 5) { buff_change(36,32,32,nmima[0],nmima[1],nmima[2],nmima[3],nmima[4]); } else if (nnum == 6 && tf == 2) { scan = 0; buff_change(36,32,nmima[0],nmima[1],nmima[2],nmima[3],nmima[4],nmima[5]); nnum = 0; } } else if (mscan) // 修改密码时的显示 { if (nnum == 0) { buff_change(12,32,32,32,32,32,32,32); //0输入 } if(nnum == 1) { buff_change(12,32,32,32,32,32,32,nmima[0]); //1输入 } else if (nnum == 2) { buff_change(12,32,32,32,32,32,nmima[0],nmima[1]); //2输入 } else if (nnum == 3) { buff_change(12,32,32,32,32,nmima[0],nmima[1],nmima[2]); //3输入 } else if (nnum == 4) { buff_change(12,32,32,32,nmima[0],nmima[1],nmima[2],nmima[3]); //4输入 } else if (nnum == 5) { buff_change(12,32,32,nmima[0],nmima[1],nmima[2],nmima[3],nmima[4]); //4输入 } else if (nnum == 6 ) { buff_change(12,32,nmima[0],nmima[1],nmima[2],nmima[3],nmima[4],nmima[5]); //5输入 } } } } void Tint0() interrupt 1 //2ms { smg_display(); led_run(); if(timer++ == 500) // 1s { timer = 0; if (count++ == 5) // 5s { count = 0; if (door == 0) // 门关 进入初始化状态 { led = 0xff; buff_change(32,32,32,32,32,32,32,32); } else if (door && notdo) // 门开启状态下 5秒没有操作 { door = 0; mscan = 0; P0 = 0x00; enable(ULN); buff_change(32,32,32,32,32,32,32,32); } } } }

    ENABLE138代码

    库文件就简单地声明

    #include "enable138.h" void enable(u8 x) { P2&= 0x1f; P2|=(x << 5); _nop_(); _nop_(); P2&= 0x1f; }

    矩阵键盘

    包括键值操作

    #include "jp.h" u8 KEY_UP=1; u16 tf = 0; //对错 u16 nnum = 0; //记录输入个数 bit notdo = 1; bit mscan = 0; //密码修改状态 bit scan = 0; //密码输入状态 u8 mima[6]= {8,8,8,8,8,8}; u8 nmima[6] = {0}; void Delay7ms() //@12.000MHz { unsigned char i, j; i = 82; j = 179; do { while (--j); } while (--i); } //额外操作 void tf_true() { P0 = 0x10; enable(ULN); door = 1; notdo = 1; scan = 0; nnum = 0; buff_change(0,32,32,32,0,34,14,35); // open } void mima_buff() { u16 i; timer = 0; count = 0; //判断对错 for (i = 0;i<6;i++) { if(mima[i]!= nmima[i]) { tf = 2; break; } else { tf =1; } } if(tf == 1) tf_true(); else if (tf == 2) { led = 0xfe; } } //输入存储,只计入前6位 void nmima_scan(u8 key1) { nmima[nnum] = key1; nnum++; if (nnum == 6) mima_buff(); } //密码修改 只计入前6位 void mima_scan(u8 key1) { nmima[nnum] = key1; nnum++; if (nnum == 6) { door = 1; timer = 0; count = 0; } } void jp_choose(u8 keys) { switch(keys) { case 10: //s9 if (scan) nmima_scan(keys - 1); else if (mscan) mima_scan(keys - 1); break; case 14: //s8 nnum = 0; break; case 15: //s12 timer =0; count = 0; if(mscan && nnum >= 6) //确认修改的密码 { mscan = 0; buff_change(12,32,32,32,32,32,32,32); scan = 0; nnum = 0; at24c02_writestr(0x00,nmima,6);//将密码写入EEROM at24c02_readstr(0x00, mima,6);//读取密码存入密码数组 } else if (door == 1) //进入修改模式 前提 门开 { nnum = 0; mscan = 1; scan = 0; } break; case 16: //s16 //进入输入密码模式 scan = 1; door =0; mscan =0; P0 = 0x00; enable(ULN); break; default: break; } } //键值判断(矩阵键盘) u8 jp_buff() { u8 keyvalue= 0;//1~16 u8 cache=0; u8 Hang=0; u8 Lie=0; P3&=0xc0; P3|=0x0f; P42=0; P44=0; if(((P3&0x0f)!=0x0f)&&(KEY_UP)) { Delay7ms(); P3&=0xc0; P3|=0x0f; P42=0; P44=0; if(((P3&0x0f)!=0x0f)&&(KEY_UP)) { KEY_UP=0; notdo = 0; cache=P3&0x0f; switch(cache) { case 0x0e:Hang=1; break; case 0x0d:Hang=2; break; case 0x0b:Hang=3; break; case 0x07:Hang=4; break; } P3&=0xf0; P3|=0x30; P42=1; P44=1; if(P44==0) Lie=1; else if(P42==0) Lie=2; else if(P35==0) Lie=3; else if(P34==0) Lie=4; keyvalue=Hang*4+Lie - 4; } } P3&=0xc0;//bit5 bit4¸´Î» P3|=0x0f;//bit3~bit0ÖÃλ P42=0; P44=0; if(((P3&0x0f)==0x0f)&&(!KEY_UP)) { KEY_UP=1; if (door) notdo = 1; } return keyvalue; }

    数码管显示

    #include "smg.h" u8 code smgDU[37] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E, // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0E, // 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. A. B. C. D. E. F. 0xff,0xbf,0x8c,0xc8,0xf7}; // Ãð - p n _ u8 smgWE[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//λѡ static u16 num =0; u16 smgbuff[8] = {32}; void buff_change(u16 d1,d2,d3,d4,d5,d6,d7,d8)//显示内容转换 { smgbuff[0] = d1; smgbuff[1] = d2; smgbuff[2] = d3; smgbuff[3] = d4; smgbuff[4] = d5; smgbuff[5] = d6; smgbuff[6] = d7; smgbuff[7] = d8; } void smg_display() //将数码管显示 { P0 = 0xff; enable(DUAN); P0 = smgWE[num]; enable(WEI); P0 = smgDU[smgbuff[num]]; enable(DUAN); num++; num &= 7; }

    部分变量为全局变量 如 timer,count,notdo,scan,mscan,led,door,KEY_UP,mima[6],nmima[6],nnum. 因为在库文件中声明,嫌代码太多没有放上。同时 库文件中的部分函数声明同理,请自己声明。不懂可参考我的 模板. 谢谢。

    Processed: 0.022, SQL: 8