Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

MengFanjun的博客

最近几天闲着没事干,刷动态的时候,看到了十三届的模拟题,然后就去搜了搜,题目来源@电子设计工坊,我是从博主@slow_walker看到的题目,原blog的链接:https://blog.csdn.net/boybs/article/details/123829667

先看题目吧: 在这里插入图片描述

在这里插入图片描述 在这里插入图片描述

刚看的时候,感觉还是很简单的,没有乱七八糟的显示模式切换,也就用到了eeprom和PCF8591,后来往下仔细看,发现了长按键,我心态直接崩了,虽然之前十二届第二批的时候,做过长按键,但是是在大佬的帮助下,才做出来的,现在要自己做,心里总是害怕,做了三天,到最后还是做出来了,跟之前的第十二届第二批其实是一个思路,利用定时器,使一个数字每1s自加一次,然后再去判断。 但是另外一点我没有想到的是,在题目中,要求按下S8不触发储存功能,这个我思考了好久,其实就是需要引入一个中间变量,把eeprom显示界面的数值,赋值给他就好了,先看源代码吧。

IIC.C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/

#include "reg52.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;
}

IIC.H

1
2
3
4
5
6
7
8
9
10
11
#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);

#endif

MAIN.C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#include<reg51.h>
#include<iic.h>
#include<intrins.h>

#define uchar unsigned char

//矩阵按键配置
sbit R1=P3^0;//第一排初始化(如果跳线帽模式是BTN,则只有最左侧一列能用)
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;//第四列初始化

//////////////////////////// 0 1 2 3 4 5 6 7 8 9 - 全灭 .
unsigned char code shuzi[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0xbf,0xff,0x7f};
/////////////////////////// A b C d E F H L P U n
unsigned char code zimu[]={0x88,0x83,0xc6,0xa1,0x86,0x8e,0x89,0xc7,0x8c,0xc1,0xc8};
//////////////////////////// 0 1 2 3 4 5 6 7
unsigned char code weizhi[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00};
////////////////////////// 1 2 3 4 5 6 7 8 灭
unsigned char ledweizhi[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff};



uchar count=0;//计数数值
uchar count_z;//长按键判断值
int n;//定时器1的自加值
uchar num_re=0;//保存上一个值
uchar led_b;
uchar mode_led;
uchar temp_num;

void write_eeprom(unsigned char add,unsigned char date);
unsigned char read_eeprom(unsigned char add);
void ledlight(uchar x);


void Init_Keys()//配置矩阵键盘
{
R1=R2=R3=R4=1;
C1=C2=C3=C4=1;
}
void timer0() //定时模式
{
ET0=1;
EA=1;
TMOD &= 0xF0;
TH0 = (65535-50000)/256;//50000us=50ms
TL0 = (65535-50000)%256;
TF0 = 1;
TR0 = 1;
}
void Service_timer0() interrupt 1//定时器0,实现长按键功能
{
TH0 = (65535-50000)/256;//50000us=50ms
TL0 = (65535-50000)%256;
if(n==20)
{
n=0;
count_z++;
}
else n++;
}
//定时器1,定时1ms
void Timer1(void) //定时模式
{
TMOD &= 0x0F;
TL1 = (65535-20000)%256;
TH1 = (65535-20000)/256;
TF1 = 0;
TR1 = 1;
ET1 = 1;
}
void Timer1_Service() interrupt 3//定时器1的定时模式,控制led闪烁
{
uchar i;
i++;
if(i==10)
{
i=0;
led_b++;
if(mode_led==0)
{
mode_led=1;
}
else if(mode_led==1)
{
mode_led=0;
}
}
}
void led_blink()
{
if(mode_led==1)
{
ledlight(1);
}
if(mode_led==0)
{
P2=(P2&0X1f)|0x80;
P0=0xff;
}
}
//////延时1ms
void delay_ms(int ms)
{
int q,w;
for(q = 0;q<ms;q++){
for(w=845;w>0;w--);
}
}
void ledlight(uchar x)
{
P2=(P2&0X1f)|0x80;
P0=ledweizhi[x];
}
///数码管数字显示
void shumaguan_shuzi(uchar a,uchar b)
{
delay_ms(1);
P2=(P2&0X1f)|0xC0;P0=weizhi[a];
P2=(P2&0X1f)|0xE0;P0=shuzi[b];
delay_ms(1);
//消隐
P2 = (P2 & 0x1f) | 0xc0;
P0 = 0x00;
P2 = P2 & 0x1f;
}
//数码管字母显示
void shumaguan_zimu(uchar a,uchar b)
{
delay_ms(1);
P2=(P2&0X1f)|0xC0;P0=weizhi[a];
P2=(P2&0X1f)|0xE0;P0=zimu[b];
delay_ms(1);
//消隐
P2 = (P2 & 0x1f) | 0xc0;
P0 = 0x00;
P2 = P2 & 0x1f;
}
void display_count()//计数显示
{
shumaguan_zimu(0,0);

shumaguan_shuzi(5,count/100);
shumaguan_shuzi(6,count%100/10);
shumaguan_shuzi(7,count%10);
ledlight(0);
temp_num=num_re;

}
void display_re()//显示eeprom读取的数据
{
shumaguan_zimu(0,6);
num_re=read_eeprom(0x00);
shumaguan_shuzi(5,num_re/100);
shumaguan_shuzi(6,num_re%100/10);
shumaguan_shuzi(7,num_re%10);
temp_num=num_re;
}
void write_eeprom(unsigned char add,unsigned char date)//写入eepeom数据,前面是地址,后面是数据
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_eeprom(unsigned char add)//读eeprom,直接写出地址就能读,在read和write之间一定要间隔上delay
{
unsigned char temp;
EA = 0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();

IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_WaitAck();
IIC_Stop();
EA = 1;
return temp;
}
void pcf8591_dac(char dat)//dac读取的是16进制数值
{
EA=0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();

IIC_SendByte(0x40);
IIC_WaitAck();

IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();

EA=1;
}
void Scan_S4()
{
R4=0;R1=1;R2=1;R3=1;
C2=1;C3=1;C4=1;
if(C1==0&&R4==0)
{
while(C1==0)display_count();
count++;
}

}
void Scan_S5()
{
R4=1;R1=1;R2=1;R3=0;
C2=1;C3=1;C4=1;
if(C1==0&&R3==0)
{
while(C1==0)display_count();
count--;
}
}
void Scan_S8()
{
R4=0;R1=1;R2=1;R3=1;
C1=1;C3=1;C4=1;
if(C2==0&&R4==0)
{
n=0;
count_z=0;
while(C2==0) display_count();

delay_ms(10);
write_eeprom(0x00,count);
delay_ms(10);

while(C2==0)shumaguan_shuzi(0,count_z);

if(count_z>=2)
{
count=0;
delay_ms(10);
write_eeprom(0x00,temp_num);
delay_ms(10);
}
}
}
void Scan_S9()
{

uchar temp=4;
R4=1;R1=1;R2=1;R3=0;
C1=1;C3=1;C4=1;
if(C2==0)
{
while(C2==0);
temp++;
}
if(temp%2==0)
{
display_count();
}
if(temp%2==1)
{
while(1)
{
display_re();
if(C2==0)
{
while(C2==0);
break;
}
}
}
}
void judge()//判断读取的数值大小
{
if(count%5==0)
{
pcf8591_dac(255);
}
else pcf8591_dac(51);
if(count>num_re)
{
TR1=1;
}
else if(count<=num_re)
{
TR1=0;
}
}
void main()
{
Init_Keys();
timer0();
Timer1();
while(1)
{
Scan_S4();
Scan_S5();
Scan_S8();
Scan_S9();
judge();
led_blink();
display_count();
}
}

还有4天比赛了,这几天不打算去做省赛题了,我打算先去看看客观题,客观题毕竟也占好多分。

评论