专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
PIC单片机
为什么用PIC16F677运行C语言不行?
2020-02-08 12:22
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
51单片机
7840
10
10
为什么我用PIC16F677运行C语言不行?是不是MPLAB IDE软件include文件夹中没有"PIC16F677.h"的原因?我看了是没有的。请教一下如何才能运行起来。
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
10条回答
zhj555
2020-02-09 05:16
回复【3楼】role_2099
用pic16f685.h这个报错吗?如果源程序短你贴上来,我编译一下试试
-----------------------------------------------------------------------
用PIC16F685也试了不行.
#include <pic16f685.h> //头文件引用
//大LED数码管显示代码表
const unsigned char LEDCODE[]=
{
0x3F,0x06,0x5B,0x4F,//0,1,2,3
0x66,0x6D,0x7D,0x07,//4,5,6,7
0x7F,0x6F, //8,9
};
//宏定义
#define TRUE 1
#define FALsE 0
//-------------------------------------------------------------
//---定义软件定时器定时1s和0.5秒结构体变量
struct TIMER_sTRUCT
{
unsigned int Interval;
unsigned char Enable;
};
struct TIMER_sTRUCT second_1s,second_Halfs;
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义实时带温度与闹铃功能的日历/时钟结构体变量
struct REALCLOCK_sTRUCT
{
unsigned char Year; //年份
unsigned char Month; //月份
unsigned char Day; //日
unsigned char Week; //星期
unsigned char Hour; //时
unsigned char Minute; //分
unsigned char second; //秒
unsigned char Temp; //温度
};
struct REALCLOCK_sTRUCT RealClock;
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义定时闹钟结构体变量
struct ALARMCLOCK_sTRUCT
{
unsigned char Day; //日
unsigned char Week; //星期
unsigned char Hour; //时
unsigned char Minute; //分
unsigned char second; //秒
unsigned char status; //状态
};
struct ALARMCLOCK_sTRUCT AlarmClock;
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义PIC单片机与74HC595芯片接口连接关系
#define HC595_sER LATCbits.LATC0
#define HC595_RCLK LATCbits.LATC1
#define HC595_sRCLK LATCbits.LATC2
#define HC595_sRCLR LATCbits.LATC3
#define HC595_OE LATCbits.LATC4
//---定义LED数码管显示缓冲区
unsigned char LEDBuffer[16];
//---定义大LED数码管初始化函数
void InitizeLED(void)
{
HC595_OE=1;//并行输出为高阻状态
HC595_sRCLR=0;//清空移位寄存器
HC595_sER=0;//清零
HC595_RCLK=0;//移位时钟初始为低
HC595_sRCLK=0;//存储器时钟初始为低
HC595_OE=0;//允许并行输出
HC595_sRCLR=1;//结束复位状态
}
//---定义大LED显示驱动函数
//*LedData指针,DataLength数据长度
void sendDataToLED(unsigned char *LedData,unsigned char DataLength)
{
unsigned char i,j,temp;
for(j=0;j<DataLength;j++)
{
temp=LEDCODE[*LedData];//取出LED显示的代码表送入变量中
for(i=0;i<8;i++)
{
if(0x80==(temp & 0x80))HC595_sER=1;//将字节按位移出
else HC595_sER=0;
HC595_RCLK=1;//将数据送入移位寄存器中
HC595_RCLK=0;
temp<<=1;//当前指针的内容左移一位
}
LedData++;//指针指向下一个数据
}
HC595_sRCLK=1;//将移位寄存器中的内容送到并行输出口
HC595_sRCLK=0;
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义PIC单片机与Ds1302引脚之间的连接关系
#define Ds1302CE_1 LATCbits.LATC5=1
#define Ds1302CE_0 LATCbits.LATC5=0
#define Ds1302CE_O TRIsC &=0xDF
#define Ds1302IO_O TRIsC &=0xBF
#define Ds1302IO_I TRIsC |=0x20
#define Ds1302IO_1 LATCbits.LATC6=1
#define Ds1302IO_0 LATCbits.LATC6=0
#define Ds1302IO_D PORTC & 0x40
#define Ds1302CK_1 LATCbits.LATC7=1
#define Ds1302CK_0 LATCbits.LATC7=0
#define Ds1302CK_O TRIsC &=0x7F
//---Ds1302初始化函数
void Init_Ds1302_RTC(void)
{
Ds1302CK_O;//置CK为输出
Ds1302CE_O;//置CE为输出
Ds1302CE_0;//输出为0
Ds1302CK_0;//输出为0
Ds1302IO_1;//置IO为输入
Ds1302IO_I;
}
//---读取Ds1302日历函数
unsigned char Read_Ds1302_RTC(unsigned char RTC_Address)
{
unsigned char i;
unsigned int temp;
Ds1302CE_0;//CE=0
Ds1302CK_0;//CK=0
Ds1302IO_O;//Ds1302为IO为输出
_asm//简短延时
NOP
NOP
_endasm
Ds1302CE_1;//CE=1
_asm//简短延时
NOP
NOP
_endasm
for(i=8;i>0;i--)//CPU送出访问Ds1302的地址
{ //以串行方式从PIC单片机的RC6引脚输出
if(RTC_Address & 0x01)Ds1302IO_1;
else Ds1302IO_0;
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
RTC_Address>>=1;//右移一位
}
Ds1302IO_1;//PIC单片机的RC7为输入状态
_asm//简短延时
NOP
NOP
_endasm
Ds1302IO_I;
_asm//简短延时
NOP
NOP
_endasm
temp=0;
if(Ds1302IO_D)temp|=0x8000;
temp>>=1;//右移一位
for(i=7;i>0;i--)
{
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
if(Ds1302IO_D)temp|=0x8000;//RC7引脚上的电平并保存到变量中
temp>>=1;//右移一位
}
Ds1302CE_0;//CE=0
temp<<=1;//左移一位
return(temp/256);//返回读取到的内容
}
//---写入Ds1302日历函数
void Write_Ds1302_RTC(unsigned char RTC_Address,unsigned char RTC_Data)
{
unsigned char i;
Ds1302CE_0;//CE为输出
Ds1302CK_0;//CK为输出
Ds1302IO_O;//IO为输出
_asm//简短延时
NOP
NOP
_endasm
Ds1302CE_1;//CE=1
_asm//简短延时
NOP
NOP
_endasm
for(i=8;i>0;i--)
{ //送地址给Ds1302
if(RTC_Address & 0x01)Ds1302IO_1;
else Ds1302IO_0;
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
RTC_Address>>=1;//右移一位
}
for(i=8;i>0;i--)
{ //送数据给Ds1302
if(RTC_Data & 0x01)Ds1302IO_1;
else Ds1302IO_0;
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
RTC_Data>>=1;//右移一位
}
Ds1302CE_0;//CE=0
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义ADC缓冲区,和指针变量
unsigned char ADCBuffer[5]; //ADC采集缓冲区
unsigned char ADCBufferPointer; //ADC采集缓冲区指针
unsigned char TemperatureDisplayFlag; //当缓冲区满时,处理完后标志
//---ADC初始化函数定义
void ADC_Initize(void)
{
unsigned char i;
ADCON1=0x07;//初始化ADC的参考电压取VCC,GND
ADCON2=0x00;//左对齐,0TAD,FOsC/2
ADCON0=0x03;//选择通道0,启动A/D转换开始
//初始化ADCBuffer变量指针和缓冲区
ADCBufferPointer=0;
for(i=0;i<sizeof(ADCBuffer);i++)ADCBuffer
=0;
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---初始化PIC18F单片机工作于内部时钟8MHz状态下
void INTOsC_Initize(void)
{
OsCCON=0x70;//选择内部8MHz的主振荡器
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---TMR0定时器初始化函数
void TMR0_Initize(void)
{
T0CONbits.TMR0ON=FALsE;//TMR0停止运行
T0CON=0x12;//TMR0初始化为8位定时,预分频比为1:8
TMR0L=256-25;//定时100ms初值
T0CONbits.TMR0ON=TRUE;
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---延时函数的定义
void Delay(unsigned int t)
{
while(t--);
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---按键引脚的定义
#define DATEKEY PORTBbits.RA1
#define TIMEKEY PORTBbits.RA2
#define ALARMKEY PORTBbits.RA5
#define NUMBERADDKEY PORTBbits.RA3
#define NUMBERsUBKEY PORTBbits.RA4
//---功能按键状态变量定义
unsigned char DateKeyID;
unsigned char TimeKeyID;
unsigned char AlarmKeyID;
//-------------------------------------------------------------
//-------------------------------------------------------------
//定时器低优先级中断入口函数声明
void TMR0_TMR1_IsR(void);
#pragma code low_vector=0x18
void low_interrupt(void)
{
_asm goto TMR0_TMR1_IsR _endasm
}
#pragma code
//-------------------------------------------------------------
//-------------------------------------------------------------
//---主程序 main函数
void main(void)
{
unsigned char i,j;
unsigned long temp;
INTOsC_Initize(); //初始化时钟源
TMR0_Initize(); //初始化TMR0定时器
ADC_Initize(); //初始化A/D模块
InitizeLED(); //初始化LED数码管显示
INTCONbits.GIE=1; //CPU开中断
INTCONbits.PEIE=1; //CPU的第二梯队中断允许
while(1)
{
//-------------------------------------------------------
//---功能键及数字调节键识别与处理过程
//---
//-------------------------------------------------------
//---闹铃设置功能键
if(0==ALARMKEY) //闹铃设置键是否按下
{
Delay(1000); //去抖动
if(0==ALARMKEY)//是真得按下了吗
{
AlarmKeyID++; //闹铃设置状态变量加1
if(1==AlarmKeyID)//在闹铃设置状态为1的情况下,复制当前日历的内容到闹铃变量中
{
AlarmClock.second=RealClock.second; //复制秒
AlarmClock.Minute=RealClock.Minute; //复制分
AlarmClock.Hour=RealClock.Hour; //复制时
AlarmClock.Week=RealClock.Week; //复制日
AlarmClock.Day=RealClock.Day; //复制星期
}
if(0==AlarmClock.status)//如果闹铃是关闭的,则
{
if(2==AlarmKeyID)AlarmKeyID=0;//直接回到正常状态
}
else//如果是闹铃是打开的,则
{
if(5==AlarmKeyID)AlarmKeyID=0;//可以设置时分秒闹铃时间
}
}
while(0==ALARMKEY); //等待按键释放
}
//-------------------------------------------------------
//---校准日期的功能键
if(0==DATEKEY)//日期校准按键是否按下
{
Delay(1000);//去按键抖动
if(0==DATEKEY)//再判断是否真得按下
{
TimeKeyID=0;//其它校准或设置变量状态为正常状态
AlarmKeyID=0;
DateKeyID++;//校准日期状态变量加1
if(5==DateKeyID)DateKeyID=0;//所有校准完毕,回到正常状态
}
while(0==DATEKEY);//等待按键释放
}
//-------------------------------------------------------
//-------------------------------------------------------
//---校准时间的功能键
if(0==TIMEKEY)
{
Delay(1000);
if(0==TIMEKEY)
{
DateKeyID=0;//其它校准或设置变量状态为正常状态
AlarmKeyID=0;
TimeKeyID++;
if(4==TimeKeyID)TimeKeyID=0;
}
while(0==TIMEKEY);
}
//-------------------------------------------------------
//-------------------------------------------------------
//---数字加调节键
if(0==NUMBERADDKEY)//数字增调节键按下了
{
Delay(1000);//去抖动
if(0==NUMBERADDKEY)//再判断是否真得按下
{
if(AlarmKeyID>0)//如果闹铃设置状态是处于设置条件下,则
{
switch(AlarmKeyID)//根据闹铃状态变量来分析调节哪个功能
{
case 1://闹铃打开/关闭设置状态
//如果闹铃关闭则打开,否则关闭
if(0==AlarmClock.status)AlarmClock.status=1;
else AlarmClock.status=0;
break;
case 2://设置闹铃的时状态
if(0!=AlarmClock.status) //如果闹铃是打开的,则
{
AlarmClock.Hour++;//闹铃的时变量加1
if(24==AlarmClock.Hour)AlarmClock.Hour=0;//到24归0
}
break;
case 3://设置闹铃的分状态
if(0!=AlarmClock.status)//如果闹铃是打开的,则
{
AlarmClock.Minute++;//闹铃的分变量加1
if(60==AlarmClock.Minute)AlarmClock.Minute=0;//到60归0
}
break;
case 4://设置闹铃的秒状态
if(0!=AlarmClock.status) //如果闹铃是打开的,则
{
AlarmClock.second++;//闹铃的秒变量加1
if(60==AlarmClock.second)AlarmClock.second=0;//到60归0
}
break;
}
if((AlarmKeyID>1)&&((0==DateKeyID)||(0==TimeKeyID)))
{
//将调整的结果送到LED显示缓冲区
LEDBuffer[0]=AlarmClock.second%10;
LEDBuffer[1]=AlarmClock.second/10;
LEDBuffer[2]=AlarmClock.Minute%10;
LEDBuffer[3]=AlarmClock.Minute/10;
LEDBuffer[4]=AlarmClock.Hour%10;
LEDBuffer[5]=AlarmClock.Hour/10;
}
}
if(TimeKeyID>0)//如果时间设置状态是处于设置状态条件下,则
{
switch(TimeKeyID)//根据时间设置状态变量的数值来决定
{
case 1://时间设置的时状态
RealClock.Hour++;//时间设置时加1
if(24==RealClock.Hour)RealClock.Hour=0;//到24归0
//将其转换成16进制,以方便写入Ds1302的时寄存器单元
i=((RealClock.Hour/10)<<4)|(RealClock.Hour%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x84,i);//写入Ds1302的时寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://时间设置的分状态
RealClock.Minute++;//时间设置的分加1
if(60==RealClock.Minute)RealClock.Minute=0;//到60归0
//将其转换成16进制,以方便写入Ds1302的分寄存器单元
i=((RealClock.Minute/10)<<4)|(RealClock.Minute%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x82,i);//写入Ds1302的分寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://时间设置的秒状态
RealClock.second++;//时间设置的秒变量加1
if(60==RealClock.second)RealClock.second=0;//到60归0
//将其转换成16进制,以方便写入Ds1302的秒寄存器单元
i=((RealClock.second/10)<<4)|(RealClock.second%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x80,i);//写入Ds1302的秒寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
if(DateKeyID>0)//如果日期设置状态变量处于设置状态条件下,则
{
switch(DateKeyID)//根据日期设置状态变量的内容来决定
{
case 1://年份校准状态
RealClock.Year++;//设置的年变量加1
if(99<RealClock.Year)RealClock.Year=0;//到100归0
//将其转换成16进制,以方便写入Ds1302的年寄存器单元
i=((RealClock.Year/10)<<4)|(RealClock.Year%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8c,i);//写入Ds1302的年寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://月份校准状态
RealClock.Month++;//设置的月变量加1
if(12<RealClock.Month)RealClock.Month=1;//到12归1
//将其转换成16进制,以方便写入Ds1302的月寄存器单元
i=((RealClock.Month/10)<<4)|(RealClock.Month%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x88,i);//设置Ds1302的月寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 4://星期校准状态
RealClock.Week++;//设置星期变量加1
if(7<RealClock.Week)RealClock.Week=1;//到8归1
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8a,RealClock.Week);//写入Ds1302的星期
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://日期校准状态
RealClock.Day++;//设置日的变量加1
switch(RealClock.Month)//根据月份来调整日期最大值
{
case 1://属于一个月中有31天的调整
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if(31<RealClock.Day)RealClock.Day=1;//到32归1
break;
case 4://属于一个月中有30天的调整
case 6:
case 9:
case 11:
if(30<RealClock.Day)RealClock.Day=1;//到31归1
break;
case 2://属于2月份根据是平的还是闰年来调整
if(0==(RealClock.Year%4))//如果是闰年.则
{
if(29<RealClock.Day)RealClock.Day=1;//到30归1
}
else//是平年,则
{
if(28<RealClock.Day)RealClock.Day=1;//到29归1
}
break;
}
//将其转换成16进制,以方便写入Ds1302的日寄存器单元
i=((RealClock.Day/10)<<4)|(RealClock.Day%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x86,i);//写入Ds1302的日寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
//在设置状态下将所调节的内容装入显示缓冲区
if(((DateKeyID>0)||(TimeKeyID>0))&&(0==AlarmKeyID))
{
//将调整的结果送到LED显示缓冲区
LEDBuffer[0]=RealClock.second%10; //秒的个位
LEDBuffer[1]=RealClock.second/10; //秒的十位
LEDBuffer[2]=RealClock.Minute%10; //分的个位
LEDBuffer[3]=RealClock.Minute/10; //分的十位
LEDBuffer[4]=RealClock.Hour%10; //时的个位
LEDBuffer[5]=RealClock.Hour/10; //时的十位
LEDBuffer[6]=RealClock.Week; //星期
LEDBuffer[7]=RealClock.Day%10; //日的个位
LEDBuffer[8]=RealClock.Day/10; //日的十位
LEDBuffer[9]=RealClock.Month%10; //月的个位
LEDBuffer[10]=RealClock.Month/10; //月的十位
LEDBuffer[11]=RealClock.Year%10; //年的个位
LEDBuffer[12]=RealClock.Year/10; //年的十位
}
}
while(0==NUMBERADDKEY);//等待数字增调节键释放
}
//-------------------------------------------------------
//-------------------------------------------------------
//---数字减调节键程序段
if(0==NUMBERsUBKEY)//数字减调节键按下
{
Delay(1000);//去抖动
if(0==NUMBERsUBKEY)//再判断是否真得按下
{
if(TimeKeyID>0)//如果时间设置状态变量是处于设置状态条件下,则
{
switch(TimeKeyID)//根据时间设置状态变量来决定
{
case 1://时间设置的时状态
RealClock.Hour--;//时减1
if(0xFF==RealClock.Hour)RealClock.Hour=23;//到-1则归23
//将其转换成16进制,以方便写入Ds1302的时寄存器单元
i=((RealClock.Hour/10)<<4)|(RealClock.Hour%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x84,i);//写入Ds1302的时寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://时间设置的分状态
RealClock.Minute--;//分减1
if(0xFF==RealClock.Minute)RealClock.Minute=59;//到-1归59
//将其转换成16进制,以方便写入Ds1302的分寄存器单元
i=((RealClock.Minute/10)<<4)|(RealClock.Minute%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x82,i);//写入Ds1302的分寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://时间设置的秒状态
RealClock.second--;//秒减1
if(0xFF==RealClock.second)RealClock.second=59;//到-1归59
//将其转换成16进制,以方便写入Ds1302的秒寄存器单元
i=((RealClock.second/10)<<4)|(RealClock.second%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x80,i);//写入Ds1302的秒寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
if(DateKeyID>0)//日期设置状态变量是处于设置条件下,则
{
switch(DateKeyID)//根据日期设置状态变量来决定
{
case 1://日期设置的年份
RealClock.Year--;//年变量减1
if(0xFF==RealClock.Year)RealClock.Year=99;//到-1归99
//将其转换成16进制,以方便写入Ds1302的年寄存器单元
i=((RealClock.Year/10)<<4)|(RealClock.Year%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8c,i);//写入Ds1302的年寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://日期设置的月份
RealClock.Month--;//月变量减1
if(0==RealClock.Month)RealClock.Month=1;//到0归1
//将其转换成16进制,以方便写入Ds1302的月寄存器单元
i=((RealClock.Month/10)<<4)|(RealClock.Month%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x88,i);//写入Ds1302的月寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://日期设置的日
RealClock.Day--;//日变量减1
if(0==RealClock.Day)RealClock.Day=1;//到0归1
//将其转换成16进制,以方便写入Ds1302的日寄存器单元
i=((RealClock.Day/10)<<4)|(RealClock.Day%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x86,i);//写入Ds1302的天寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 4://日期设置的星期
RealClock.Week--;//星期减1
if(0==RealClock.Week)RealClock.Week=1;//到0归1
//将其转换成16进制,以方便写入Ds1302的星期寄存器单元
i=RealClock.Week%10;
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8a,i);//写入Ds1302的星期寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
//在设置状态下将所调节的内容装入显示缓冲区
if(((DateKeyID>0)||(TimeKeyID>0))&&(0==AlarmKeyID))
{
//将调整的结果送到LED显示缓冲区
LEDBuffer[0]=RealClock.second%10; //秒的个位
LEDBuffer[1]=RealClock.second/10; //秒的十位
LEDBuffer[2]=RealClock.Minute%10; //分的个位
LEDBuffer[3]=RealClock.Minute/10; //分的十位
LEDBuffer[4]=RealClock.Hour%10; //时的个位
LEDBuffer[5]=RealClock.Hour/10; //时的十位
LEDBuffer[6]=RealClock.Week; //星期
LEDBuffer[7]=RealClock.Day%10; //日的个位
LEDBuffer[8]=RealClock.Day/10; //日的十位
LEDBuffer[9]=RealClock.Month%10; //月的个位
LEDBuffer[10]=RealClock.Month/10; //月的十位
LEDBuffer[11]=RealClock.Year%10; //年的个位
LEDBuffer[12]=RealClock.Year/10; //年的十位
}
}
while(0==NUMBERsUBKEY);//等待数字减调节释放
}
//-------------------------------------------------------
//-------------------------------------------------------
//---温度数据采集和滤波完毕,将结果送到显示缓冲区
if(TRUE==TemperatureDisplayFlag)
{
TemperatureDisplayFlag=FALsE;
temp=RealClock.Temp;
temp*=500;
temp/=256;
temp-=273;//将A/D转换的数据根据AD590计算公式转换成温度值
LEDBuffer[15]=16;//数码管灭
if(0x80000000==(temp & 0x80000000))//测量温度为负
{
temp=~temp;//取反
temp++;//加1
}
LEDBuffer[15]=17;//数码管显示负号
LEDBuffer[14]=temp/10;//将温度值存储到缓冲区
LEDBuffer[13]=temp%10;
}
//-------------------------------------------------------
//-------------------------------------------------------
//---定时半秒时间到,读取Ds1302日历和闪烁现象产生
if(TRUE==second_Halfs.Enable)
{
second_Halfs.Enable=FALsE;
if((0==DateKeyID)&&(0==TimeKeyID)&&(0==AlarmKeyID))
{
i=Read_Ds1302_RTC(0x81);//读取Ds1302的秒
RealClock.second=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x83);//读取Ds1302的分
RealClock.Minute=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x85);//读取Ds1302的时
RealClock.Hour=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x87);//读Ds1302的日
RealClock.Day=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x89);//读Ds1302的月
RealClock.Month=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x8b);//读Ds1302的星期
RealClock.Week=i%16;
i=Read_Ds1302_RTC(0x8d);//读Ds1302的年
RealClock.Year=(i/16)*10+(i%16);
}
//---------------------------------------------------
if(AlarmKeyID>0)
{
switch(AlarmKeyID)
{
case 1:
if(0==AlarmClock.status)
{
LEDBuffer[12]=10;//"A"
LEDBuffer[11]=18;//"L"
LEDBuffer[10]=19;//"r"
LEDBuffer[9] =20;//"O"
LEDBuffer[8] =15;//"F"
LEDBuffer[7] =15;//"F"
}
else
{
LEDBuffer[12]=10;//"A"
LEDBuffer[11]=18;//"L"
LEDBuffer[10]=19;//"r"
LEDBuffer[9] =16;//" "
LEDBuffer[8] =20;//"O"
LEDBuffer[7] =21;//"N"
}
break;
case 2:
if((16==LEDBuffer[4])&&(16==LEDBuffer[5]))//灭状态
{
LEDBuffer[4]=AlarmClock.Hour%10;//装入闹铃时钟内容
LEDBuffer[5]=AlarmClock.Hour/10;
}
else
{
LEDBuffer[4]=16;//装入LED灭的内容
LEDBuffer[5]=16;
}
break;
case 3:
if((16==LEDBuffer[2])&&(16==LEDBuffer[3]))//灭状态
{
LEDBuffer[2]=AlarmClock.Minute%10;//装入闹铃分钟内容
LEDBuffer[3]=AlarmClock.Minute/10;
}
else
{
LEDBuffer[2]=16;//装入LED灭的内容
LEDBuffer[3]=16;
}
break;
case 4:
if((16==LEDBuffer[0])&&(16==LEDBuffer[1]))//灭状态
{
LEDBuffer[0]=AlarmClock.Day%10;//装入闹铃秒钟内容
LEDBuffer[1]=AlarmClock.Day/10;
}
else
{
LEDBuffer[0]=16;//装入LED灭的内容
LEDBuffer[1]=16;
}
break;
}
}
//---------------------------------------------------
//---------------------------------------------------
//---校准日期和星期时,以闪烁现象提示
if(DateKeyID>0)
{
switch(DateKeyID)
{
case 1:
if((16==LEDBuffer[11])&&(16==LEDBuffer[12]))//灭状态
{
LEDBuffer[11]=RealClock.Year%10;//装入年份内容
LEDBuffer[12]=RealClock.Year/10;
}
else
{
LEDBuffer[11]=16;//装入LED灭的内容
LEDBuffer[12]=16;
}
break;
case 2:
if((16==LEDBuffer[9])&&(16==LEDBuffer[10]))//灭状态
{
LEDBuffer[9]=RealClock.Month%10;//装入月份内容
LEDBuffer[10]=RealClock.Month/10;
}
else
{
LEDBuffer[9]=16;//装入LED灭的内容
LEDBuffer[10]=16;
}
break;
case 3:
if((16==LEDBuffer[7])&&(16==LEDBuffer[8]))//灭状态
{
LEDBuffer[7]=RealClock.Day%10;//装入年份内容
LEDBuffer[8]=RealClock.Day/10;
}
else
{
LEDBuffer[7]=16;//装入LED灭的内容
LEDBuffer[8]=16;
}
break;
case 4:
if(16==LEDBuffer[6])LEDBuffer[6]=RealClock.Week;
else LEDBuffer[6]=16;
break;
}
}
//---------------------------------------------------
//---------------------------------------------------
//---校准时间时,以闪烁现象提示
if(TimeKeyID>0)
{
switch(TimeKeyID)
{
case 1:
if((16==LEDBuffer[4])&&(16==LEDBuffer[5]))//灭状态
{
LEDBuffer[4]=RealClock.Hour%10;//装入时钟内容
LEDBuffer[5]=RealClock.Hour/10;
}
else
{
LEDBuffer[4]=16;//装入LED灭的内容
LEDBuffer[5]=16;
}
break;
case 2:
if((16==LEDBuffer[2])&&(16==LEDBuffer[3]))//灭状态
{
LEDBuffer[2]=RealClock.Minute%10;//装入分钟内容
LEDBuffer[3]=RealClock.Minute/10;
}
else
{
LEDBuffer[2]=16;//装入LED灭的内容
LEDBuffer[3]=16;
}
break;
case 3:
if((16==LEDBuffer[0])&&(16==LEDBuffer[1]))//灭状态
{
LEDBuffer[0]=RealClock.Day%10;//装入秒钟内容
LEDBuffer[1]=RealClock.Day/10;
}
else
{
LEDBuffer[0]=16;//装入LED灭的内容
LEDBuffer[1]=16;
}
break;
}
}
//---------------------------------------------------
//---------------------------------------------------
//---将闪烁现象送到LED数码管显示
if((DateKeyID>0)||(TimeKeyID>0)||(AlarmKeyID>0))
sendDataToLED(LEDBuffer,sizeof(LEDBuffer));
//---------------------------------------------------
}
//-------------------------------------------------------
//---定时1s时间到,送出显示
if(TRUE==second_1s.Enable)
{
second_1s.Enable=FALsE;
if((0==DateKeyID)&&(0==TimeKeyID)&&(0==AlarmKeyID))
sendDataToLED(LEDBuffer,sizeof(LEDBuffer));
}
//-------------------------------------------------------
}
}
//-------------------------------------------------------------
//---低优先中断服务程序
#pragma interruptlow TMR0_TMR1_IsR
void TMR0_TMR1_IsR(void)
{
unsigned char i,j,temp;
if(TRUE==INTCONbits.TMR0IF)//定时100ms溢出
{
INTCONbits.TMR0IF=FALsE;//清TMR0溢出中断标志
TMR0L=256-25;//装入新的初值
second_Halfs.Interval++;
if(5==second_Halfs.Interval)//每0.5秒读Ds1302和闪烁
{
second_Halfs.Interval=0;
second_Halfs.Enable=TRUE;
}
second_1s.Interval++;
if(10==second_1s.Interval)
{
second_1s.Interval=0;
second_1s.Enable=TRUE;
}
if(0==ADCON0bits.DONE)//判断A/D转换是否完毕
{
ADCBuffer[ADCBufferPointer]=ADREsH;//装入当前缓冲区
ADCON0bits.GO=1;//重新启动A/D开始转换
ADCBufferPointer++;//指针加1
if(ADCBufferPointer==sizeof(ADCBuffer))//缓冲区装满否
{
ADCBufferPointer=0;//指针初始化
//将缓冲区的内容按从大到小排序
for(i=0;i<sizeof(ADCBuffer);i++)
for(j=i;j<sizeof(ADCBuffer);j++)
{
if(ADCBuffer
<ADCBuffer[j])
{
temp=ADCBuffer
;
ADCBuffer
=ADCBuffer[j];
ADCBuffer[j]=temp;
}
}
//取缓冲区中间的数值作为当前测量到的温度值数据
RealClock.Temp=ADCBuffer[sizeof(ADCBuffer)/2];
TemperatureDisplayFlag=TRUE;
}
}
}
}
加载中...
查看其它10个回答
一周热门
更多
>
相关问题
PIC单片机不同的IO口驱动74HC573驱动共阴极的数码管,有的段不亮
1 个回答
一种简单精确的pic延时方法
21 个回答
谁熟悉PIC的产品发布时间的,帮看看PIC18F47K40啥版本IDE能开发
12 个回答
求AN1078对应的源代码下载地址
5 个回答
PIC单片机应用技巧
4 个回答
相关文章
一种用PIC单片机主时钟驱动的老式挂钟
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
PIC单片机
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
用pic16f685.h这个报错吗?如果源程序短你贴上来,我编译一下试试
-----------------------------------------------------------------------
用PIC16F685也试了不行.
#include <pic16f685.h> //头文件引用
//大LED数码管显示代码表
const unsigned char LEDCODE[]=
{
0x3F,0x06,0x5B,0x4F,//0,1,2,3
0x66,0x6D,0x7D,0x07,//4,5,6,7
0x7F,0x6F, //8,9
};
//宏定义
#define TRUE 1
#define FALsE 0
//-------------------------------------------------------------
//---定义软件定时器定时1s和0.5秒结构体变量
struct TIMER_sTRUCT
{
unsigned int Interval;
unsigned char Enable;
};
struct TIMER_sTRUCT second_1s,second_Halfs;
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义实时带温度与闹铃功能的日历/时钟结构体变量
struct REALCLOCK_sTRUCT
{
unsigned char Year; //年份
unsigned char Month; //月份
unsigned char Day; //日
unsigned char Week; //星期
unsigned char Hour; //时
unsigned char Minute; //分
unsigned char second; //秒
unsigned char Temp; //温度
};
struct REALCLOCK_sTRUCT RealClock;
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义定时闹钟结构体变量
struct ALARMCLOCK_sTRUCT
{
unsigned char Day; //日
unsigned char Week; //星期
unsigned char Hour; //时
unsigned char Minute; //分
unsigned char second; //秒
unsigned char status; //状态
};
struct ALARMCLOCK_sTRUCT AlarmClock;
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义PIC单片机与74HC595芯片接口连接关系
#define HC595_sER LATCbits.LATC0
#define HC595_RCLK LATCbits.LATC1
#define HC595_sRCLK LATCbits.LATC2
#define HC595_sRCLR LATCbits.LATC3
#define HC595_OE LATCbits.LATC4
//---定义LED数码管显示缓冲区
unsigned char LEDBuffer[16];
//---定义大LED数码管初始化函数
void InitizeLED(void)
{
HC595_OE=1;//并行输出为高阻状态
HC595_sRCLR=0;//清空移位寄存器
HC595_sER=0;//清零
HC595_RCLK=0;//移位时钟初始为低
HC595_sRCLK=0;//存储器时钟初始为低
HC595_OE=0;//允许并行输出
HC595_sRCLR=1;//结束复位状态
}
//---定义大LED显示驱动函数
//*LedData指针,DataLength数据长度
void sendDataToLED(unsigned char *LedData,unsigned char DataLength)
{
unsigned char i,j,temp;
for(j=0;j<DataLength;j++)
{
temp=LEDCODE[*LedData];//取出LED显示的代码表送入变量中
for(i=0;i<8;i++)
{
if(0x80==(temp & 0x80))HC595_sER=1;//将字节按位移出
else HC595_sER=0;
HC595_RCLK=1;//将数据送入移位寄存器中
HC595_RCLK=0;
temp<<=1;//当前指针的内容左移一位
}
LedData++;//指针指向下一个数据
}
HC595_sRCLK=1;//将移位寄存器中的内容送到并行输出口
HC595_sRCLK=0;
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义PIC单片机与Ds1302引脚之间的连接关系
#define Ds1302CE_1 LATCbits.LATC5=1
#define Ds1302CE_0 LATCbits.LATC5=0
#define Ds1302CE_O TRIsC &=0xDF
#define Ds1302IO_O TRIsC &=0xBF
#define Ds1302IO_I TRIsC |=0x20
#define Ds1302IO_1 LATCbits.LATC6=1
#define Ds1302IO_0 LATCbits.LATC6=0
#define Ds1302IO_D PORTC & 0x40
#define Ds1302CK_1 LATCbits.LATC7=1
#define Ds1302CK_0 LATCbits.LATC7=0
#define Ds1302CK_O TRIsC &=0x7F
//---Ds1302初始化函数
void Init_Ds1302_RTC(void)
{
Ds1302CK_O;//置CK为输出
Ds1302CE_O;//置CE为输出
Ds1302CE_0;//输出为0
Ds1302CK_0;//输出为0
Ds1302IO_1;//置IO为输入
Ds1302IO_I;
}
//---读取Ds1302日历函数
unsigned char Read_Ds1302_RTC(unsigned char RTC_Address)
{
unsigned char i;
unsigned int temp;
Ds1302CE_0;//CE=0
Ds1302CK_0;//CK=0
Ds1302IO_O;//Ds1302为IO为输出
_asm//简短延时
NOP
NOP
_endasm
Ds1302CE_1;//CE=1
_asm//简短延时
NOP
NOP
_endasm
for(i=8;i>0;i--)//CPU送出访问Ds1302的地址
{ //以串行方式从PIC单片机的RC6引脚输出
if(RTC_Address & 0x01)Ds1302IO_1;
else Ds1302IO_0;
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
RTC_Address>>=1;//右移一位
}
Ds1302IO_1;//PIC单片机的RC7为输入状态
_asm//简短延时
NOP
NOP
_endasm
Ds1302IO_I;
_asm//简短延时
NOP
NOP
_endasm
temp=0;
if(Ds1302IO_D)temp|=0x8000;
temp>>=1;//右移一位
for(i=7;i>0;i--)
{
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
if(Ds1302IO_D)temp|=0x8000;//RC7引脚上的电平并保存到变量中
temp>>=1;//右移一位
}
Ds1302CE_0;//CE=0
temp<<=1;//左移一位
return(temp/256);//返回读取到的内容
}
//---写入Ds1302日历函数
void Write_Ds1302_RTC(unsigned char RTC_Address,unsigned char RTC_Data)
{
unsigned char i;
Ds1302CE_0;//CE为输出
Ds1302CK_0;//CK为输出
Ds1302IO_O;//IO为输出
_asm//简短延时
NOP
NOP
_endasm
Ds1302CE_1;//CE=1
_asm//简短延时
NOP
NOP
_endasm
for(i=8;i>0;i--)
{ //送地址给Ds1302
if(RTC_Address & 0x01)Ds1302IO_1;
else Ds1302IO_0;
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
RTC_Address>>=1;//右移一位
}
for(i=8;i>0;i--)
{ //送数据给Ds1302
if(RTC_Data & 0x01)Ds1302IO_1;
else Ds1302IO_0;
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_1;//CK=1
_asm//简短延时
NOP
NOP
_endasm
Ds1302CK_0;//CK=0
_asm//简短延时
NOP
NOP
_endasm
RTC_Data>>=1;//右移一位
}
Ds1302CE_0;//CE=0
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---定义ADC缓冲区,和指针变量
unsigned char ADCBuffer[5]; //ADC采集缓冲区
unsigned char ADCBufferPointer; //ADC采集缓冲区指针
unsigned char TemperatureDisplayFlag; //当缓冲区满时,处理完后标志
//---ADC初始化函数定义
void ADC_Initize(void)
{
unsigned char i;
ADCON1=0x07;//初始化ADC的参考电压取VCC,GND
ADCON2=0x00;//左对齐,0TAD,FOsC/2
ADCON0=0x03;//选择通道0,启动A/D转换开始
//初始化ADCBuffer变量指针和缓冲区
ADCBufferPointer=0;
for(i=0;i<sizeof(ADCBuffer);i++)ADCBuffer=0;
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---初始化PIC18F单片机工作于内部时钟8MHz状态下
void INTOsC_Initize(void)
{
OsCCON=0x70;//选择内部8MHz的主振荡器
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---TMR0定时器初始化函数
void TMR0_Initize(void)
{
T0CONbits.TMR0ON=FALsE;//TMR0停止运行
T0CON=0x12;//TMR0初始化为8位定时,预分频比为1:8
TMR0L=256-25;//定时100ms初值
T0CONbits.TMR0ON=TRUE;
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---延时函数的定义
void Delay(unsigned int t)
{
while(t--);
}
//-------------------------------------------------------------
//-------------------------------------------------------------
//---按键引脚的定义
#define DATEKEY PORTBbits.RA1
#define TIMEKEY PORTBbits.RA2
#define ALARMKEY PORTBbits.RA5
#define NUMBERADDKEY PORTBbits.RA3
#define NUMBERsUBKEY PORTBbits.RA4
//---功能按键状态变量定义
unsigned char DateKeyID;
unsigned char TimeKeyID;
unsigned char AlarmKeyID;
//-------------------------------------------------------------
//-------------------------------------------------------------
//定时器低优先级中断入口函数声明
void TMR0_TMR1_IsR(void);
#pragma code low_vector=0x18
void low_interrupt(void)
{
_asm goto TMR0_TMR1_IsR _endasm
}
#pragma code
//-------------------------------------------------------------
//-------------------------------------------------------------
//---主程序 main函数
void main(void)
{
unsigned char i,j;
unsigned long temp;
INTOsC_Initize(); //初始化时钟源
TMR0_Initize(); //初始化TMR0定时器
ADC_Initize(); //初始化A/D模块
InitizeLED(); //初始化LED数码管显示
INTCONbits.GIE=1; //CPU开中断
INTCONbits.PEIE=1; //CPU的第二梯队中断允许
while(1)
{
//-------------------------------------------------------
//---功能键及数字调节键识别与处理过程
//---
//-------------------------------------------------------
//---闹铃设置功能键
if(0==ALARMKEY) //闹铃设置键是否按下
{
Delay(1000); //去抖动
if(0==ALARMKEY)//是真得按下了吗
{
AlarmKeyID++; //闹铃设置状态变量加1
if(1==AlarmKeyID)//在闹铃设置状态为1的情况下,复制当前日历的内容到闹铃变量中
{
AlarmClock.second=RealClock.second; //复制秒
AlarmClock.Minute=RealClock.Minute; //复制分
AlarmClock.Hour=RealClock.Hour; //复制时
AlarmClock.Week=RealClock.Week; //复制日
AlarmClock.Day=RealClock.Day; //复制星期
}
if(0==AlarmClock.status)//如果闹铃是关闭的,则
{
if(2==AlarmKeyID)AlarmKeyID=0;//直接回到正常状态
}
else//如果是闹铃是打开的,则
{
if(5==AlarmKeyID)AlarmKeyID=0;//可以设置时分秒闹铃时间
}
}
while(0==ALARMKEY); //等待按键释放
}
//-------------------------------------------------------
//---校准日期的功能键
if(0==DATEKEY)//日期校准按键是否按下
{
Delay(1000);//去按键抖动
if(0==DATEKEY)//再判断是否真得按下
{
TimeKeyID=0;//其它校准或设置变量状态为正常状态
AlarmKeyID=0;
DateKeyID++;//校准日期状态变量加1
if(5==DateKeyID)DateKeyID=0;//所有校准完毕,回到正常状态
}
while(0==DATEKEY);//等待按键释放
}
//-------------------------------------------------------
//-------------------------------------------------------
//---校准时间的功能键
if(0==TIMEKEY)
{
Delay(1000);
if(0==TIMEKEY)
{
DateKeyID=0;//其它校准或设置变量状态为正常状态
AlarmKeyID=0;
TimeKeyID++;
if(4==TimeKeyID)TimeKeyID=0;
}
while(0==TIMEKEY);
}
//-------------------------------------------------------
//-------------------------------------------------------
//---数字加调节键
if(0==NUMBERADDKEY)//数字增调节键按下了
{
Delay(1000);//去抖动
if(0==NUMBERADDKEY)//再判断是否真得按下
{
if(AlarmKeyID>0)//如果闹铃设置状态是处于设置条件下,则
{
switch(AlarmKeyID)//根据闹铃状态变量来分析调节哪个功能
{
case 1://闹铃打开/关闭设置状态
//如果闹铃关闭则打开,否则关闭
if(0==AlarmClock.status)AlarmClock.status=1;
else AlarmClock.status=0;
break;
case 2://设置闹铃的时状态
if(0!=AlarmClock.status) //如果闹铃是打开的,则
{
AlarmClock.Hour++;//闹铃的时变量加1
if(24==AlarmClock.Hour)AlarmClock.Hour=0;//到24归0
}
break;
case 3://设置闹铃的分状态
if(0!=AlarmClock.status)//如果闹铃是打开的,则
{
AlarmClock.Minute++;//闹铃的分变量加1
if(60==AlarmClock.Minute)AlarmClock.Minute=0;//到60归0
}
break;
case 4://设置闹铃的秒状态
if(0!=AlarmClock.status) //如果闹铃是打开的,则
{
AlarmClock.second++;//闹铃的秒变量加1
if(60==AlarmClock.second)AlarmClock.second=0;//到60归0
}
break;
}
if((AlarmKeyID>1)&&((0==DateKeyID)||(0==TimeKeyID)))
{
//将调整的结果送到LED显示缓冲区
LEDBuffer[0]=AlarmClock.second%10;
LEDBuffer[1]=AlarmClock.second/10;
LEDBuffer[2]=AlarmClock.Minute%10;
LEDBuffer[3]=AlarmClock.Minute/10;
LEDBuffer[4]=AlarmClock.Hour%10;
LEDBuffer[5]=AlarmClock.Hour/10;
}
}
if(TimeKeyID>0)//如果时间设置状态是处于设置状态条件下,则
{
switch(TimeKeyID)//根据时间设置状态变量的数值来决定
{
case 1://时间设置的时状态
RealClock.Hour++;//时间设置时加1
if(24==RealClock.Hour)RealClock.Hour=0;//到24归0
//将其转换成16进制,以方便写入Ds1302的时寄存器单元
i=((RealClock.Hour/10)<<4)|(RealClock.Hour%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x84,i);//写入Ds1302的时寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://时间设置的分状态
RealClock.Minute++;//时间设置的分加1
if(60==RealClock.Minute)RealClock.Minute=0;//到60归0
//将其转换成16进制,以方便写入Ds1302的分寄存器单元
i=((RealClock.Minute/10)<<4)|(RealClock.Minute%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x82,i);//写入Ds1302的分寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://时间设置的秒状态
RealClock.second++;//时间设置的秒变量加1
if(60==RealClock.second)RealClock.second=0;//到60归0
//将其转换成16进制,以方便写入Ds1302的秒寄存器单元
i=((RealClock.second/10)<<4)|(RealClock.second%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x80,i);//写入Ds1302的秒寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
if(DateKeyID>0)//如果日期设置状态变量处于设置状态条件下,则
{
switch(DateKeyID)//根据日期设置状态变量的内容来决定
{
case 1://年份校准状态
RealClock.Year++;//设置的年变量加1
if(99<RealClock.Year)RealClock.Year=0;//到100归0
//将其转换成16进制,以方便写入Ds1302的年寄存器单元
i=((RealClock.Year/10)<<4)|(RealClock.Year%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8c,i);//写入Ds1302的年寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://月份校准状态
RealClock.Month++;//设置的月变量加1
if(12<RealClock.Month)RealClock.Month=1;//到12归1
//将其转换成16进制,以方便写入Ds1302的月寄存器单元
i=((RealClock.Month/10)<<4)|(RealClock.Month%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x88,i);//设置Ds1302的月寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 4://星期校准状态
RealClock.Week++;//设置星期变量加1
if(7<RealClock.Week)RealClock.Week=1;//到8归1
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8a,RealClock.Week);//写入Ds1302的星期
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://日期校准状态
RealClock.Day++;//设置日的变量加1
switch(RealClock.Month)//根据月份来调整日期最大值
{
case 1://属于一个月中有31天的调整
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if(31<RealClock.Day)RealClock.Day=1;//到32归1
break;
case 4://属于一个月中有30天的调整
case 6:
case 9:
case 11:
if(30<RealClock.Day)RealClock.Day=1;//到31归1
break;
case 2://属于2月份根据是平的还是闰年来调整
if(0==(RealClock.Year%4))//如果是闰年.则
{
if(29<RealClock.Day)RealClock.Day=1;//到30归1
}
else//是平年,则
{
if(28<RealClock.Day)RealClock.Day=1;//到29归1
}
break;
}
//将其转换成16进制,以方便写入Ds1302的日寄存器单元
i=((RealClock.Day/10)<<4)|(RealClock.Day%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x86,i);//写入Ds1302的日寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
//在设置状态下将所调节的内容装入显示缓冲区
if(((DateKeyID>0)||(TimeKeyID>0))&&(0==AlarmKeyID))
{
//将调整的结果送到LED显示缓冲区
LEDBuffer[0]=RealClock.second%10; //秒的个位
LEDBuffer[1]=RealClock.second/10; //秒的十位
LEDBuffer[2]=RealClock.Minute%10; //分的个位
LEDBuffer[3]=RealClock.Minute/10; //分的十位
LEDBuffer[4]=RealClock.Hour%10; //时的个位
LEDBuffer[5]=RealClock.Hour/10; //时的十位
LEDBuffer[6]=RealClock.Week; //星期
LEDBuffer[7]=RealClock.Day%10; //日的个位
LEDBuffer[8]=RealClock.Day/10; //日的十位
LEDBuffer[9]=RealClock.Month%10; //月的个位
LEDBuffer[10]=RealClock.Month/10; //月的十位
LEDBuffer[11]=RealClock.Year%10; //年的个位
LEDBuffer[12]=RealClock.Year/10; //年的十位
}
}
while(0==NUMBERADDKEY);//等待数字增调节键释放
}
//-------------------------------------------------------
//-------------------------------------------------------
//---数字减调节键程序段
if(0==NUMBERsUBKEY)//数字减调节键按下
{
Delay(1000);//去抖动
if(0==NUMBERsUBKEY)//再判断是否真得按下
{
if(TimeKeyID>0)//如果时间设置状态变量是处于设置状态条件下,则
{
switch(TimeKeyID)//根据时间设置状态变量来决定
{
case 1://时间设置的时状态
RealClock.Hour--;//时减1
if(0xFF==RealClock.Hour)RealClock.Hour=23;//到-1则归23
//将其转换成16进制,以方便写入Ds1302的时寄存器单元
i=((RealClock.Hour/10)<<4)|(RealClock.Hour%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x84,i);//写入Ds1302的时寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://时间设置的分状态
RealClock.Minute--;//分减1
if(0xFF==RealClock.Minute)RealClock.Minute=59;//到-1归59
//将其转换成16进制,以方便写入Ds1302的分寄存器单元
i=((RealClock.Minute/10)<<4)|(RealClock.Minute%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x82,i);//写入Ds1302的分寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://时间设置的秒状态
RealClock.second--;//秒减1
if(0xFF==RealClock.second)RealClock.second=59;//到-1归59
//将其转换成16进制,以方便写入Ds1302的秒寄存器单元
i=((RealClock.second/10)<<4)|(RealClock.second%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x80,i);//写入Ds1302的秒寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
if(DateKeyID>0)//日期设置状态变量是处于设置条件下,则
{
switch(DateKeyID)//根据日期设置状态变量来决定
{
case 1://日期设置的年份
RealClock.Year--;//年变量减1
if(0xFF==RealClock.Year)RealClock.Year=99;//到-1归99
//将其转换成16进制,以方便写入Ds1302的年寄存器单元
i=((RealClock.Year/10)<<4)|(RealClock.Year%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8c,i);//写入Ds1302的年寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 2://日期设置的月份
RealClock.Month--;//月变量减1
if(0==RealClock.Month)RealClock.Month=1;//到0归1
//将其转换成16进制,以方便写入Ds1302的月寄存器单元
i=((RealClock.Month/10)<<4)|(RealClock.Month%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x88,i);//写入Ds1302的月寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 3://日期设置的日
RealClock.Day--;//日变量减1
if(0==RealClock.Day)RealClock.Day=1;//到0归1
//将其转换成16进制,以方便写入Ds1302的日寄存器单元
i=((RealClock.Day/10)<<4)|(RealClock.Day%10);
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x86,i);//写入Ds1302的天寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
case 4://日期设置的星期
RealClock.Week--;//星期减1
if(0==RealClock.Week)RealClock.Week=1;//到0归1
//将其转换成16进制,以方便写入Ds1302的星期寄存器单元
i=RealClock.Week%10;
Write_Ds1302_RTC(0x8e,0x00);//Ds1302的允许写打开
Write_Ds1302_RTC(0x8a,i);//写入Ds1302的星期寄存器单元
Write_Ds1302_RTC(0x8e,0x80);//Ds1302的禁止写禁止
break;
}
}
//在设置状态下将所调节的内容装入显示缓冲区
if(((DateKeyID>0)||(TimeKeyID>0))&&(0==AlarmKeyID))
{
//将调整的结果送到LED显示缓冲区
LEDBuffer[0]=RealClock.second%10; //秒的个位
LEDBuffer[1]=RealClock.second/10; //秒的十位
LEDBuffer[2]=RealClock.Minute%10; //分的个位
LEDBuffer[3]=RealClock.Minute/10; //分的十位
LEDBuffer[4]=RealClock.Hour%10; //时的个位
LEDBuffer[5]=RealClock.Hour/10; //时的十位
LEDBuffer[6]=RealClock.Week; //星期
LEDBuffer[7]=RealClock.Day%10; //日的个位
LEDBuffer[8]=RealClock.Day/10; //日的十位
LEDBuffer[9]=RealClock.Month%10; //月的个位
LEDBuffer[10]=RealClock.Month/10; //月的十位
LEDBuffer[11]=RealClock.Year%10; //年的个位
LEDBuffer[12]=RealClock.Year/10; //年的十位
}
}
while(0==NUMBERsUBKEY);//等待数字减调节释放
}
//-------------------------------------------------------
//-------------------------------------------------------
//---温度数据采集和滤波完毕,将结果送到显示缓冲区
if(TRUE==TemperatureDisplayFlag)
{
TemperatureDisplayFlag=FALsE;
temp=RealClock.Temp;
temp*=500;
temp/=256;
temp-=273;//将A/D转换的数据根据AD590计算公式转换成温度值
LEDBuffer[15]=16;//数码管灭
if(0x80000000==(temp & 0x80000000))//测量温度为负
{
temp=~temp;//取反
temp++;//加1
}
LEDBuffer[15]=17;//数码管显示负号
LEDBuffer[14]=temp/10;//将温度值存储到缓冲区
LEDBuffer[13]=temp%10;
}
//-------------------------------------------------------
//-------------------------------------------------------
//---定时半秒时间到,读取Ds1302日历和闪烁现象产生
if(TRUE==second_Halfs.Enable)
{
second_Halfs.Enable=FALsE;
if((0==DateKeyID)&&(0==TimeKeyID)&&(0==AlarmKeyID))
{
i=Read_Ds1302_RTC(0x81);//读取Ds1302的秒
RealClock.second=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x83);//读取Ds1302的分
RealClock.Minute=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x85);//读取Ds1302的时
RealClock.Hour=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x87);//读Ds1302的日
RealClock.Day=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x89);//读Ds1302的月
RealClock.Month=(i/16)*10+(i%16);
i=Read_Ds1302_RTC(0x8b);//读Ds1302的星期
RealClock.Week=i%16;
i=Read_Ds1302_RTC(0x8d);//读Ds1302的年
RealClock.Year=(i/16)*10+(i%16);
}
//---------------------------------------------------
if(AlarmKeyID>0)
{
switch(AlarmKeyID)
{
case 1:
if(0==AlarmClock.status)
{
LEDBuffer[12]=10;//"A"
LEDBuffer[11]=18;//"L"
LEDBuffer[10]=19;//"r"
LEDBuffer[9] =20;//"O"
LEDBuffer[8] =15;//"F"
LEDBuffer[7] =15;//"F"
}
else
{
LEDBuffer[12]=10;//"A"
LEDBuffer[11]=18;//"L"
LEDBuffer[10]=19;//"r"
LEDBuffer[9] =16;//" "
LEDBuffer[8] =20;//"O"
LEDBuffer[7] =21;//"N"
}
break;
case 2:
if((16==LEDBuffer[4])&&(16==LEDBuffer[5]))//灭状态
{
LEDBuffer[4]=AlarmClock.Hour%10;//装入闹铃时钟内容
LEDBuffer[5]=AlarmClock.Hour/10;
}
else
{
LEDBuffer[4]=16;//装入LED灭的内容
LEDBuffer[5]=16;
}
break;
case 3:
if((16==LEDBuffer[2])&&(16==LEDBuffer[3]))//灭状态
{
LEDBuffer[2]=AlarmClock.Minute%10;//装入闹铃分钟内容
LEDBuffer[3]=AlarmClock.Minute/10;
}
else
{
LEDBuffer[2]=16;//装入LED灭的内容
LEDBuffer[3]=16;
}
break;
case 4:
if((16==LEDBuffer[0])&&(16==LEDBuffer[1]))//灭状态
{
LEDBuffer[0]=AlarmClock.Day%10;//装入闹铃秒钟内容
LEDBuffer[1]=AlarmClock.Day/10;
}
else
{
LEDBuffer[0]=16;//装入LED灭的内容
LEDBuffer[1]=16;
}
break;
}
}
//---------------------------------------------------
//---------------------------------------------------
//---校准日期和星期时,以闪烁现象提示
if(DateKeyID>0)
{
switch(DateKeyID)
{
case 1:
if((16==LEDBuffer[11])&&(16==LEDBuffer[12]))//灭状态
{
LEDBuffer[11]=RealClock.Year%10;//装入年份内容
LEDBuffer[12]=RealClock.Year/10;
}
else
{
LEDBuffer[11]=16;//装入LED灭的内容
LEDBuffer[12]=16;
}
break;
case 2:
if((16==LEDBuffer[9])&&(16==LEDBuffer[10]))//灭状态
{
LEDBuffer[9]=RealClock.Month%10;//装入月份内容
LEDBuffer[10]=RealClock.Month/10;
}
else
{
LEDBuffer[9]=16;//装入LED灭的内容
LEDBuffer[10]=16;
}
break;
case 3:
if((16==LEDBuffer[7])&&(16==LEDBuffer[8]))//灭状态
{
LEDBuffer[7]=RealClock.Day%10;//装入年份内容
LEDBuffer[8]=RealClock.Day/10;
}
else
{
LEDBuffer[7]=16;//装入LED灭的内容
LEDBuffer[8]=16;
}
break;
case 4:
if(16==LEDBuffer[6])LEDBuffer[6]=RealClock.Week;
else LEDBuffer[6]=16;
break;
}
}
//---------------------------------------------------
//---------------------------------------------------
//---校准时间时,以闪烁现象提示
if(TimeKeyID>0)
{
switch(TimeKeyID)
{
case 1:
if((16==LEDBuffer[4])&&(16==LEDBuffer[5]))//灭状态
{
LEDBuffer[4]=RealClock.Hour%10;//装入时钟内容
LEDBuffer[5]=RealClock.Hour/10;
}
else
{
LEDBuffer[4]=16;//装入LED灭的内容
LEDBuffer[5]=16;
}
break;
case 2:
if((16==LEDBuffer[2])&&(16==LEDBuffer[3]))//灭状态
{
LEDBuffer[2]=RealClock.Minute%10;//装入分钟内容
LEDBuffer[3]=RealClock.Minute/10;
}
else
{
LEDBuffer[2]=16;//装入LED灭的内容
LEDBuffer[3]=16;
}
break;
case 3:
if((16==LEDBuffer[0])&&(16==LEDBuffer[1]))//灭状态
{
LEDBuffer[0]=RealClock.Day%10;//装入秒钟内容
LEDBuffer[1]=RealClock.Day/10;
}
else
{
LEDBuffer[0]=16;//装入LED灭的内容
LEDBuffer[1]=16;
}
break;
}
}
//---------------------------------------------------
//---------------------------------------------------
//---将闪烁现象送到LED数码管显示
if((DateKeyID>0)||(TimeKeyID>0)||(AlarmKeyID>0))
sendDataToLED(LEDBuffer,sizeof(LEDBuffer));
//---------------------------------------------------
}
//-------------------------------------------------------
//---定时1s时间到,送出显示
if(TRUE==second_1s.Enable)
{
second_1s.Enable=FALsE;
if((0==DateKeyID)&&(0==TimeKeyID)&&(0==AlarmKeyID))
sendDataToLED(LEDBuffer,sizeof(LEDBuffer));
}
//-------------------------------------------------------
}
}
//-------------------------------------------------------------
//---低优先中断服务程序
#pragma interruptlow TMR0_TMR1_IsR
void TMR0_TMR1_IsR(void)
{
unsigned char i,j,temp;
if(TRUE==INTCONbits.TMR0IF)//定时100ms溢出
{
INTCONbits.TMR0IF=FALsE;//清TMR0溢出中断标志
TMR0L=256-25;//装入新的初值
second_Halfs.Interval++;
if(5==second_Halfs.Interval)//每0.5秒读Ds1302和闪烁
{
second_Halfs.Interval=0;
second_Halfs.Enable=TRUE;
}
second_1s.Interval++;
if(10==second_1s.Interval)
{
second_1s.Interval=0;
second_1s.Enable=TRUE;
}
if(0==ADCON0bits.DONE)//判断A/D转换是否完毕
{
ADCBuffer[ADCBufferPointer]=ADREsH;//装入当前缓冲区
ADCON0bits.GO=1;//重新启动A/D开始转换
ADCBufferPointer++;//指针加1
if(ADCBufferPointer==sizeof(ADCBuffer))//缓冲区装满否
{
ADCBufferPointer=0;//指针初始化
//将缓冲区的内容按从大到小排序
for(i=0;i<sizeof(ADCBuffer);i++)
for(j=i;j<sizeof(ADCBuffer);j++)
{
if(ADCBuffer<ADCBuffer[j])
{
temp=ADCBuffer;
ADCBuffer=ADCBuffer[j];
ADCBuffer[j]=temp;
}
}
//取缓冲区中间的数值作为当前测量到的温度值数据
RealClock.Temp=ADCBuffer[sizeof(ADCBuffer)/2];
TemperatureDisplayFlag=TRUE;
}
}
}
}
一周热门 更多>