



iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "iic.h"
#include "intrins.h"
sbit scl = P2^0;
sbit sda = P2^1;
#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);
}
unsigned int Read_PCF8591()
{
unsigned int temp;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x03);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
temp = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return temp;
}
void Write_AT24C02_Page(unsigned char *buf,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(0x00);
I2CWaitAck();
while(num--)
{
I2CSendByte(*buf++);
I2CWaitAck();
}
I2CStop();
}
void Read_AT24C02_Page(unsigned char *buf,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(0x00);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(num--)
{
*buf++ = I2CReceiveByte();
if(num) I2CSendAck(0);
else I2CSendAck(1);
}
I2CStop();
}
iic.h
#ifndef __iic_h
#define __iic_h
static void I2C_Delay(unsigned char n);
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);
unsigned int Read_PCF8591();
void Write_AT24C02_Page(unsigned char *buf,unsigned char num);
void Read_AT24C02_Page(unsigned char *buf,unsigned char num);
#endif
ds1302.c
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
//
#include <STC15F2K60S2.H>
#include "ds1302.h"
#include "intrins.h"
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
code unsigned char Write_addr[] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
code unsigned char Read_addr[] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char time[] = {0x55,0x59,0x23};
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 Write_time()
{
char i;
Write_Ds1302_Byte(0x8e,0x00);
for(i = 0;i < 3;i++)
Write_Ds1302_Byte(Write_addr[i],time[i]);
Write_Ds1302_Byte(0x8e,0x80);
}
void Write_new_time(unsigned char index,dat)
{
Write_Ds1302_Byte(0x8e,0x00);
Write_Ds1302_Byte(Write_addr[index],dat);
Write_Ds1302_Byte(0x8e,0x80);
}
void Read_time()
{
char i;
for(i = 0;i < 3;i++)
time[i] = Read_Ds1302_Byte(Read_addr[i]);
}
ds1302.h
#ifndef __ds1302_h
#define __ds1302_h
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte ( unsigned char address );
void Write_time();
void Read_time();
void Write_new_time(unsigned char index,dat);
#endif
sys.c
#include <STC15F2K60S2.H>
#include "sys.h"
void Delay_ms(unsigned int t) //@12.000MHz
{
while(t--)
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void Select_Hc573(char n)
{
switch(n)
{
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 ;
}
void Sys_Init()
{
P0 = 0x00;
Select_Hc573(5);
P0 = 0xff;
Select_Hc573(4);
}
void Select_Bit(unsigned char pos,dat)
{
P0 = 0x01 << pos;
Select_Hc573(6);
P0 = dat;
Select_Hc573(7);
Delay_ms(1);
P0 = 0xff;
Select_Hc573(7);
}
sys.h
#ifndef __sys_h
#define __sys_h
void Delay_ms(unsigned int t);
void Select_Hc573(char n);
void Sys_Init();
void Select_Bit(unsigned char pos,dat);
#endif
main.c
#include <STC15F2K60S2.H>
#include "iic.h"
#include "ds1302.h"
#include "sys.h"
sbit R1 = P3^0;
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;
code unsigned char SMG[] = {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F,~0x40};
extern unsigned char time[];
unsigned char count1,count2,count3,count4,count5,count6;
unsigned int fre;//频率
unsigned int v;//电压
int v_up = 2000,v_down = 1000;//电压上下限
unsigned int fre_zhouqi;//频率周期
bit flag_10ms;
unsigned char key_val;
bit mode_fre;//0-频率 1-周期
bit type;//事件类型
unsigned char time_happen[3];
unsigned char mode;
bit shi,fen,miao;
unsigned char mode_time;//0-时钟界面 1-设置小时 2-分钟 3-秒
unsigned char mode_v;//0-电压界面 1-上限 2-下限
bit up,down;
unsigned char save[8];
unsigned char rec[8];
char i;
bit mode_thing;//0-类型 1-时间
void Timer1Init(void) //10毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD = 0x05; //设置定时器模式
TL1 = 0xF0; //设置定时初值
TH1 = 0xD8; //设置定时初值
TH0 = TL0 = 0;
TF1 = 0; //清除TF1标志
TR0 = TR1 = 1; //定时器1开始计时
ET0 = ET1 = 1;
EA = 1;
}
void Timer1_isr() interrupt 3
{
if(++count1 > 100)
{
count1 = 0;
fre = TH0 << 8 | TL0;
TH0 = TL0 = 0;
}
flag_10ms = 1;
switch(mode_time)
{
case 0:shi = fen = miao = 0;break;
case 1:
if(++count2 > 100)
{
count2 = 0;
shi = ~shi;fen = miao = 0;
}
break;
case 2:
if(++count3 > 100)
{
count3 = 0;
fen = ~fen;shi = miao = 0;
}
break;
case 3:
if(++count4 > 100)
{
count4 = 0;
miao = ~miao;fen = shi = 0;
}
break;
}
switch(mode_v)
{
case 0:up = down = 0;break;
case 1:
if(++count5 > 100)
{
count5 = 0;
up = ~up;down = 0;
}
break;
case 2:
if(++count6 > 100)
{
count6 = 0;
down = ~down;up = 0;
}
break;
}
}
void Display_time()//时间界面
{
Select_Bit(0,SMG[time[2] / 16]);
Select_Bit(1,SMG[time[2] % 16]);
Select_Bit(2,SMG[10]);
Select_Bit(3,SMG[time[1] / 16]);
Select_Bit(4,SMG[time[1] % 16]);
Select_Bit(5,SMG[10]);
Select_Bit(6,SMG[time[0] / 16]);
Select_Bit(7,SMG[time[0] % 16]);
}
void Display_time_set()//时间设置界面
{
if(!shi)
{
Select_Bit(0,SMG[time[2] / 16]);
Select_Bit(1,SMG[time[2] % 16]);
}
else
{
Select_Bit(0,0xff);
Select_Bit(1,0xff);
}
Select_Bit(2,SMG[10]);
if(!fen)
{
Select_Bit(3,SMG[time[1] / 16]);
Select_Bit(4,SMG[time[1] % 16]);
}
else
{
Select_Bit(3,0xff);
Select_Bit(4,0xff);
}
Select_Bit(5,SMG[10]);
if(!miao)
{
Select_Bit(6,SMG[time[0] / 16]);
Select_Bit(7,SMG[time[0] % 16]);
}
else
{
Select_Bit(6,0xff);
Select_Bit(7,0xff);
}
}
void Display_v()//电压测量
{
Select_Bit(0,SMG[10]);
Select_Bit(1,SMG[1]);
Select_Bit(2,SMG[10]);
Select_Bit(4,SMG[v / 1000]);
Select_Bit(5,SMG[v / 100 % 10]);
Select_Bit(6,SMG[v / 10 % 10]);
Select_Bit(7,SMG[v % 10]);
}
void Display_v_set()//电压阈值设置
{
if(!up)
{
Select_Bit(0,SMG[v_up / 1000]);
Select_Bit(1,SMG[v_up / 100 % 10]);
Select_Bit(2,SMG[v_up / 10 % 10]);
Select_Bit(3,SMG[v_up % 10]);
}
else
{
Select_Bit(0,0xff);
Select_Bit(1,0xff);
Select_Bit(2,0xff);
Select_Bit(3,0xff);
}
if(!down)
{
Select_Bit(4,SMG[v_down / 1000]);
Select_Bit(5,SMG[v_down / 100 % 10]);
Select_Bit(6,SMG[v_down / 10 % 10]);
Select_Bit(7,SMG[v_down % 10]);
}
else
{
Select_Bit(4,0xff);
Select_Bit(5,0xff);
Select_Bit(6,0xff);
Select_Bit(7,0xff);
}
}
void Display_fre()//频率界面
{
Select_Bit(0,SMG[10]);
Select_Bit(1,SMG[2]);
Select_Bit(2,SMG[10]);
if(!mode_fre)
{
Select_Bit(3,SMG[fre / 10000]);
Select_Bit(4,SMG[fre / 1000 % 10]);
Select_Bit(5,SMG[fre / 100 % 10]);
Select_Bit(6,SMG[fre / 10 % 10]);
Select_Bit(7,SMG[fre % 10]);
}
else
{
Select_Bit(3,SMG[fre_zhouqi / 10000]);
Select_Bit(4,SMG[fre_zhouqi / 1000 % 10]);
Select_Bit(5,SMG[fre_zhouqi / 100 % 10]);
Select_Bit(6,SMG[fre_zhouqi / 10 % 10]);
Select_Bit(7,SMG[fre_zhouqi % 10]);
}
}
void Display_type()//事件类型界面
{
Select_Bit(6,SMG[0]);
Select_Bit(7,SMG[type]);
}
void Display_time_happen()//事件时间界面
{
Select_Bit(0,SMG[time_happen[2] / 16]);
Select_Bit(1,SMG[time_happen[2] % 16]);
Select_Bit(2,SMG[10]);
Select_Bit(3,SMG[time_happen[1] / 16]);
Select_Bit(4,SMG[time_happen[1] % 16]);
Select_Bit(5,SMG[10]);
Select_Bit(6,SMG[time_happen[0] / 16]);
Select_Bit(7,SMG[time_happen[0] % 16]);
}
unsigned char Key_Scan()
{
unsigned char key_temp = 0;
static unsigned char cnt4 = 0;
static unsigned char cnt5 = 0;
static unsigned char cnt6 = 0;
static unsigned char cnt7 = 0;
static unsigned char cnt8 = 0;
static unsigned char cnt9 = 0;
static unsigned char cnt10 = 0;
static unsigned char cnt11 = 0;
if(flag_10ms)
{
C1 = 0;
C2 = C3 = C4 = R1 = R2 = R3 = R4 = 1;
if(R1 == 0) cnt7++;
if(R1 == 1)
{
if(cnt7 > 2) key_temp = 7;
cnt7 = 0;
}
if(R2 == 0) cnt6++;
if(R2 == 1)
{
if(cnt6 > 2) key_temp = 6;
cnt6 = 0;
}
if(R3 == 0) cnt5++;
if(R3 == 1)
{
if(cnt5 > 2) key_temp = 5;
cnt5 = 0;
}
if(R4 == 0) cnt4++;
if(R4 == 1)
{
if(cnt4 > 2) key_temp = 4;
cnt4 = 0;
}
C2 = 0;
C1 = C3 = C4 = R1 = R2 = R3 = R4 = 1;
if(R1 == 0) cnt11++;
if(R1 == 1)
{
if(cnt11 > 2) key_temp = 11;
cnt11 = 0;
}
if(R2 == 0) cnt10++;
if(R2 == 1)
{
if(cnt10 > 2) key_temp = 10;
cnt10 = 0;
}
if(R3 == 0) cnt9++;
if(R3 == 1)
{
if(cnt9 > 2) key_temp = 9;
cnt9 = 0;
}
if(R4 == 0) cnt8++;
if(R4 == 1)
{
if(cnt8 > 2) key_temp = 8;
cnt8 = 0;
}
flag_10ms = 0;
}
return key_temp;
}
unsigned char shi_bcd(unsigned char shi)
{
return (shi + (shi / 10) * 6);
}
unsigned char bcd_shi(unsigned char bcd)
{
return (bcd - (bcd >> 4) * 6);
}
void Key_Pro()
{
char shi_temp,fen_temp,miao_temp;
switch(key_val)
{
case 4:
if(mode == 1)
{
if(++mode_time > 3) mode_time = 1;
}
if(mode == 2)
{
if(++mode_v > 2) mode_v = 1;
}
if(mode == 3)
mode_fre ^= 1;
if(mode == 4)
mode_thing ^= 1;
break;
case 5:
mode = 3;
break;
case 6:
mode = 2;
mode_v = 0;
break;
case 7:
mode = 1;
mode_time = 0;
break;
case 8:
break;
case 9:
mode = 4;
break;
case 10:
if(mode == 1)
switch(mode_time)
{
case 1://时
shi_temp = bcd_shi(time[2]);
if(--shi_temp < 0) shi_temp = 23;
Write_new_time(2,shi_bcd(shi_temp));
break;
case 2://分
fen_temp = bcd_shi(time[1]);
if(--fen_temp < 0) fen_temp = 59;
Write_new_time(1,shi_bcd(fen_temp));
break;
case 3://秒
miao_temp = bcd_shi(time[0]);
if(--miao_temp < 0) miao_temp = 59;
Write_new_time(0,shi_bcd(miao_temp));
break;
}
if(mode == 2)
switch(mode_v)
{
case 1://up
v_up -= 500;
if(v_up < 0 ) v_up = 9500;
break;
case 2://down
v_down -= 500;
if(v_down < 0) v_down = 9500;
break;
}
break;
case 11:
if(mode == 1)
switch(mode_time)
{
case 1://时
shi_temp = bcd_shi(time[2]);
if(++shi_temp > 23) shi_temp = 0;
Write_new_time(2,shi_bcd(shi_temp));
break;
case 2://分
fen_temp = bcd_shi(time[1]);
if(++fen_temp > 59) fen_temp = 0;
Write_new_time(1,shi_bcd(fen_temp));
break;
case 3://秒
miao_temp = bcd_shi(time[0]);
if(++miao_temp > 59) miao_temp = 0;
Write_new_time(0,shi_bcd(miao_temp));
break;
}
if(mode == 2)
switch(mode_v)
{
case 1://up
v_up += 500;
if(v_up > 9999) v_up = 0;
break;
case 2://down
v_down += 500;
if(v_down > 9999) v_down = 0;
break;
}
break;
}
if(mode == 2 && mode_v == 0)
{
save[0] = v_up / 100;save[1] = v_up % 100;
save[2] = v_down / 100;save[3] = v_down % 100;
}
}
void main()
{
Sys_Init();
Timer1Init();
Write_time();
Read_AT24C02_Page(rec,8);
v_up = rec[0] * 100 + rec[1];
v_down = rec[2] * 100 + rec[3];
type = rec[4];
time_happen[2] = rec[5];
time_happen[1] = rec[6];
time_happen[0] = rec[7];
while(1)
{
v = Read_PCF8591() / 51.0 * 1000;
key_val = Key_Scan();
Key_Pro();
Read_time();
fre_zhouqi = (1.0 / fre) * 1000000;
if(v < v_down || v > v_up)
{
if(v < v_down) type = 0;
else type = 1;
save[4] = type;
save[5] = time[2];
save[6] = time[1];
save[7] = time[0];
}
Write_AT24C02_Page(save,8);
switch(mode)
{
case 1:
if(!mode_time) Display_time();
else Display_time_set();
break;
case 2:
if(!mode_v) Display_v();
else Display_v_set();
break;
case 3:Display_fre();break;
case 4:
if(!mode_thing) Display_type();
else Display_time_happen();
break;
}
}
}