⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2ctime.c

📁 《dsPIC通用数字信号控制器原理及应用》源码
💻 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 + -