一、iic.h代码
#include "STC15F2K60S2.H"
#include "intrins.h"
sbit sda=P2^1;
sbit scl=P2^0;
unsigned char PCF8591_ADC(void);
void PCF8591_DAC(unsigned char dat);
void EEPROM_Read(unsigned char *pucRuf,unsigned char addr,unsigned char num);
void EEPROM_Write(unsigned char *pucRuf,unsigned char addr,unsigned char num);
二、iic.c代码
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"
#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 char PCF8591_ADC(void)
{
unsigned char temp;
/**********************写入**********************/
I2CStart();//开始
I2CSendByte(0x90);//发送写地址
I2CWaitAck();//等待应答
I2CSendByte(0x43);//发送光敏电阻控制位
I2CWaitAck();//等待应答
/**********************读取**********************/
I2CStart();//开始
I2CSendByte(0x91);//发送读地址
I2CWaitAck();//等待应答
temp=I2CReceiveByte();//接收
I2CSendAck(1);//发送应答
I2CStop();//终止通信
return temp;
}
void PCF8591_DAC(unsigned char dat)
{
I2CStart();//开始
I2CSendByte(0x90);//发送写地址
I2CWaitAck();//等待应答
I2CSendByte(0x41);//发送光敏电阻控制位
I2CWaitAck();//等待应答
I2CSendByte(dat);//发送光敏电阻控制位
I2CWaitAck();//等待应答
I2CStop();
}
void EEPROM_Read(unsigned char *pucRuf,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xA0);//发送设备地址
I2CWaitAck();//等待应答
I2CSendByte(addr);//发送写入位置
I2CWaitAck();
I2CStart();
I2CSendByte(0xA1);//发送读取地址
I2CWaitAck();
while(num--)
{
*pucRuf++= I2CReceiveByte();
if(num)
I2CSendAck(0);
else
I2CSendAck(1);
}
I2CStop();//终止通信
}
void EEPROM_Write(unsigned char *pucRuf,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xA0);//发送设备地址
I2CWaitAck();//等待应答
I2CSendByte(addr);//发送读取位置
I2CWaitAck();
while(num--)
{
I2CSendByte(*pucRuf++);
I2CWaitAck();
I2C_Delay(200);//加入延时,不至于导致总线过于繁忙,有助于总线稳定性
}
I2CStop();//终止通信
}
三、主函数代码
#include "tim.h"
#include "init.h"
#include "led.h"
#include "seg.h"
#include "stdio.h"//sprintf所需头文件
#include "key.h"
#include "peripheral.h"
#include "ds1302.h"
#include "iic.h"
//Timer
unsigned long ulms=0;
unsigned int uiLed_Dly=0;
unsigned int uiSeg_Dly=0;
unsigned int uiKey_Dly=0;
unsigned int uiPeripheral_Dly=0;
unsigned int uiRTC_Dly=0;
unsigned int uiADC_Dly=0;
unsigned int uiDAC_Dly=0;
//LED
unsigned char ucLed=0x25;
//Seg
unsigned char ucSeg_Pos=0;
unsigned char pucSeg_Buf[12],pucSeg_Code[8];
//KEY
unsigned char ucKey_Val=0;
//RTC
unsigned char pucRTC[3]={23,59,55};
//ADC
unsigned char ucADC=0;
//Function
void Led_Proc(void);
void Seg_Proc(void);
void Key_Proc(void);
void Peripheral_Proc(void);
void RTC_Proc(void);
void ADC_Proc(void);
void DAC_Proc(void);
void main()
{
Cls_Peripheral();
Timer0Init();
EEPROM_Read(pucRTC,0x00,3);//读出先前存到EEPROM芯片里的数据,然后传给pucRTC
if(pucRTC[0]>23||pucRTC[1]>59||pucRTC[2]>59)
{
pucRTC[0]=23;
pucRTC[1]=59;
pucRTC[2]=55;
}
Set_RTC(pucRTC);
EA=1;
while(1)
{
Led_Proc();
Seg_Proc();
Key_Proc();
Peripheral_Proc();
RTC_Proc();
ADC_Proc();
DAC_Proc();
}
}
void Led_Proc(void)
{
if(uiLed_Dly<200)
return;
uiLed_Dly=0;
Led_Disp(ucLed);
}
void Seg_Proc(void)
{
if(uiSeg_Dly<200)
return;
uiSeg_Dly=0;
sprintf(pucSeg_Buf,"%03u ",(unsigned int)ucADC);//将文字存储到数组中
Seg_Tran(pucSeg_Buf,pucSeg_Code);//将存入的数组中的内容转换成段码
}
void Key_Proc(void)
{
if(uiKey_Dly<20)
return;
uiKey_Dly=0;
ucKey_Val=Key_Read_KBD();
}
void Peripheral_Proc(void)
{
if(uiPeripheral_Dly<500)
return;
uiPeripheral_Dly=0;
Set_Peripheral(0,1);
}
void RTC_Proc(void)
{
if(uiRTC_Dly<500)
return;
uiRTC_Dly=0;
Get_RTC(pucRTC);
EEPROM_Write(pucRTC,0x00,3);
}
void ADC_Proc(void)
{
if(uiADC_Dly<500)
return;
uiADC_Dly=0;
ucADC=PCF8591_ADC();
}
void DAC_Proc(void)
{
if(uiDAC_Dly<500)
return;
uiDAC_Dly=0;
PCF8591_DAC(ucADC);
}
void Time_0(void) interrupt 1
{
ulms++;
uiLed_Dly++;
uiSeg_Dly++;
uiKey_Dly++;
uiPeripheral_Dly++;
uiRTC_Dly++;
uiADC_Dly++;
uiDAC_Dly++;
if(ulms%2==0)//数码管2ms循环一次,因为数码管没有办法一次性显示不同内容,因此逐位去点来点亮
{
ucSeg_Pos=(ucSeg_Pos+1)%8;//ucSeg_Pos会在0-7之间循环,依次点亮数码管的每个位
Seg_Disp(pucSeg_Code,ucSeg_Pos);//基于段码,让对应的位进行显示
}
}