赞
踩
原标题:基于AVR单片机的DS1302数码管时间显示C语言程序设计
#include
#include
#define uchar unsigned char
#define uint unsigned int
#include " _drive.h"
uchar K1_FLAG=0; //定义按键标志位,当按下K1键时,该位置1,K1键未按下时,该位为0。
uchar const bit_tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选表,用来选择哪一只 进行显示
uchar const seg_data[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xbf};
//0~F、熄灭符和字符"-"的显示码(字形码) //0~F、熄灭符和字符"-"的显示码(字形码)
#define beep_0 (PORTD=PORTD&0x7f) //PD7上的蜂鸣器发声
#define beep_1 (PORTD=PORTD|0x80) //PD7上的蜂鸣器不发声
uchar disp_buf[8] ={0x00}; //定义显示缓冲区
uchar time_buf[7] ={0,0,0x12,0,0,0,0}; //DS1302时间缓冲区,存放秒、分、时、日、月、星期、年
uchar temp [2]={0}; //用来存放设置时的小时、分钟的中间值
/********函数功能:延时函数********/
void Delay_ms(uint xms)
{
int i,j;
for(i=0;i
{ for(j=0;j<1140;j++) ; }
}
/*********以下是蜂鸣器响一声函数********/
void beep()
{
beep_0; //蜂鸣器响
Delay_ms(100);
beep_1; //关闭蜂鸣器
Delay_ms(100);
}
/********端口设置函数********/
void port_init(void)
{
PORTA = 0xFF; //输出高电平
DDRA = 0xFF; //设为输出
PORTC = 0xff; //输出高电平
DDRC = 0xFF; //设为输出
DDRD =(0<
PORTD = 0xFF; //PD7输出高电平,其它为带上拉的输入
}
/********以下是走时转换函数,负责将走时数据转换为适合数码管显示的数据********/
void conv(uchar in1,uchar in2,uchar in3) //形参in1、in2、in3接收实参time_buf[2]、time_buf[1]、time_buf[0]传来的时/分/秒数据
{
disp_buf[0] =in1/10; // 小时十位
disp_buf[1] = in1%10; // 小时个位
disp_buf[3] = in2/10; // 分钟十位
disp_buf[4] = in2%10; // 分钟个位
disp_buf[6] = in3/10; // 秒十位
disp_buf[7] = in3%10; // 秒个位
disp_buf[2] = 17; // 第3只数码管显示"-"(在 seg_data表的第17位)
disp_buf[5] = 17; // 第6只数码管显示"-"
}
/********以下是显示函数********/
void Display()
{
uchar tmp; //定义显示暂存
static uchar disp_sel=0; //显示位选计数器,显示程序通过它得知现正显示哪个数码管,初始值为0
tmp=bit_tab[disp_sel]; //根据当前的位选计数值决定显示哪只数码管
PORTC=tmp; //送P2控制被选取的数码管点亮
tmp=disp_buf[disp_sel]; //根据当前的位选计数值查的数字的显示码
tmp=seg_data[tmp]; //取显示码
PORTA=tmp; //送到P0口显示出相应的数字
disp_sel++; //位选计数值加1,指向下一个数码管
if(disp_sel==8)
disp_sel=0; //如果8个数码管显示了一遍,则让其回0,重新再扫描
}
/********以下是定时器T0中断函数, 用于数码管的动态扫描********/
#pragma _handler timer0_ovf:10
void timer0_ovf(void)
{
TIFR=0x01; //写1清除定时器T0标志位
TCNT0=240; //置计数初值,设置定时时间为2ms
Display(); //调显示函数
}
/********以下是按键处理函数********/
void KeyProcess()
{
uchar min16,hour16; //定义16进制的分钟和小时变量
write_ (0x8e,0x00); //DS1302写保护控制字,允许写
write_ds1302(0x80,0x80); //时钟停止运行
if((PIND&0x3C)!=0x3C) //如果K1~K4键有一个被按下
Delay_ms(10); //延时10ms
if((PIND&0x3C)!=0x3C) //如果仍被按下,说明不 引起
{
if((PIND&0x08)==0) //K2键用来对小时进行加1调整
{
while(!(PIND&0x08)); //等待K2键释放
beep();
time_buf[2]=time_buf[2]+1; //小时加1
if(time_buf[2]==24) time_buf[2]=0; //当变成24时初始化为0
hour16=time_buf[2]/10*16+time_buf[2]%10; //将所得的小时数据转变成16进制数据
write_ds1302(0x84,hour16); //将调整后的小时数据写入DS1302
}
if((PIND&0x10)==0) // K3键用来对分钟进行加1调整
{
while(!(PIND&0x10)); //等待K3键释放
beep();
time_buf[1]=time_buf[1]+1; //分钟加1
if(time_buf[1]==60) time_buf[1]=0; //当分钟加到60时初始化为0
min16=time_buf[1]/10*16+time_buf[1]%10; //将所得的分钟数据转变成16进制数据
write_ds1302(0x82,min16); //将调整后的分钟数据写入DS1302
}
if((PIND&0x20)==0) //K4键是确认键
{
while(!(PIND&0x20)); //等待K4键释放
beep();
write_ds1302(0x80,0x00); //调整完毕后,启动时钟运行
write_ds1302(0x8e,0x80); //写保护控制字,禁止写
K1_FLAG=0; //将K1键按下标志位清0
}
}
}
/********以下是读取时间函数,负责读取当前的时间,并将读取到的时间转换为10进制数********/
void get_time()
{
uchar sec,min,hour; //定义秒、分和小时变量
write_ds1302(0x8e,0x00); //控制命令,WP=0,允许写操作
write_ds1302(0x90,0xab); //涓流充电控制
sec=read_ds1302(0x81); //读取秒
min=read_ds1302(0x83); //读取分
hour=read_ds1302(0x85); //读取时
time_buf[0]=sec/16*10+sec%16; //将读取到的16进制数转化为10进制
time_buf[1]=min/16*10+min%16; //将读取到的16进制数转化为10进制
time_buf[2]=hour/16*10+hour%16; //将读取到的16进制数转化为10进制
}
/********定时器0初始化********/
void timer0_init()
{
SREG = 0x80; //使能全局中断
TIMSK|=(1<
TCCR0|=(1<
TCNT0 = 240; //定时初值设置,定时时间2ms
}
/********以下是主函数********/
void main(void)
{
port_init();
timer0_init(); //调定时器T0、T1初始化函数
init_ds1302(); //DS1302初始化
while(1)
{
get_time(); //读取当前时间
if((PIND&0x04)==0) //若K1键按下
{
Delay_ms(10); //延时10ms去抖
if((PIND&0x04)==0)
{
while(!(PIND&0x04)); //等待K1键释放
beep(); //蜂鸣器响一声
K1_FLAG=1; //K1键标志位置1,以便进行时钟调整
}
}
if(K1_FLAG==1)KeyProcess(); //若K1_FLAG为1,则进行走时调整
conv(time_buf[2],time_buf[1],time_buf[0]); //将DS1302的小时/分/秒传送到转换函数
}
}
责任编辑:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。