基于PIC16F887单片机的数字钟完整c程序代码
更新时间:2023-12-22 12:09:01 阅读量: 教育文库 文档下载
#include
__CONFIG (0x20F1); __CONFIG (0x3FFF); //调试用
#define LCD_E RD6 //LCD E 读写使能控制 #define LCD_RW RD5 //LCD 读(1)/写(0)控制线
#define LCD_RS RD4 //LCD 寄存器选择 数据(1)指令(0) //RD4-RD7分别接DB4-DB7,RD7为忙标志 #define COM 0 //在LCD_WRITE()中的第2参数为0表示写命令 #define DAT 1 //在LCD_WRITE()中的第2参数为1表示写数据
#define mod RB3//模式选择(时间、闹钟、温度、秒表) #define set RB0//选择按键 #define add RB1//加按键 #define miu RB2//减按键
#define RTR 0b00000000 //TC74的读温度命令 #define TC74_ADD 0b1001101 //TC74的7位地址
#define LINE1 0b10000000 #define LINE2 0b11000000
signed char hourt,mint,sect;//闹钟设置位 int f;//闹钟显示清零判断 char flag=0;//按键标志位
char WW,QW,BW,SW,GW,M;
char table[]=\星期 signed char year,month,day,week,hour,min,sec,a,T;
bank1 char DD[16]; //一行LCD显示数据暂存 char A[7];//DS1307读数
//====LCD程序 void CSH(void); //初始化 void LCD_CSH(void); //LCD初始化 void LCD_BUSY(void); //检测LCD是否忙 char LCD_READ(void); //读LCD,忙检测用 void LCD_WRITE(char,char); //LCD写1字节,命令或数据 void LCD_WRITE_4(char,char); //LCD写半字节 void DISP_C(char); //在指定行中显示字符,字符在数组DD中 void DISP_MENU(const char *); //由常数数组显示整屏字符
void DELAY_US(char); void DELAY(unsigned int); void delaynms(unsigned int);
//===DS1307
void IIC_SEND(char); void IIC_CSH(void);
void READ_DS1307(char addr,char n); void write_DS1307(char addr,char data); void DS1307_CSH(void);//DS1307初始化 void MENU_DS1307(void);
//==温度
void DISP_T(signed char R1); //温度在R1
signed char READ_T(void);
void clock();//闹钟
void set_time(void);//按键
void bcd_dec(char adr,char R); char dec_bcd(char dec); void BCD(unsigned int R1);
void guangbiao(void);//光标
//========主程序 void main() { CSH(); READ_DS1307(0,7);//读DS1307 if(A[0]&0x80) DS1307_CSH();//判断是否初始化 while(1) { clock(); set_time();//按键检测 delaynms(50); if(flag==0) { READ_DS1307(0,7);//读DS1307
MENU_DS1307();//显示DS1307 T=READ_T();//读温度 DISP_T(T);//显示温度 } } }
//========初始化端口 void CSH(void) { TRISD=0b00000000; //控制LCD1604,全为输出 RD7=1; //背光 TRISB=0x0FF; RBPU=0;
WPUB=0x0FF; ANSELH=0; PORTB=0x00; //===PWM设置 TRISC1=0; //RC1为输出 RC1=0; PR2=124; //周期为1ms CCPR2L=0x32; CCP2CON=0b00000000;//关闭PWM T2CON=0b00000110; //TMR2预分频1:16,开始工 IIC_CSH(); LCD_CSH(); }
//LCD模块初始化 void LCD_CSH(void) { DELAY(20); //延时20ms LCD_WRITE_4(0b0011,COM); //发送控制序列 DELAY_US(10); //延时100us LCD_WRITE_4(0b0011,COM); //发送控制序列 DELAY_US(10); //延时100us LCD_WRITE_4(0b0011,COM); //发送控制序列 DELAY_US(10); //延时100us LCD_WRITE_4(0b0010,COM); //4位数据格式 LCD_BUSY(); //LCD忙检测 LCD_WRITE(0b00101000,COM); //4位数据格式,2行,5×7点阵
LCD_WRITE(0b00001100,COM); //D(d2)=1:打开显示,C(d1)=1:光标打开,B(d0)=1:光标不闪烁 LCD_WRITE(0b00000001,COM); //清除显示 DELAY(2); //延时2ms LCD_WRITE(0b00000110,COM); //输入模式,I/D(d1)=1:地址加1,S(d0)=1:显示移位关闭 }
//========读LCD状态 char LCD_READ(void) { unsigned char R1; TRISD|=0X0F; //LCD数据线为输入 LCD_RS=0; //寄存器选择 LCD_RW=1;NOP(); //读为1 LCD_E=1;NOP(); //使能 R1=0; //短延时 R1=(PORTD<<4 )& 0xF0; //读数据的高4位给R1高四位 LCD_E=0;NOP(); //读数据结束 LCD_E=1;NOP(); //使能 R1 |= (PORTD & 0x0F); //读PORTD的低4位,R1的高4位不变! LCD_E=0;NOP(); //读数据结束 LCD_RW=0; return (R1); }
//写一字节数R1,FLAG为写命令或数据选择,0为写命令,1为写数据 //写之前先检查是否忙,写完后延时100us,分二次写4位数据/命令 void LCD_WRITE(char R1,char FLAG) { char R2; TRISD&=0XF0; LCD_BUSY(); R2=R1 & 0xF0; //低4位清0 R2=R2>>4; //取高4位 LCD_WRITE_4(R2,FLAG); //先写高4位 R2=(R1 & 0x0F); //高4位清0,取低4位 LCD_WRITE_4(R2,FLAG); //再送低4位 DELAY_US(10); //延时100us }
//写R1的低4位,FLAG为寄存器选择,1为命令,0为数据 void LCD_WRITE_4(char R1,char FLAG) { TRISD&=0XF0; LCD_RW=0;NOP(); //写模式 LCD_RS=FLAG;NOP(); //寄存器选择
PORTD &= 0xF0;NOP(); //RD低4位先清0 LCD_E=1;NOP(); //使能 R1=(R1&0x0F); //R1低4位送至低4位 PORTD |=R1;NOP(); //送4位 LCD_E=0;NOP(); //数据送入有效,下降沿送入 LCD_RS=0;NOP(); PORTD &= 0xF0; //RD低4位清0 }
//========检测LCD是否忙 void LCD_BUSY(void) { unsigned char R1; while(1) { R1=LCD_READ(); //读寄存器 if ((R1 & 0x80)==0x00) //最高位为忙标志位 break; }; }
//======延时(n)ms
void DELAY(unsigned int n) { unsigned int j; char k; for (j=0;j
//======延时(n)ms
void delaynms(unsigned int n) { unsigned int j; char k; for (j=0;j
//======延时(n×10)us void DELAY_US(char n) { char j; for (j=0;j //=======DS1307有关子程序 //===DS1307初始化 void DS1307_CSH() { write_DS1307(0x00,0X00);//秒钟设置 write_DS1307(0x01,0x01);//分钟设置 write_DS1307(0x02,0x01);//小时设置 write_DS1307(0x03,0X01);//星期天设置 write_DS1307(0x04,0x01);//日月设置 write_DS1307(0x05,0x05);//月设置 write_DS1307(0x06,0x12);//年设置 write_DS1307(0x07,0x70);//7脚方波允许,输出1HZ } //==IIC初始化 void IIC_CSH() { TRISC =0b00011000; //SDA,SCL设置为输入 SSPCON=0b00101000; //同步串口使能(SSPEN),主控方式 SMP=0; //使能高速模式(400 kHz) 的压摆率控制 SSPADD=4; //主控模式为波特率值,每位时间T=(SSPADD+1)/Tcy=5us } //发送数R并等待发送完成,收到从机的应答信号 void IIC_SEND(char R) { SSPBUF=R; //发送 while (RW==1); //在主动模式下,判断发送是否完成 while (SSPIF==0); //等待发送完成 while (ACKSTAT==1); //等待从机发送应答信号 NOP(); } //====读写DS1307程序 void write_DS1307(char addr,char data) { SEN=1; //发送起始位 while(SEN==1); //检测起始位完成 IIC_SEND(0b11010000); //送DS1307的七位地址和写功能 IIC_SEND(addr); //发送要写入的地址 IIC_SEND(data); //发送要写入的数 PEN=1; //发送停止位 while (PEN==1); //检查停止位结束 } //===读DS1307 void READ_DS1307(char addr,char n) { char i; SEN=1; //产生起始位 while (SEN==1); //检测起始位完成 IIC_SEND(0b11010000); //送DS1307的7位地址 IIC_SEND(addr); //此值为DS1307要读的地址 PEN=1; //发送停止位 while (PEN==1);//检查停止位结束 NOP(); RSEN=1; //发送重新启始位 while(RSEN==1); //检测重新起始位完成 IIC_SEND(0b11010001); //读数据 for (i=0;i //=====显示DS1307 void MENU_DS1307(void) { LCD_WRITE(0b00001100,COM); //D(d2)=1:打开显示,C(d1)=1:光标打开,B(d0)=1:光标不闪烁 char i; LCD_WRITE(LINE1,COM); //DDRAM地址,第1行的第1个字符 LCD_WRITE(' ',DAT); LCD_WRITE('2',DAT); LCD_WRITE('0',DAT); LCD_WRITE((A[6]>>4)+0x30,DAT); LCD_WRITE((A[6]&0x0F)+0x30,DAT); LCD_WRITE('-',DAT); LCD_WRITE((A[5]>>4)+'0',DAT); LCD_WRITE((A[5]&0x0F)+'0',DAT); LCD_WRITE('-',DAT); LCD_WRITE((A[4]>>4)+'0',DAT); LCD_WRITE((A[4]&0x0F)+'0',DAT); LCD_WRITE(' ',DAT); i=A[3]&0x07; LCD_WRITE(table[(i-1)*4],DAT); LCD_WRITE(table[(i-1)*4+1],DAT); LCD_WRITE(table[(i-1)*4+2],DAT); LCD_WRITE(table[(i-1)*4+3],DAT); //LCD_WRITE(' ',DAT); LCD_WRITE(LINE2,COM); //DDRAM地址,第2行的第1个字符 LCD_WRITE(' ',DAT); LCD_WRITE((A[2]>>4)+'0',DAT); LCD_WRITE((A[2]&0x0F)+'0',DAT); LCD_WRITE(0x3A,DAT); LCD_WRITE((A[1]>>4)+'0',DAT); LCD_WRITE((A[1]&0x0F)+'0',DAT); LCD_WRITE(0x3A,DAT); LCD_WRITE((A[0]>>4)+'0',DAT); LCD_WRITE((A[0]&0x0F)+'0',DAT); LCD_WRITE(' ',DAT); } char dec_bcd(char dec) { char bcd; bcd= 0; while(dec >= 10) { dec -= 10; bcd++; } bcd <<= 4; bcd |= dec; return (bcd); } void bcd_dec(char adr,char R) { SW=A[adr]>>4; GW=A[adr]&0x0F; while(SW>0) { R=R+10;SW--; } R+=GW; } //====按键程序 void set_time() { if(mod==0) { delaynms(30); if(mod==0) { while(!mod);//等待 M++; if(M==3) { M=0;flag=0;f=0;a=0; } } } if(M==1)//设置时间 { if(set==0) { delaynms(30); if(set==0) { while(!set); a++; if(a==8) a=0; } } guangbiao();//光标定位,闪烁 if(a==1) { if(add==0) { delaynms(30); if(add==0) { while(!add); bcd_dec(0,sec); sec++; if(sec==60) sec=0; write_DS1307(0,dec_bcd(sec)); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); bcd_dec(0,sec); sec--; if(sec==-1)sec=59; write_DS1307(0,dec_bcd(sec)); } } } if(a==2) { if(add==0) { delaynms(30); if(add==0) { while(!add); bcd_dec(1,min); min++; if(min==60) min=0; write_DS1307(1,dec_bcd(min)); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); bcd_dec(1,min); min--; if(min==-1)min=59; write_DS1307(1,dec_bcd(min)); } } } if(a==3) { if(add==0) { delaynms(30); if(add==0) { while(!add); bcd_dec(2,hour); hour++; if(hour==24)hour=0; write_DS1307(2,dec_bcd(hour)); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); bcd_dec(2,hour); hour--; if(hour==-1)hour=23; write_DS1307(2,dec_bcd(hour)); } } } if(a==4) { if(add==0) { delaynms(30); if(add==0) { while(!add); bcd_dec(3,week); week++; if(week==8)week=1; write_DS1307(3,dec_bcd(week)); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); bcd_dec(3,week); week--; if(week==0)week=7; write_DS1307(3,dec_bcd(week)); } } } if(a==5) { if(add==0) { delaynms(30); if(add==0) { while(!add); bcd_dec(4,day); day++; if(day==32)day=1; write_DS1307(4,dec_bcd(day)); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu);bcd_dec(4,day); day--; if(day==0)day=31; write_DS1307(4,dec_bcd(day)); } } } if(a==6) { if(add==0) { delaynms(30); if(add==0) { while(!add); bcd_dec(5,month); month++; if(month==13)month=1; write_DS1307(5,dec_bcd(month)); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu);bcd_dec(5,month); month--; if(month==0)month=12; write_DS1307(5,dec_bcd(month)); } } } if(a==7) { if(add==0) { delaynms(30); if(add==0) { while(!add); bcd_dec(6,year); year++; if(year==99)year=0; write_DS1307(6,dec_bcd(year)); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); year--; if(year==-1)year=99; bcd_dec(6,year); write_DS1307(6,dec_bcd(year)); } } } READ_DS1307(0,7);//读DS1307 } //====闹钟按键设置 else if(M==2) { f++; flag=1; if(f==1) { a=0; LCD_WRITE(LINE2+1,COM);//显示上次闹铃时间 BCD(hourt); LCD_WRITE(SW+'0',DAT); LCD_WRITE(GW+'0',DAT); LCD_WRITE(LINE2+4,COM); BCD(mint); LCD_WRITE(SW+'0',DAT); LCD_WRITE(GW+'0',DAT); LCD_WRITE(LINE2+7,COM); BCD(sect); LCD_WRITE(SW+'0',DAT); LCD_WRITE(GW+'0',DAT); } if(set==0) //设置时间 { delaynms(30); if(set==0) { while(!set); a++; if(a==4) a=0; } } guangbiao();//光标定位,闪烁 if(a==1) { if(add==0) { delaynms(30); if(add==0) { while(!add); sect++; if(sect==60) sect=0; BCD(sect); LCD_WRITE(LINE2+7,COM); LCD_WRITE(SW+0x30,DAT); LCD_WRITE(GW+0x30,DAT); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); sect--; if(sect==-1)sect=59; BCD(sect); LCD_WRITE(LINE2+7,COM); LCD_WRITE(SW+0x30,DAT); LCD_WRITE(GW+0x30,DAT); } } } if(a==2) { if(add==0) { //显示十位//显示个位//显示十位//显示个位 delaynms(30); if(add==0) { while(!add); mint++; if(mint==60) mint=0; BCD(mint); LCD_WRITE(LINE2+4,COM); LCD_WRITE(SW+0x30,DAT); LCD_WRITE(GW+0x30,DAT); } } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); mint--; if(mint==-1)mint=59; BCD(mint); LCD_WRITE(LINE2+4,COM); LCD_WRITE(SW+0x30,DAT); LCD_WRITE(GW+0x30,DAT); } } } if(a==3) { if(add==0) { delaynms(30); if(add==0) { while(!add); hourt++; if(hourt==24)hour=0; BCD(hourt); LCD_WRITE(LINE2+1,COM); LCD_WRITE(SW+0x30,DAT); LCD_WRITE(GW+0x30,DAT); } //显示十位//显示个位//显示十位//显示个位//显示十位//显示个位 } if(miu==0) { delaynms(30); if(miu==0) { while(!miu); hourt--; if(hourt==-1)hourt=23; BCD(hourt); LCD_WRITE(LINE2+1,COM); LCD_WRITE(SW+0x30,DAT); //显示十位 LCD_WRITE(GW+0x30,DAT); //显示个位 } } } } } //====光标定位 void guangbiao(void) { switch(a) { case(1):LCD_WRITE(0b11001000,COM);LCD_WRITE(0b00001111,COM);break;//定位秒,光标打开,B(d0)=1:光标闪烁 case(2):LCD_WRITE(0b11000101,COM);LCD_WRITE(0b00001111,COM);break;//定位分,光标打开,B(d0)=1:光标闪烁 case(3):LCD_WRITE(0b11000010,COM);LCD_WRITE(0b00001111,COM);break;//定位时,光标打开,B(d0)=1:光标闪烁 case(4):LCD_WRITE(0b10001110,COM);LCD_WRITE(0b00001111,COM);break;//定位星期,光标打开,B(d0)=1:光标闪烁 case(5):LCD_WRITE(0b10001010,COM);LCD_WRITE(0b00001111,COM);break;//定位日,光标打开,B(d0)=1:光标闪烁 case(6):LCD_WRITE(0b10000111,COM);LCD_WRITE(0b00001111,COM);break;//定位月,光标打开,B(d0)=1:光标闪烁 case(7):LCD_WRITE(0b10000100,COM);LCD_WRITE(0b00001111,COM);break;//定位秒,光标打开,B(d0)=1:光标闪烁 case(8):LCD_WRITE(0b10000010,COM);LCD_WRITE(0b00001111,COM);break;//定位秒,光标打开,B(d0)=1:光标闪烁 } } //=====读TC74的温度值 signed char READ_T(void) { signed char R1; SEN=1; //开始条件 while (SEN==1); //检测开始条件是否完成? IIC_SEND(TC74_ADD<<1); //送TC74地址(写) IIC_SEND(RTR); //写RTR命令(写) RSEN=1; //重新开始条件 while (RSEN==1); //等待重新开始条件结束 IIC_SEND((TC74_ADD<<1)+1);//发送TC74地址(读) RCEN=1; //接收使能 while (RCEN==1); //等待接收完成 R1=SSPBUF; //接收数据存入R1 PEN=1; //停止位 while(PEN==0); return(R1); } //从R1双字节数转换为十进制数万位-个位:WW,QW,BW,SW,GW void BCD(unsigned int R1) { WW=0;QW=0;BW=0;SW=0;GW=0; while(R1>=10000) {R1-=10000;WW++;} while(R1>=1000) {R1-=1000;QW++;} while(R1>=100) {R1-=100;BW++;} while(R1>=10) {R1-=10; SW++;} GW=R1; } //===温度显示 void DISP_T(signed char R1) //温度在R1 { char R2; if (R1>=0) BCD(R1); else { R2=~(R1)+1; BCD(R2); } if (R1<0) {LCD_WRITE(LINE2+10,COM); //DDRAM地址,第1行的第5个字符 LCD_WRITE('-',DAT); } if (R1>=0) //只在温度为正时才显示百位 LCD_WRITE(BW+0x30,DAT); //显示百位,数字加上0x30即为相应的ASCII码,下同 LCD_WRITE(SW+0x30,DAT); //显示十位 LCD_WRITE(GW+0x30,DAT); //显示个位 LCD_WRITE(0xDF,DAT); //° LCD_WRITE('C',DAT); LCD_WRITE(' ',DAT); } //====闹钟 void clock() { if(!mod||!set||!add||!miu) {delaynms(30); if(!mod||!set||!add||!miu); CCP2CON=0b00000000; //关PWM模式 } BCD(sect); if(SW==(A[0]>>4)&&GW==(A[0]&0x0F)) {BCD(mint); if(SW==(A[1]>>4)&&GW==(A[1]&0x0F)) {BCD(hourt); if(SW==(A[2]>>4)&&GW==(A[2]&0x0F)) CCP2CON=0b00001100; //开PWM模式 } } }
正在阅读:
基于PIC16F887单片机的数字钟完整c程序代码12-22
2009年东南大学建筑史题目07-04
河南省部分业余电台通信录11-14
发展党员工作问答_发展党员问答02-23
乡镇特产富乡工作总结和下一年工作思路08-04
钢结构专项施工组织方案12-31
2020年《傅雷家书》读后感(五篇模版)08-23
基于ProE二级减速器的设计开题报告09-02
浅谈小学数学自主学习能力的培养03-06
三年级劳动与技术上册教案07-09
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 数字钟
- 单片机
- PIC16F887
- 基于
- 完整
- 代码
- 程序