前言
蓝桥杯第十一届省赛使用到的传感器并不是很多,主要是有那个E2PROM存储器,不过E2PROM存储器只要你会读和写的话,基本上不是很难的,但是要注意的是,E2PROM是不能连续写的,要有一个短的间隔,起码要延时5ms,不然你写入的内容将会是乱码。他的主要考点是那个门锁的逻辑,虽然传感器比较简单,但是门锁的逻辑是需要读者去认真思考一下的,那个门锁的逻辑也是一大难点。我这里主要是给读者完整代码,如果是初学者的话,请移步我的蓝桥杯单片机第十三届的省赛代码完整讲解,如果是初学者的话,看完之后也很容易上手了。
蓝桥杯单片机STC15F2K60S2第十三届省赛代码详细讲解(附完整代码)
试题
完整代码
iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"
#include "intrins.h"
#define DELAY_TIME 5
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
void E2PORM_Write(unsigned char Addr,unsigned char Data)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(Addr);
I2CWaitAck();
I2CSendByte(Data);
I2CWaitAck();
I2CStop();
}
unsigned char E2PORM_Read(unsigned char Addr)
{
unsigned char Byte;
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(Addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xA1);
I2CWaitAck();
Byte =I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return Byte;
}
iic
#ifndef __IIC_H__
#define __IIC_H__
#include <stc15.h>
#define sda P21
#define scl P20
void E2PORM_Write(unsigned char Addr,unsigned char Data);
unsigned char E2PORM_Read(unsigned char Addr);
#endif
display.c
#include <STC15F2K60S2.H>
code unsigned char Show_Number[]=
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,//0~9
0xbf, //- 10
0x8c, //P 11
0x86, //E 12
0xc8, //N 13
0xc6 //C 14
};
void Select_HC573(unsigned char Number)
{
switch(Number)
{
case 4:P2=(P2 &0x1f)|0x80;break;
case 5:P2=(P2 &0x1f)|0xA0;break;
case 6:P2=(P2 &0x1f)|0xC0;break;
case 7:P2=(P2 &0x1f)|0xE0;break;
}
P2=(P2 &0x1f)|0x00;
}
void System_Init(void)
{
P0 =0x00;
Select_HC573(5);
Select_HC573(6);
P0=0xff;
Select_HC573(4);
}
void Delayms(int n) //@12.000MHz
{
unsigned char data i, j;
int k;
for(k=0;k<n;k++)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void Display_Number(unsigned char Pos,unsigned char Data)
{
P0=0x01<<Pos -1;
Select_HC573(6);
P0=Show_Number[Data];
Select_HC573(7);
Delayms(1);
P0=0x01<<Pos -1;
Select_HC573(6);
P0=0xff;
Select_HC573(7);
}
void Display_LED(unsigned char Number,unsigned char State)
{
static unsigned char temp=0xff;
if(State)
{
switch(Number)
{
case 1:temp &=0xfe;break;
case 7:temp &=0xbf;break;
case 8:temp &=0x7f;break;
}
}
else
{
switch(Number)
{
case 1:temp |=0x01;break;
case 7:temp |=0x40;break;
case 8:temp |=0x80;break;
}
}
P0=temp;
Select_HC573(4);
}
void DisplayDian(unsigned char State)
{
static unsigned char temp=0x00;
if(State)
{
temp |=0x10;
}
else
{
temp &= 0x00;
}
P0=temp;
Select_HC573(5);
}
display.h
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
void Select_HC573(unsigned char Number);
void System_Init(void);
void Display_Number(unsigned char Pos,unsigned char Data);
void Delayms(int n); //@12.000MHz
void Display_LED(unsigned char Number,unsigned char State);
void DisplayDian(unsigned char State);
#define ON 1
#define OFF 0
#endif
main.c
#include <STC15F2K60S2.H>
#include "display.h"
#include "iic.h"
void Key_Board(void);
void Show_Switch(void);
unsigned char SertY(void);
void Timer1_Init(void); //50毫秒@12.000MHz
void Display_Password(void);
void Password_Init(void);
void Read_Password(void);
void Change(void);
void Clear(unsigned char Pos);
void Display_Change(void);
unsigned char Sert[6]={8,8,8,8,8,8};
unsigned char Sert_Number=0;
unsigned char In_Number[6];
unsigned char ShowFlag=1;
unsigned char PutFlag=0;
unsigned char ChangeFlag=0;
unsigned char WriteFlag=1;
unsigned char switching=0;
void main(void)
{
System_Init();
Timer1_Init();
if(E2PORM_Read(0x07)==0)
{
Password_Init();
}
while(1)
{
Key_Board();
Show_Switch();
}
}
void Key_Board(void)
{
unsigned char Key=0xff;
P34=0;P35=1;P42=1;P44=1;P3 |=0x0f;
Key =P3;Key &= 0x0f;
if(Key !=0x0f)
{
Delayms(5);
if(Key !=0x0f)
{
switch(Key)
{
case 0x0e: if(switching !=0 ){ //S19==1
In_Number[Sert_Number]=3;
if(Sert_Number!=6)Sert_Number++;
}break;
case 0x0d: if(switching !=0){
In_Number[Sert_Number]=7;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x07: switching=1;ShowFlag=1;PutFlag=1;Show_Switch();
break;
}
}
}
while(Key !=0x0f)
{
P3 |=0x0f;
Key =P3;Key &= 0x0f;
Show_Switch();
}
P35=0;P34=1;P42=1;P44=1;P3 |=0x0f;
Key =P3;Key &= 0x0f;
if(Key !=0x0f)
{
Delayms(5);
if(Key !=0x0f)
{
switch(Key)
{
case 0x0e:if(switching !=0){//S15
In_Number[Sert_Number]=2;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x0d: if(switching !=0){
In_Number[Sert_Number]=6;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x07:if(switching ==1){
switching=2;
ChangeFlag=1;
Sert_Number=0;
ShowFlag=0;PutFlag=0;
TR1=0;
DisplayDian(OFF);
WriteFlag=1;
Show_Switch();
break;
}
if(switching ==2){ChangeFlag=0;switching=0;Sert_Number=0;DisplayDian(OFF);
Show_Switch(); break;
}
}
}
}
while(Key !=0x0f)
{
P3 |=0x0f;
Key =P3;Key &= 0x0f;
Show_Switch();
}
P42=0;P34=1;P35=1;P44=1;P3 |=0x0f;
Key =P3;Key &= 0x0f;
if(Key !=0x0f)
{
Delayms(5);
if(Key !=0x0f)
{
switch(Key)
{
case 0x0e: if(switching !=0){//S11
In_Number[Sert_Number]=1;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x0d: if(switching !=0){
In_Number[Sert_Number]=5;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x0b: if(switching !=0){
In_Number[Sert_Number]=9;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x07: Sert_Number=0;switching=1;Show_Switch();
break;
}
}
}
while(Key !=0x0f)
{
P3 |=0x0f;
Key =P3;Key &= 0x0f;
Show_Switch();
}
P44=0;P34=1;P35=1;P42=1;P3 |=0x0f;
Key =P3;Key &= 0x0f;
if(Key !=0x0f)
{
Delayms(5);
if(Key !=0x0f)
{
switch(Key)
{
case 0x0e: if(switching !=0){//S7
In_Number[Sert_Number]=0;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x0d: if(switching !=0){
In_Number[Sert_Number]=4;
if(Sert_Number !=6)Sert_Number++;
}break;
case 0x0b: if(switching !=0){
In_Number[Sert_Number]=8;
if(Sert_Number !=6)Sert_Number++;
}break;
}
}
}
while(Key !=0x0f)
{
P3 |=0x0f;
Key =P3;Key &= 0x0f;
Show_Switch();
}
}
void Show_Switch(void)
{
if(switching==1)
{
Display_Number(1,10);
Display_Password();
if(Sert_Number==6){SertY();}
}
if(switching==2&& ChangeFlag )
{
TR1=0;
Display_Number(1,14);
Display_Change();
if(Sert_Number==6&&WriteFlag){
Display_Change();
Read_Password();
Delayms(5);
Change();
WriteFlag=0;
}
}
}
unsigned char SertY(void)
{
unsigned char i=0;
if(Sert_Number==6)
{
for(i=0;i<6;i++)
{
if(Sert[i] != In_Number[i])
{
Display_LED(1,ON);
Sert_Number=0;
switching=0;
TR1=1;
ChangeFlag=0;
return 0;
}
}
ChangeFlag=1;
return 1;
}
return 0;
}
void Timer1_Isr(void) interrupt 3
{
unsigned char ms;
unsigned char s;
ms++;
if(ms == 20)
{
s++;
ms=0;
if(s ==5)
{
s=0;
Sert_Number=0;
ChangeFlag=0;
switching=0;
Display_LED(1,OFF);
DisplayDian(OFF);
TR1=0;
}
}
}
void Timer1_Init(void) //50毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xB0; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
TF1 = 0; //清除TF1标志
// TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA=1;
TR1=0;
}
void Display_Password(void)
{
int i;
if(SertY() && Sert_Number==6 &&ShowFlag==1)
{
PutFlag=0;
Display_Number(1,14);
Display_Number(5,0);
Display_Number(6,11);
Display_Number(7,12);
Display_Number(8,13);
DisplayDian(ON);
TR1=1;
}
if(PutFlag || SertY()==0)
{
for (i = 0; i < Sert_Number; i++) {
Display_Number(8-i, In_Number[i]);
}
}
}
void Display_Change(void)
{
int i=0;
if(ChangeFlag)
{
for (i = 0; i < Sert_Number; i++) {
Display_Number(8-i, In_Number[i]);
}
}
}
void Password_Init(void)
{
E2PORM_Write(0x01,Sert[0]);
E2PORM_Write(0x02,Sert[0]);
E2PORM_Write(0x03,Sert[0]);
E2PORM_Write(0x04,Sert[0]);
E2PORM_Write(0x05,Sert[0]);
E2PORM_Write(0x06,Sert[0]);
E2PORM_Write(0x06,0);
}
void Change(void)
{
E2PORM_Write(0x01,Sert[0]);
E2PORM_Write(0x02,Sert[0]);
E2PORM_Write(0x03,Sert[0]);
E2PORM_Write(0x04,Sert[0]);
E2PORM_Write(0x05,Sert[0]);
E2PORM_Write(0x06,Sert[0]);
E2PORM_Write(0x07,1);
}
void Read_Password(void)
{
int i=0;
for(i=0;i<6;i++)
{
Sert[i]=In_Number[i];
}
}