📄 i2ctime.c
字号:
#include "p30f6014.h"
#include "I2CTime.h"
void InitializeSys()
{
SRbits.IPL = 6; // CPU中断优先级设为6
}
void InitializeKeyboard()
{
TRISD = (TRISD | 0xff00); //将RD8-RD15配置为输入,D0~D7
TRISD = (TRISD & 0xfff8); //RD0-RD2配置为输出,作138译码
PORTD = (PORTD & 0xfff8); //选中KEYA,针对S1~S8的按键
}
void ConfigI2CTime()
{
I2CCONbits.I2CEN = 1; //启动I2C模块
I2CBRG = 0x064; //I2C波特率
}
void InitializeSPIOut()
{
TRISF = TRISF&0xfebf; //RF6、RF8输出
TRISG = TRISG&0xfdff; //RG9输出
SPI1CON = 0x0379; // 字节通讯模式,CKP=1,CKE=1,FOSC/32,时钟上升沿发送数据
SPI1STATbits.SPIEN = 1; //SPI1EN=1
IFS0bits.SPI1IF = 0; // 清除SPI1IF标志
}
void InitializeTMR1()
{
TMR1 = 0; //定时器1计数寄存器TMR1=0
T1CON = 0x0020; //关闭定时器,使用内部时钟,预分频比为1:64
PR1 = 0x3D09; //定时器Timer1周期寄存器PR1=0xf424,0.5s初值
IFS0bits.T1IF = 0; //清除TMR1的中断标志
IPC0bits.T1IP = 7; //中断优先级为7
IEC0bits.T1IE = 1; //使能中断
}
void DealWithKeys()
{
int i;
if((PORTD&0xff00) == 0xfe00) //查询是否S1键按下
{
for(i=0; i<100; i++); //延时消抖
if((PORTD&0xff00) == 0xfe00)
{
SetMode += 1; //改变当前模式
if(SetMode == 4)
SetMode = 0;
}
while((PORTD&0xff00) == 0xfe00); //不对一次长按按键进行多次计数
}
if((PORTD&0xff00) == 0xfd00) //查询是否S2键按下
{
for(i=0; i<100; i++); //延时消抖
if((SetMode == 1)||(SetMode == 2)) //如果模式没有改变,S2键按下无效
{
if((PORTD&0xfd00) == 0xfd00)
{
SelfIncrFlag += 1;
}
while((PORTD&0xff00) == 0xfd00); //不对一次长按按键进行多次计数
}
}
}
void ModifyMode()
{
if(SetMode == 1) //修改小时数模式
{
T1CONbits.TON = 1;
ModifyHour();
}
if(SetMode == 2) //修改分钟数模式
{
T1CONbits.TON = 1;
ModifyMinute();
}
if((SetMode == 0)||(SetMode == 3)) //其他模式
T1CONbits.TON = 0;
}
void ModifyHour()
{
if(SelfIncrFlag == 1) //小时修改范围0~23h
{
Time[1] += 1;
if(Time[1] == 10)
{
Time[0] += 1;
Time[1] = 0;
}
if((Time[0] == 2)&&(Time[1] == 4))
Time[0] = Time[1] = 0;
SelfIncrFlag = 0;
}
}
void ModifyMinute()
{
if(SelfIncrFlag == 1) //分钟修改范围0~59m
{
Time[4] += 1;
if(Time[4] == 10)
{
Time[3] += 1;
Time[4] = 0;
if((Time[3] == 6)&&(Time[4] == 0))
Time[3] = Time[4] = 0;
}
SelfIncrFlag = 0;
}
}
void WriteData()
{
int i;
I2CCONbits.SEN = 1; //发送启动位
while(I2CCONbits.SEN==1){} //等待启动操作完成
I2CTRN = ControlByteW; //发送控制字:写准备
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
I2CTRN = AddressH;
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
I2CTRN = AddressL;
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
for (i=0;i<16;i++)
{
I2CTRN = DataReceived[i];
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
}
I2CCONbits.PEN = 1; //发送停止位
while(I2CCONbits.PEN==1){} //等待停止操作完成
}
void ReadData()
{
int i;
I2CCONbits.SEN = 1; //发送启动位
while(I2CCONbits.SEN == 1){} //等待启动操作完成
I2CTRN = ControlByteW; //发送控制字:写准备
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
I2CTRN = AddressH;
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
I2CTRN = AddressL;
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
I2CCONbits.RSEN = 1; //发送重启动位
while(I2CCONbits.RSEN==1){} //等待重启动操作完成
I2CTRN = ControlByteR; //发送控制字:读准备
while(I2CSTATbits.TRSTAT==1){} //等待发送完成
for (i=0;i<16;i++)
{
I2CCONbits.RCEN = 1; //接收数据使能
while(I2CSTATbits.RBF==0){}
DataReceived[i] = I2CRCV;
I2CCONbits.ACKDT = 0;
if (i==15)
I2CCONbits.ACKDT = 1; //最后一字节则不发ACK
I2CCONbits.ACKEN = 1;
while(I2CCONbits.ACKEN==1){}
}
I2CCONbits.PEN = 1; //发送停止位
while(I2CCONbits.PEN==1){} //等待停止操作完成
}
void FormatDataReceived()
{
Time[0] = (DataReceived[3]>>4)&0x03;
Time[1] = DataReceived[3]&0x0f;
Time[2] = 10;
Time[3] = (DataReceived[2]>>4)&0x07;
Time[4] = DataReceived[2]&0x0f;
Time[5] = 10;
Time[6] = (DataReceived[1]>>4)&0x07;
Time[7] = DataReceived[1]&0x0f;
}
void FormatTime()
{
//DataReceived[1] = (Time[6]<<4)|Time[7];
DataReceived[2] = (Time[3]<<4)|Time[4];
DataReceived[3] = ((Time[0]<<4)|Time[1])&0x7f;
}
void DisplayOnLED(unsigned int* TimeTemp)
{
int i;
PORTGbits.RG9 = 0; //为锁存作准备
for(i=0; i<2; i++) // 显示小时
{
SPI1BUF = Table1[TimeTemp[i]];
while(SPI1STATbits.SPITBF == 1);
}
SPI1BUF = 0xbf; //显示“-”
while(SPI1STATbits.SPITBF == 1);
for(i=3; i<5; i++) //显示分钟
{
SPI1BUF = Table1[TimeTemp[i]];
while(SPI1STATbits.SPITBF == 1);
}
SPI1BUF = 0xbf; //显示"-"
while(SPI1STATbits.SPITBF == 1);
for(i=6; i<8; i++) //显示秒
{
SPI1BUF = Table1[TimeTemp[i]];
while(SPI1STATbits.SPITBF == 1);
}
SPI1BUF = 0xff;
while(SPI1STATbits.SPITBF == 1);
PORTGbits.RG9 = 1; //给锁存信号
}
void __attribute__((__interrupt__))_T1Interrupt(void)
{
unsigned char i;
for(i=0; i<8; i++)
TimeFlicker[i] = Time[i];
TMR1INTFlag = ~TMR1INTFlag; // 区别相邻的两次中断,为了在修改时钟时产生闪烁效果
TMR1 = 0;
IFS0bits.T1IF = 0; // 清定时器中断标志
if(SetMode == 1) // 修改当前小时数
{
TimeFlicker[0] = 10;
TimeFlicker[1] = 10;
}
if(SetMode == 2) // 修改当前分钟数
{
TimeFlicker[3] = 10;
TimeFlicker[4] = 10;
}
}
int main()
{
int i;
InitializeSys();
ConfigI2CTime();
InitializeKeyboard();
InitializeSPIOut();
InitializeTMR1();
while(1)
{
if(SetMode == 0) // 时钟显示模式
{
ReadData();
FormatDataReceived();
}
DealWithKeys();
ModifyMode();
if(SetMode == 3) // 修改当前时钟
{
FormatTime();
WriteData();
}
if(TMR1INTFlag == 0) // 更改时间时产生闪烁效果
DisplayOnLED(&Time[0]);
else
DisplayOnLED(&TimeFlicker[0]);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -