200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 1302数码管c语言程序 基于AVR单片机的DS1302数码管时间显示C语言程序设计

1302数码管c语言程序 基于AVR单片机的DS1302数码管时间显示C语言程序设计

时间:2021-06-10 05:58:59

相关推荐

1302数码管c语言程序 基于AVR单片机的DS1302数码管时间显示C语言程序设计

#include #include #defineucharunsigned char

#defineuintunsignedint

#include "DS1302_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时间缓冲区,存放秒、分、时、日、月、星期、年

uchartemp [2]={0}; //用来存放设置时的小时、分钟的中间值

/********函数功能:延时函数********/

void Delay_ms(uint xms)

{

int i,j;

for(i=0;i

{ for(j=0;j<1140;j++) ; }

}

/*********以下是蜂鸣器响一声函数********/

voidbeep()

{

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 interrupt_handler timer0_ovf:10

void timer0_ovf(void)

{

TIFR=0x01; //写1清除定时器T0标志位

TCNT0=240; //置计数初值,设置定时时间为2ms

Display(); //调显示函数

}

/********以下是按键处理函数********/

void KeyProcess()

{

uchar min16,hour16; //定义16进制的分钟和小时变量

write_ds1302(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的小时/分/秒传送到转换函数

}

}

关注eeworld公众号

快捷获取更多信息

关注eeworld服务号

享受更多官方福利

推荐阅读

AVR单片机需要设置合适的熔丝位才能实现其功能,如果熔丝位设置的不对将有可能导致单片机自锁,这是我整理的AVR单片机熔丝位的设置及拯救方,希望对大家有帮助。

发表于 -09-17

单片机源程序如下:/***版权所有(c),艁ukasz Marcin Podkalicki*12月13日*简单定时器(启动/复位/停止),使用基于TM1637的一个按钮和7段显示模块。 **注意,这个ATtiny13项目使用的内部时钟并不精确&nbsp

发表于 -09-16

为0到9,分别表示LED的占空比为0/9到9/9。比如,当占空比为4/9时,在9毫秒的周期中,前4毫秒LED亮,后5毫秒LED不亮。可以看见,占空比越大,LED亮度也越高。原来,在亮与暗之间,LED还有中间的状态。我们不是通过让引脚输出一个0V和5V之间的电压,而是让引脚电平迅速地在高低之间变化来实现的。这种通过电平的快速跳变来实现模拟量效果的技术,称为脉冲宽度调制,简称PWM。定时器大多数单片机的定时器都可以输出PWM波,外设丰富的AVR单片机自然不例外。上一讲提到定时器0有四种工作模式,后两种就是快速PWM模式与相位修正PWM模式。在快速PWM模式中,TCNT0寄存器的动作与普通模式相同,但还可以把OCR0A作为上限。对于非反转输出

发表于 -09-09

7)接到一个单片机引脚上。关于为什么会有这种诡异的接法,这是设计时的失误(也可能是不得已吧,毕竟单片机的32个IO已经占满了),参见:一个低电平引发的思考。协议1602与单片机之间是通过并行总线通信的。AVR单片机硬件上不支持并行总线,需要通过软件模拟时序来实现。写操作的时序如下:进行一个写操作,需要先让RS根据写的类型设置电平,R/W输出低电平,D0~D7输出要发送的数据,然后在E的上升沿数据被对方读取,并保持R/W与D0~D7电平不变,直到E的下降沿之后。两次E的上升沿之间至少需要400us时间间隔。1602共有8条指令,都是一字节长度的。从高位到低位,每一条指令都由若干个0、一个1和有效指令组成,使得没有两条指令会有相同的二进制

发表于 -09-09

在第一期中,我们已经开始使用UART来实现单片机开发板与计算机之间的通信,但只是简单地讲了讲一些概念和库函数的使用。在这一篇教程中,我们将从硬件与软件等各方面更深入地了解UART。USART组件一直在讲的UART其实是USART组件的一部分,USART比UART多了同步的一部分,但这一部分用得太少(我从来没用过),而且缺乏实例,所以就略过了。然而,单片机的设计者很机智地把这个鸡肋功能升华了一下,USART组件可以支持SPI模式。SPI是一种同步串行总线,可以支持很高的传输速率。这个功能使得ATmega324PA支持最多3个SPI通道,其中一个是纯SPI,另两个就是SPI模式下的USART。我们将在下一讲中揭开SPI的神秘面纱。回到

发表于 -09-08

开发板上有4个按键,我们可以把每一个按键连接到一个单片机引脚上,来实现按键状态的检测。但是常见的键盘有104键,是每一个键分别连接到一个引脚上的吗?我没有考证过,但我们确实有节省引脚的方法。矩阵键盘这是一个4*4的矩阵键盘,共有16个按键只需要8个引脚就可以驱动。我们先来看看它的原理。每个按键有两个引脚,当按键按下时接通。每一行的一个引脚接在一起,分别连接到左边4个端口,称为“行引脚”;每一列的另一个引脚接在一起,分别连接到右边的4个端口,称为“列引脚”。这就是矩阵键盘内部的电路连接方式。那么如何驱动它呢?首先我们简化一下,只考虑第一排:这样就很简单了吧,只要让行引脚保持低电平,4个列引脚设置为输入并开启上拉电阻,读到低电平

发表于 -09-08

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。