这一届的模拟题还是比较难的,用到了两个通讯协议,需要采集电压、频率、读取时间、保存参数及超压低压数据。
在写矩阵键盘模块代码时,不能对P34进行操作,否则会影响频率测量,实际上只用到前两列按键,完全可以避免P34。
频率每隔一秒刷新,即读取计数器0的中断函数里的计数值。
另外不知道为什么在定时器中断函数里对eeprom写操作会导致写入数据错误,因此只能放在主函数。
题目
main.c
#include<stc15f2k60s2.h>
#include <intrins.h>
#define uchar unsigned char
#define s0 0
#define s1 1
#define s2 3
#define s3 2
void init_ds1302(char t[]);
void init_ds1302_main(char t[]);
char * read_ds1302();
void write_eeprom(uchar add, char dat);
char read_eeprom(uchar add);
int read_vol( );
code uchar semg[12] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
0xbf, 0xff};
code uchar semg_bit[8] = {0x01, 0x2, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
uchar semg_temp[8] = {11, 11, 11, 11, 11, 11, 11, 11};
char time[3] = {13, 59, 59};
char vre[2] = {20, 10};
char event[4] = {0};
char temp_fre[5] = {0};
uchar state = s0;
int vol = 1234;
int fre = 1000;
int count = 0;
uchar c = 0;
void Delay400ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 17;
j = 208;
k = 27;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay4ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 44;
j = 4;
do
{
while (--j);
} while (--i);
}
void allinit(void) //2毫秒@11.0592MHz
{
P2 = 0x80; P0 = 0xff;
P2 = 0xa0; P0 = 0x00;
P2 = 0xc0; P0 = 0xff;
P2 = 0xe0; P0 = 0xff;
}
void TimerInit(void) //2毫秒@11.0592MHz
{
AUXR = 0xc0; //定时器时钟1T模式
TMOD = 0x06; //设置定时器模式
TL0 = TH0 = 0xff; //fill with 0xff to c one time
TL1 = 0x9A; //设置定时初值
TH1 = 0xA9; //设置定时初值
TF1 = 0; //清除TF1标志
TR0 = 1; //定时器1开始计时
TR1 = 1; //定时器1开始计时
ET0 = 1;
ET1 = 1;
EA = 1;
}
void disfun(uchar i, int j)
{
if(j < 500)
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
else
{
P2 = 0xe0; P0 = 0xff; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
}
void display()
{
static uchar i = 0;
static int j = 0;
P0 = 0xff;
j++;
if(j == 1000)
j = 0;
if(state == s0)
{
if(c == 1)
{
if(i == 0 || i == 1)
disfun(i, j);
else
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
}
else if(c == 2)
{
if(i == 3 || i == 4)
disfun(i, j);
else
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
}
else if(c == 3)
{
if(i == 6 || i == 7)
disfun(i, j);
else
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
}
else
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
}
else if(state == s1)
{
if(c != 0)
{
if( i < (c * 4) && i >= (c * 4 - 4) )
disfun(i, j);
else
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
}
else
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
}
else
{
P2 = 0xe0; P0 = semg[semg_temp[i]]; P2 = 0x00;
P2 = 0xc0; P0 = semg_bit[i]; P2 = 0x00;
}
P0 = 0xff;
i++;
if(i == 8)
i = 0;
}
void fun0() interrupt 1
{
count++;
}
void fun1() interrupt 3
{
static int c_fre = 0, j = 0;
static uchar state_vre = s0;
uchar k;
int div = 1000;
char *temp;
display();
/***存时间、电压参数,取频率各位数值***/
if(state == s0)
{
if(c != 0)
init_ds1302(&time);
}
else if(state == s2)
{
/***读频率***/
c_fre++;
if(c_fre >= 500)
{
TR0 = 0;
if(c == 1)
{
if(count != 0)
fre = 1000000 / count;
else
fre = 0;
}
else
fre = count;
div = 10000;
for(k = 0; k < 5; k++)
{
temp_fre[k] = fre / div;
fre = fre - temp_fre[k] * div;
div = div / 10;
}
c_fre = 0;
count = 0;
TR0 = 1;
}
}
/***每隔0.2秒读取电压及时间***/
j++;
if(j >= 100)
{
j = 0;
vol = read_vol();
temp = read_ds1302();
time[0] = temp[0];
time[1] = temp[1];
time[2] = temp[2];
/***状态机判断电压情况 并保事件及其发生时间***/
switch(state_vre)
{
case s0:
{
if(vol > vre[0] * 100)
{
event[0] = 1;
event[1] = time[0];
event[2] = time[1];
event[3] = time[2];
state_vre = s1;
}
else if(vol < vre[1] * 100)
{
event[0] = 0;
event[1] = time[0];
event[2] = time[1];
event[3] = time[2];
state_vre = s1;
}
else
state_vre = s0;
} break;
case s1:
{
if(vol >= vre[1] * 100 && vol <= vre[0] * 100)
state_vre = s0;
} break;
default: state_vre = s0; break;
}
if(c == 0 && state == s1)
{
div = 1000;
for(k = 0; k < 3; k++)
{
temp_fre[k] = vol / div;
vol = (vol - temp_fre[k] * div);
div = div / 10;
}
}
}
}
char keyscan()
{
char keyvalue;
static uchar keystate = s0;
uchar keyrow, keycloumn, keycode, i, j;
P3 = P3 | 0x0f; P44 = 0; P42 = 0;
keyrow = P3 & 0x0f;
P3 = P3 & 0xf0; P44 = 1; P42 = 1;
if(P44 == 0) keycloumn = 0x70;
else if(P42 == 0) keycloumn = 0xb0;
else keycloumn = 0xf0;
keycode = ~(keyrow | keycloumn);
switch(keystate)
{
case s0:
if(keycode)
keystate = s1;
else
keyvalue = -1;
break;
case s1:
{
if(keycode)
{
for(i =0; i< 4; i++)
for(j =0; j< 4; j++)
if(keycode == (0x80 >> i | 0x08 >> j))
{
keyvalue = (i + 1) * 4 + j ;
break;
}
keystate = s2;
}
else
keystate = s0;
} break;
case s2:
{
keyvalue = -1;
if(!keycode)
keystate = s0;
} break;
default: keystate = s0; break;
}
return keyvalue;
}
void menu(char keyvalue)
{
uchar i = 0;
if(keyvalue == 4)
c++;
semg_temp[0] = c;
switch(state)
{
case s0:
{
semg_temp[0] = time[0] / 10;
semg_temp[1] = time[0] % 10;
semg_temp[2] = 10;
semg_temp[3] = time[1] / 10;
semg_temp[4] = time[1] % 10;
semg_temp[5] = 10;
semg_temp[6] = time[2] / 10;
semg_temp[7] = time[2] % 10;
if(c != 0)
{
if(keyvalue == 11)
{
time[c - 1] = time[c - 1] + 1;
if(c == 1)
{
if(time[c - 1] > 23)
time[c - 1] = 0;
}
else
{
if(time[c - 1] > 59)
time[c - 1] = 0;
}
}
else if(keyvalue == 10)
{
time[c - 1] = time[c - 1] - 1;
if(c == 1)
{
if(time[c - 1] < 0)
time[c - 1] = 23;
}
else
{
if(time[c - 1] < 0)
time[c - 1] = 59;
}
}
}
else ;
if(keyvalue == 6)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s1;
}
else if(keyvalue == 5)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s2;
}
else if(keyvalue == 9)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s3;
}
else ;
if(c == 4)
c = 0;
} break;
case s1:
{
if(c != 0)
{
semg_temp[0] = vre[0] / 10;
semg_temp[1] = vre[0] % 10;
semg_temp[2] = 0;
semg_temp[3] = 0;
semg_temp[4] = vre[1] / 10;
semg_temp[5] = vre[1] % 10;
semg_temp[6] = 0;
semg_temp[7] = 0;
if(keyvalue == 11)
{
vre[c - 1] = vre[c - 1] + 5;
if(vre[c - 1] > 50)
vre[c - 1] = 0;
}
else if(keyvalue == 10)
{
vre[c - 1] = vre[c - 1] - 5;
if(vre[c - 1] < 0)
vre[c - 1] = 50;
}
write_eeprom(4, vre[0]);
write_eeprom(5, vre[1]);
}
else
{
semg_temp[0] = 10;
semg_temp[1] = 1;
semg_temp[2] = 10;
semg_temp[3] = 11;
for(i = 4; i < 8; i++)
semg_temp[i] = temp_fre[i - 4];
}
if(keyvalue == 7)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s0;
}
else if(keyvalue == 5)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s2;
}
else if(keyvalue == 9)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s3;
}
else ;
if(c == 3)
c = 0;
} break;
case s2:
{
semg_temp[0] = 10;
semg_temp[1] = 2;
semg_temp[2] = 10;
for(i = 3; i < 8; i++)
semg_temp[i] = temp_fre[i - 3];
if(keyvalue == 7)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s0;
}
else if(keyvalue == 6)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s1;
}
else if(keyvalue == 9)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s3;
}
else ;
if(c == 2)
c = 0;
} break;
case s3:
{
if(c != 0)
{
semg_temp[0] = event[1] / 10;
semg_temp[1] = event[1] % 10;
semg_temp[2] = 10;
semg_temp[3] = event[2] / 10;
semg_temp[4] = event[2] % 10;
semg_temp[5] = 10;
semg_temp[6] = event[3] / 10;
semg_temp[7] = event[3] % 10;
}
else
{
semg_temp[6] = 0;
semg_temp[7] = event[0];
for(i = 0; i < 6; i++)
{
semg_temp[i] = 11;
}
}
if(keyvalue == 7)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s0;
}
else if(keyvalue == 6)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s1;
}
else if(keyvalue == 5)
{
c = 0;
for(i = 0; i < 8; i++)
semg_temp[i] = 11;
state = s2;
}
else ;
if(c == 2)
c = 0;
} break;
default: state = s0; break;
}
}
void main()
{
char keyvalue;
uchar i;
init_ds1302_main(&time);
vol = read_vol();
for(i = 0; i < 4; i++)
event[i] = read_eeprom(i);
for(i = 4; i < 6; i++)
{
vre[i - 4] = read_eeprom(i);
if((vre[i - 4] % 5 != 0) || (vre[i - 4] > 50))
{
vre[0] = 20;
vre[1] = 10;
}
}
allinit();
TimerInit( );
Delay400ms();
while(1)
{
keyvalue = keyscan();
menu(keyvalue);
for(i = 0; i < 4; i++)
write_eeprom(i, event[i]);
Delay4ms();
}
}
iic.c
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#define uchar unsigned char
#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);
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
if(SDA)
{
SCL = 0;
IIC_Stop( );
return 0;
}
else
{
SCL = 0;
return 1;
}
}
//通过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 write_eeprom(uchar add, char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
char read_eeprom(uchar add)
{
char dat;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
dat = IIC_RecByte();
IIC_Stop();
return dat;
}
int read_vol( )
{
uchar dat;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat = IIC_RecByte();
IIC_Stop();
return (dat * 19.6078);
}
ds1302.c
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return temp;
}
void init_ds1302_main(char *time)
{
uchar addr, i;
addr = 0x84;
Write_Ds1302_Byte(0x8e, 0x00);
for(i = 0; i < 3; i++)
{
Write_Ds1302_Byte(addr, ( (time[i]/10) << 4 | time[i] % 10) );
addr -= 2;
}
Write_Ds1302_Byte(0x8e, 0x80);
}
void init_ds1302(char *time)
{
uchar addr, i;
addr = 0x84;
Write_Ds1302_Byte(0x8e, 0x00);
for(i = 0; i < 3; i++)
{
Write_Ds1302_Byte(addr, ( (time[i]/10) << 4 | time[i] % 10) );
addr -= 2;
}
Write_Ds1302_Byte(0x8e, 0x80);
}
char * read_ds1302()
{
uchar addr, i;
char time[3];
addr = 0x85;
Write_Ds1302_Byte(0x8e, 0x00);
for(i = 0; i < 3; i++)
{
time[i] = Read_Ds1302_Byte(addr);
time[i] = (time[i] / 16) * 10 + time[i] % 16;
addr -= 2;
}
Write_Ds1302_Byte(0x8e, 0x80);
return time;
}