基于PIC单片机的多功能电子时钟

基于PIC单片机的多功能电子时钟

源起

不久前做一个单片机的课程设计,主要是在液晶显示屏上显示日期时间以及温度。百度好长时间发现绝大部分都是基于51单片机的源程序,移植之后费了好长时间更改,原因是pic和51在一些细节方面有所不同。废话少说上代码,希望可以帮助到大家。

代码

程序目录
  • 原始头文件
  • LCD12864头文件
  • DS1302头文件
  • DS18B20头文件
  • DS1302功能实现C程序
  • 主函数main()
  1. 原始头文件
/ 
//
//__delay_us(15);
//__delay_ms(15);
//使用延时函数前,需定义时钟频率 #define _XTAL_FREQ 12000000
/

#ifndef	__LIAN_PIC_H__
#define	__LIAN_PIC_H__

#define __STAT_BACKWARD_COMPATIBILITY   //兼容PICC低版本  
#include <htc.h>


#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long

#define setbit(y,x)	 y|=(1<<(x))    //setb(p1,2); p12=1;
#define clrbit(y,x)	 y&=~(1<<(x))   //clr(p1,2);  p12=0;
#define getbit(y,x)  (0x01&(y>>(x)))    //获取某一位值 


#endif	//__LIAN_PIC_H__
  1. LCD12864头文件

#ifndef __LCD12864_H__
#define __LCD12864_H__

/******************************lcd12864常用命令******************************                           
0x30	 //基本指令集
0x01	 //清除显示(清零DDRAM)
0x02	 //位址归位,游标回原点
0x04	 //光标左移,整体显示不移动
0x06	 //光标右移,整体显示不移动
0x05	 //光标左移,整体显示移动
0x07	 //光标右移,整体显示移动
0x08	 //显示状态全关
0x0C  //显示开
0x0E  //显示开,游标开
0x0F  //显示开,游标开,游标位置开
0x10  //游标左移
0x14	 //游标右移
0x18	 //整体显示左移,光标跟随
0x1C	 //整体显示又移,光标跟随

					  	
0x36	 //扩展指令集,绘图显示ON
0x34	 //扩展指令集,绘图显示OFF
//2010年8月29日16:11:24		  st7920  并行8bit驱动
****************************************************************************/

#define dport     PORTD     //定义数据口
#define dport_in  TRISD=0xff  //PD端口设为输入
#define dport_out TRISD=0x00  //PD端口设为输出
#define rs        RE0       //并行数据/控制字选择 H:数据  L:控制字      串行片选信号
#define rw        RE1       //并行读/写选择       H:读    L:写	         串行数据信号
#define en        RE2       //并行读写使能        H有效,下降沿锁定数据  串行时钟信号
#define psb       RC3       //串口,并口选择       H:并口  L:串口


//*************** 函数定义 ******************
void lcd12864_io_init(void);
void lcd12864_check_busy(void);
void lcd12864_write_dat(uchar lcd_dat);
void lcd12864_write_com(uchar lcd_com);

//*********************初始化12864操作io口************************
void lcd12864_io_init(void)
{
    
  rs=1;
  rw=1;
  en=1;
  psb=1;    //选择8bit并口
}

//******************读12864读忙状态**********************
void lcd12864_check_busy(void)
{
   
  uint i=20000;	    
  dport_in;       //端口设为输入
  rs=0;
  rw=1;
  en=1;
  while((0x80&dport)&&(i>0))
  {
   
    i--;
  }
  en=0; 	
}

//******************向12864写数据**********************
void lcd12864_write_dat(uchar lcd_dat)
{
   
  lcd12864_check_busy();
  dport_out;
  rs=1;
  rw=0;
  en=1;
  dport=lcd_dat;
  en=0;
}

//******************向12864写指令**********************
void lcd12864_write_com(uchar lcd_com)
{
   
  lcd12864_check_busy();
  dport_out;
  rs=0;
  rw=0;
  en=1;
  dport=lcd_com;
  en=0;
}

#endif
  1. DS1302头文件

#ifndef __DS1302_H__
#define __DS1302_H__



#define SCLK	RC0			//DS1302串行时钟输入引脚
#define DSIO	RC1			//数据输入/输出引脚,具有三态功能
#define RST		RC2			//复位引脚,低电平有效,操作时高电平


//*************** 函数定义 ******************
void ds1302_write(uchar addr,uchar dat);		// 向DS1302命令(地址+数据)
uchar ds1302_read(uchar addr);					// 读取ds1302内容
void ds1302_init();								//ds1302初始化
void ds1302_read_time();						//读取时间函数

uchar TIME[7];									//定义全局变量
#endif


  1. DS18B20头文件
//**************************DS18B20驱动库****************************
//功能:实现对DS18B20的读取
//原理:单总线协议
//注意:单总线协议对延时要求比较严格,应根据单片机时钟调整延时函数
//       
//pic16f877a   4MHz   PICC9.8编译器
//*******************************************************************


#define	DQ_DIR  TRISB5     //控制DS18B20的DQ端
#define	DQ      RB5        //控制DS18B20的DQ端


//ds18b20 ROM操作指令码
#define ds18b20_skip_rom     0xCC    //跳过ROM指令码
#define ds18b20_search_rom   0xF0    //搜索ROM指令码
#define ds18b20_read_rom     0x33    //读ROM指令码
#define ds18b20_match_rom    0x55    //匹配ROM指令码
#define ds18b20_alarm_rom    0xEC    //报警搜索ROM指令码
//ds18b20 RAM操作指令码
#define ds18b20_convert_ram   0x44   //启动温度转换指令码
#define ds18b20_read_ram      0xBE   //读RAM指令码    
#define ds18b20_write_ram     0x4E   //写RAM指令码     
#define ds18b20_copy_ram      0x48   //把RAM的TH,TL,CFG中的内容复制到EEPROM指令码
#define ds18b20_recall_eeprom 0xB8   //把EEPROM的TH,TL,CFG中的内容恢复到RAM指令码


//*************** 函数定义 ******************
uchar ds18b20_init(void);                 //初始化函数
uchar ds18b20_read(void);                 //读一个字节 
void  ds18b20_write(uchar ds18b20_dat);            //写一个字节


//*************************初始化函数************************
uchar ds18b20_init(void)     
{
   
  uchar b=0;
  DQ=0;
  DQ_DIR=0;           //单片机将DQ拉低
  __delay_us(495);    //精确延时495us  大于480us
  DQ_DIR=1;           //拉高总线
  __delay_us(80);     //延时80us       大于60us
  b=DQ;               //读端口如果x=0则初始化成功 x=1则初始化失败
  __delay_us(495);    //精确延时495us  大于480us
  return b;
}


//***************************读一个字节**********************
uchar ds18b20_read(void)
{
   
  uchar c;
  uchar ds18b20_dat=0;   //ds18b20_dat用于存储读到的数据,先清零
  for(c=8;c>0;c--)
  {
   
    DQ=0;
    DQ_DIR=0;          //拉低总线         
    __delay_us(2);     //延时1us以上   
    DQ_DIR=1;          //拉高总线
    __delay_us(2);     //延时1us以上
                       //在15us以内读数据
    ds18b20_dat>>=1;           //数据右移,读顺序(先低后高)
    if(DQ)
    {
   
      ds18b20_dat|=0x80;
    }
    __delay_us(65);    //保持60us以上
  }
  return(ds18b20_dat);
}


//***************************写一个字节********************
void ds18b20_write(uchar ds18b20_dat)
{
   
  uchar d;
  for(d=8;d>0;d--)        //写8次,一次写1位,先写低字节
  {
   
    DQ=0;              
    DQ_DIR=0;             //拉低数据线
    __delay_us(2);        //延时1us以上
    DQ=ds18b20_dat&0x01;          //写数据
    __delay_us(65);       //保持60us以上
    ds18b20_dat>>=1;              //数据右移1位,先写低位
    DQ_DIR=1;             //拉高数据线
    __delay_us(2);        //延时1us以上
                          //两次写之间保持1us以上   
  }
}

  1. DS1302功能实现C文件
#include "lian_pic.h"
#include "DS1302.H"

//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar READ_RTC_ADDR[7]={
   0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; 
uchar WRITE_RTC_ADDR[7]={
   0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};

//---DS1302时钟初始化2019年12月20日星期五18点58分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7]={
   0x00,0x58,0x18,0x20,0x12,0x05,0x19};

//*********************DS1302WRITE************************
void ds1302_write(uchar addr,uchar dat)
{
   
	TRISC=0X00;
	uchar f;
	RST=0;
	NOP();
	
	SCLK=0;			//先将SCLK置低电平
	NOP();
	RST=1;			//然后将RST(CE)置高电平
	NOP();
	
	for(f=0;f<8;f++)		//开始传送八位地址命令
	{
   
		DSIO=addr&0x01;		//数据从低位开始传送
		addr>>=1;
		SCLK=1;				//数据在上升沿时,DS1302读取数据
		NOP();
		SCLK=0;
		NOP();
	}
	for(f=0;f<8;f++)		//开始写入八位数据
	{
   
		DSIO=dat&0x01;		//数据从低位开始传送
		dat>>=1;
		SCLK=1;				//数据在上升沿时,DS1302读取数据
		NOP();
		SCLK=0;
		NOP();
	}
	
	RST=0;					//传送数据结束
	NOP();
	
}

//******************DS1302READ**********************
uchar ds1302_read(uchar addr)
{
   
	uchar j,dat,dat1;
	RST=0;
	NOP();
	
	SCLK=0;		//先将SCLK置低电平
	NOP();
	RST=1;		//然后将RST(CE)置高电平
	NOP();
	
	for(j=0;j<8;j++)		//开始传送八位地址命令
	{
   
		TRISC1=0;
		NOP();
		DSIO=addr&0x01;		//数据从低位开始传送
		addr>>=1;
		SCLK=1;				//DS1302上升沿时,读取数据
		NOP();
		SCLK=0;				//DS1302下降沿时,放置数据
		NOP();
		
	}
	NOP();
	for(j=0;j<8;j++)		//读取8位数据
	{
   	
		TRISC1=1;
		NOP();
		dat1=DSIO;			//从最低位开始接收
		dat=(dat>>1)|(dat1<<7);
		SCLK=1;
		NOP();
		SCLK=0;				//DS1302下降沿时,放置数据
		NOP();	
	}	
	RST=0;
	NOP();					//以下为DS1302复位的稳定时间,必须的。
	SCLK=1;
	NOP();
	DSIO=0;
	NOP();
	DSIO=1;
	NOP();
	return dat;
	
}

//******************DS1302INIT**********************
void ds1302_init()
{
   
	uchar k;
	ds1302_write(0x8e,0x00
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值