DT9025A / lanqiao

蓝桥杯 单片机组 备赛
MIT License
0 stars 0 forks source link

关于第九届题写过程中遇到的一个问题。 #3

Closed yueyuan123 closed 2 years ago

yueyuan123 commented 2 years ago

我先简单描述一下,就是上电全关,随便按一个独立按键激活,S6键调设置(模式和延时),但是调完设置不是数码管全关嘛,关完led就不动了,等好一会儿才动。我再继续研究半个小时,起床了你看看吧,老哥儿

yueyuan123 commented 2 years ago

这是main.c:

include

include "iic.h"

include "intrins.h"

define uchar unsigned char

define S7 P30

define S6 P31

define S5 P32

define S4 P33

void delay(int ms); void display1(uchar yi,uchar er,uchar san,uchar si); void display2(uchar wu,uchar liu,uchar qi,uchar ba); void Timer0Init(void); void keyscan();

uchar num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xbf,0xff}; uchar yi,er,san,si,wu,liu,qi,ba; int led_time=400,mode=0,ss,ssmode,digmode=0,tt; bit spst,sb=1; uchar RB2,led;

int main() { P2=0XA0;P0=0X00;P2=0X80;P0=0XFF; led_time=eeprom_read(0x00)*100;delay(5); mode=eeprom_read(0x01);delay(5); Timer0Init(); while(1) { RB2=ad_read(0x03); if(sb==1){yi=21;er=21;san=21;si=21;wu=21;liu=21;qi=21;ba=21;} if((sb==0)&&(digmode==1)){if(ssmode==0){yi=20;er=mode;san=20;si=21;if(led_time>=1000){wu=led_time/1000;}else{wu=21;}liu=led_time%1000/100;qi=led_time%100/10;ba=led_time%10;} else {yi=21;er=21;san=21;si=21;if(led_time>=1000){wu=led_time/1000;}else{wu=21;}liu=led_time%1000/100;qi=led_time%100/10;ba=led_time%10;}} else if((sb==0)&&(digmode==2)){if(ssmode==0){yi=20;er=mode;san=20;si=21;if(led_time>=1000){wu=led_time/1000;}else{wu=21;}liu=led_time%1000/100;qi=led_time%100/10;ba=led_time%10;} else {yi=20;er=mode;san=20;si=21;wu=21;liu=21;qi=21;ba=21;}}

    if((sb==0)&&(digmode==0)&&(mode==1)){yi=21;er=21;san=21;si=21;wu=21;liu=21;qi=21;ba=21;P2=0X80;P0=~(0X01<<led);}

    if(spst==0){ET0=1;EA=1;}else {ET0=0;EA=0;}

    keyscan();
    display1(yi,er,san,si);
    display2(wu,liu,qi,ba);
}

}

void keyscan() { if(S7==0) { delay(5); if(S7==0) {if(sb==1){sb=0;} else {spst=~spst;} }while(!S7); } else if(S6==0) { delay(5); if(S6==0) {if(sb==1){sb=0;} else { digmode++; if(digmode>2){digmode=0;}} }while(!S6); } else if(S5==0) { delay(5); if(S5==0) {if(sb==1){sb=0;} else{ if(digmode==1){mode++;if(mode>4){mode=1;}} else if(digmode==2){led_time+=100;if(led_time>1200){led_time=400;}}} }while(!S5); } else if(S4==0) { delay(5); if(S4==0) {if(sb==1){sb=0;} else{ if(digmode==1){mode--;if(mode<1){mode=4;}} else if(digmode==2){led_time-=100;if(led_time<400){led_time=1200;}}}
}while(!S4); } eeprom_write(0x01,mode);delay(5); eeprom_write(0x00,led_time/100);delay(5); } void time0() interrupt 1 { ss++;tt++; if(ss==800){ssmode=~ssmode;ss=0;} if((digmode==0)&&(mode==1)&&(tt==led_time)){led++;if(led>=8){led=0;}tt=0;} } void Timer0Init(void) //1毫秒@11.0592MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0xCD; //设置定时初始值 TH0 = 0xD4; //设置定时初始值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 }

void delay(int ms) { int i,j; for(i=0;i<ms;i++) for(j=0;j<845;j++); }

void display1(uchar yi,uchar er,uchar san,uchar si) { P2=0XC0;P0=0X01; P2=0XE0;P0=num[yi]; delay(2);

P2=0XC0;P0=0X02;
P2=0XE0;P0=num[er];
delay(2);

P2=0XC0;P0=0X04;
P2=0XE0;P0=num[san];
delay(2);

P2=0XC0;P0=0X08;
P2=0XE0;P0=num[si];
delay(2);

} void display2(uchar wu,uchar liu,uchar qi,uchar ba) { P2=0XC0;P0=0X10; P2=0XE0;P0=num[wu]; delay(2);

P2=0XC0;P0=0X20;
P2=0XE0;P0=num[liu];
delay(2);

P2=0XC0;P0=0X40;
P2=0XE0;P0=num[qi];
delay(2);

P2=0XC0;P0=0X80;
P2=0XE0;P0=num[ba];
delay(2);

} 这是iic.c:

include "stc15f2k60s2.h"

include "intrins.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;

}

//通过I2C总线发送数据 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;  

}

//从I2C总线上接收数据 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;
} void eeprom_write(unsigned char add,unsigned char dat) { IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_SendByte(dat); IIC_WaitAck(); IIC_Stop(); } unsigned char eeprom_read(unsigned char add) { unsigned char temp; IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_Stop();

IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();

return temp;

} unsigned char ad_read(unsigned char add) { unsigned char temp; IIC_Start(); IIC_SendByte(0x90); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_Stop();

IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();

return temp;

} 这是iic.h:

ifndef _IIC_H

define _IIC_H

void IIC_Start(void); void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit); void IIC_SendByte(unsigned char byt); unsigned char IIC_RecByte(void); unsigned char eeprom_read(unsigned char add); void eeprom_write(unsigned char add,unsigned char dat); unsigned char ad_read(unsigned char add);

endif

yueyuan123 commented 2 years ago

我怀疑是中断自身的问题,但是没有仿真没办法证明,也没办法看到底是哪里有问题

yueyuan123 commented 2 years ago

老哥儿帮帮我啊,别不理我

yueyuan123 commented 2 years ago

兄弟,我仿真了一下,找到问题了,跟你说一下,是因为tt是int,因为设置的时候定时器没停止,tt加到超过我设置的led_time这个值了,所以即便设置完led还是不动,一直tt加到上限回到0,led才开始动。这就是为什么等几分钟led才动。

yueyuan123 commented 2 years ago

直接在模式那里写一个tt=0;完美解决

DT9025A commented 2 years ago

这是好的