第四届省赛主要涉及到IIC和DS1302,在官方驱动基础上进行改动。
#include
#include "ds1302.h"
#include "iic.h"
#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar code dottab[]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar shidu;
uchar yuzhi=50;
uchar jia=0,jian=0;//用作标志位
uchar s7=0,s6=0,s5=0,s4=0;//用作标志位
void Delay1ms(uchar ms);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void allinit();
void keyscan();
void allinit()
{
P2=0X80;
P0=0XFE;//LED L1点亮 自动工作
P2=0XC0;
P0=0XFF;
P2=0XE0;
P0=0XFF;//关闭数码管
P2=0XA0;
P0=0X00;//关闭继电器 蜂鸣器
}
void main()
{
allinit();//上电初始化
DS1302_init();//时间初始化
// EEPROM_write(0x00,yuzhi);
// Delay1ms(5);
yuzhi=EEPROM_read(0x00);
yi=11,er=11,san=11,si=11,wu=11,liu=0,qi=0,ba=0;
while(1)
{
keyscan();
DS1302_gettime();
shidu=AD_read(0x03);//Rb2
// if(shidu=yuzhi))
{
// P2=0xa0;
// P0=0x00;
if(s5==1)
{
P2=0xa0;
P0=0x10;
}
else if(s5==0)
{
P2=0xa0;
P0=0x00;
}
}
if(s6==1)
{
// P2=0xa0;
// P0=0x00;
if(s5==1)
{
P2=0xa0;
P0=0x10;
}
else if(s5==0)
{
P2=0xa0;
P0=0x00;
}
}
}
display1( yi, er);
display2( san,si);
display3( wu, liu);
display4( qi, ba);
}
}
void Delay1ms(uchar ms) //@12.000MHz
{
unsigned char i, j;
uchar k;
for(k=ms;k>0;k--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void display1(uchar yi,uchar er)
{
P2=0XC0;
P0=0X01;
P2=0XE0;
P0=tab[yi];
Delay1ms(1);
P2=0XC0;
P0=0X02;
P2=0XE0;
P0=tab[er];
Delay1ms(1);
}
void display2(uchar san,uchar si)
{
P2=0XC0;
P0=0X04;
P2=0XE0;
P0=tab[san];
Delay1ms(1);
P2=0XC0;
P0=0X08;
P2=0XE0;
P0=tab[si];
Delay1ms(1);
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;
P0=0X10;
P2=0XE0;
P0=tab[wu];
Delay1ms(1);
P2=0XC0;
P0=0X20;
P2=0XE0;
P0=tab[liu];
Delay1ms(1);
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;
P0=0X40;
P2=0XE0;
P0=tab[qi];
Delay1ms(1);
P2=0XC0;
P0=0X80;
P2=0XE0;
P0=tab[ba];
Delay1ms(1);
}
void keyscan()
{
if(P30==0)//手动 自动切换 s7按键
{
Delay1ms(5);
if(P30==0)//按键s7
{
if(s7==0)//标志位s7
{
s7=1;//切换为手动
P2=0X80;
P0=0XFD;
}
else if(s7==1)
{
s7=0;
P2=0X80;
P0=0XFE;
}
}
while(!P30);
}
if(P31==0)//s6按键
{
Delay1ms(5);
if(P31==0)
{
if(s6==0)
{
s6=1;
}
else if(s6==1)
{
s6=0;
EEPROM_write(0x00,yuzhi);
}
}
while(!P31);
}
if(P32==0)//s5按键
{
Delay1ms(5);
if(P32==0)
{
s5=1;
jia=1;
}
while(!P32);
}
if(P33==0)//s4按键
{
Delay1ms(5);
if(P33==0)
{
s5=0;
jian=1;
}
while(!P33);
}
}
DS1302部分
#include "ds1302.h"
unsigned char time[7];
unsigned char ds[7]={0,30,8,0,0,0,0};
/********************************************************************/
/*单字节写入一字节数据*/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*电平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*电平置低*/
}
SCK_SET;
SCK_CLR;
dat = dat >> 1;
}
}
/********************************************************************/
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /*电平读取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}
/********************************************************************/
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr & 0xFE;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/
Write_Ds1302_Byte((dat/10<<4)|(dat%10)); /*写入数据:dat*/
RST_CLR; /*停止DS1302总线*/
}
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp,dat1,dat2;
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr | 0x01;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/
RST_CLR; /*停止DS1302总线*/
//自己添加
dat1=temp/16;
dat2=temp%16;
temp=dat1*10+dat2;
// RST_CLR; /*读取完一个字节必须停止DS1302总线,否则出错*/
// SDA_CLR;
SD=0; //(即使IO口P2^3=0)
return temp;
}
//DS1302初始化
void DS1302_init(void)
{
unsigned char i,add;
add=0x80;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<7;i++)
{
Ds1302_Single_Byte_Write(add,ds[i]);
add=add+2;
}
Ds1302_Single_Byte_Write(0x8e,0x80);
}
//获取初始化的时间
void DS1302_gettime(void)
{
unsigned char i,add;
add=0x81;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<7;i++)
{
time[i]=Ds1302_Single_Byte_Read(add);
add=add+2;
}
Ds1302_Single_Byte_Write(0x8e,0x80);
}
#ifndef __DS1302_H__
#define __DS1302_H__
#include
#include
/********************************************************************/
sbit SCK=P1^7;
sbit SD=P2^3;
sbit RST=P1^3;
/********************************************************************/
/*复位脚*/
#define RST_CLR RST=0 /*电平置低*/
#define RST_SET RST=1 /*电平置高*/
/*双向数据*/
#define SDA_CLR SD=0 /*电平置低*/
#define SDA_SET SD=1 /*电平置高*/
#define SDA_R SD /*电平读取*/
/*时钟信号*/
#define SCK_CLR SCK=0 /*时钟信号*/
#define SCK_SET SCK=1 /*电平置高*/
/********************************************************************/
#define ds1302_sec_addr 0x80 //秒数据地址
#define ds1302_min_addr 0x82 //分数据地址
#define ds1302_hr_addr 0x84 //时数据地址
#define ds1302_date_addr 0x86 //日数据地址
#define ds1302_month_addr 0x88 //月数据地址
#define ds1302_day_addr 0x8A //星期数据地址
#define ds1302_year_addr 0x8C //年数据地址
#define ds1302_control_addr 0x8Ee //写保护命令字单元地址
#define ds1302_charger_addr 0x90 //涓电流充电命令字地址
#define ds1302_clkburst_addr 0xBE //日历、时钟突发模式命令字地址
/********************************************************************/
/********************************************************************/
/*单字节写入一字节数据*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/
/*单字节读出一字节数据*/
extern unsigned char Read_Ds1302_Byte(void);
/********************************************************************/
/********************************************************************/
/*向DS1302单字节写入一字节数据*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
//自己添加函数
extern unsigned char time[7];
extern unsigned char ds[7];
extern void DS1302_init(void);
extern void DS1302_gettime(void);
#endif
/********************************************************************/
// END FILE
/********************************************************************/
IIC通信模块,包括EEPROM和PCF8951
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(12MHz)
日 期: 2011-8-9
*/
#include "iic.h"
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//应答位控制
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
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++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
//EEPROM写入函数
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();
}
//EEPROM读取函数
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_Stop();
return temp;
}
//AD转换读取函数 PCF8951地址 0x90 0x91
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_Stop();
temp=0.39*temp; //满足湿度最大为99%
return temp;
}
#ifndef _IIC_H
#define _IIC_H
#include
#include "intrins.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
//函数声明
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(unsigned char ackbit);
void IIC_SendByte(unsigned char byt);
bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);
//以下为自己添加函数
unsigned char AD_read(unsigned char add);
void EEPROM_write(unsigned char add,unsigned char dat);
unsigned char EEPROM_read(unsigned char add);
#endif