单片机时钟程序:通过键设计当前时间,设定闹钟,时间一到,报警

单片机时钟程序:通过键设计当前时间,设定闹钟,时间一到,报警,第1张

这是我以前写的一段程序,希望对你能有帮助
我的程序,首先有一点,肯定是调试通过的,不像我以前找的一些网络程序,貌似可以,就是不能执行结果。
/DS1302时钟芯片显示设置
功能:显示 时间 日期 星期
引脚说明:DS1302三引脚 CLK = P1^5; IO=P1^6; RST=P1^7;
设计整理:创达科技 陈仲库
技术服务:kuzi00@163com QQ:86828048
整理时间:2007年5月26日
/
#define uchar unsigned char
#define uint unsigned int
sbit DS1302_CLK = P1^5; //实时时钟时钟线引脚
sbit DS1302_IO = P1^6; //实时时钟数据线引脚
sbit DS1302_RST = P1^7; //实时时钟复位线引脚
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
typedef struct __SYSTEMTIME__
{
uchar Second;
uchar Minute;
uchar Hour;
uchar Week;
uchar Day;
uchar Month;
uchar Year;
uchar DateString[9];
uchar TimeString[9];
}SYSTEMTIME; //定义的时间类型
void DS1302_WR_Byte(uchar d) //实时时钟写入一字节(内部函数)
{
uchar i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相当于汇编中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}
uchar DS1302_RD_Byte(void) //实时时钟读取一字节(内部函数)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}
void DS1302_Write(uchar ucAddr, uchar ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302_WR_Byte(ucAddr); // 地址,命令
DS1302_WR_Byte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}
uchar DS1302_Read(uchar ucAddr) //读取DS1302某地址的数据
{
uchar ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302_WR_Byte(ucAddr|0x01); // 地址,命令
ucData = DS1302_RD_Byte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}
void DS1302_SetTime(uchar Address, uchar Value) // 设置时间函数
{
DS1302_Write(0x8E,0x00); //写保护
DS1302_Write(Address, ((Value/10)<<4 | (Value%10)));
}
void DS1302_GetTime(SYSTEMTIME Time)
{
uchar ReadValue;
ReadValue = DS1302_Read(0x80);
Time->Second = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);
ReadValue = DS1302_Read(0x82);
Time->Minute = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);
ReadValue = DS1302_Read(0x84);
Time->Hour = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);
ReadValue = DS1302_Read(0x86);
Time->Day = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);
ReadValue = DS1302_Read(0x8a);
Time->Week = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);
ReadValue = DS1302_Read(0x88);
Time->Month = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);
ReadValue = DS1302_Read(0x8c);
Time->Year = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);
}
void DateToStr(SYSTEMTIME Time)
{
Time->DateString[0] = Time->Year/10 + '0';
Time->DateString[1] = Time->Year%10 + '0';
Time->DateString[2] = '-';
Time->DateString[3] = Time->Month/10 + '0';
Time->DateString[4] = Time->Month%10 + '0';
Time->DateString[5] = '-';
Time->DateString[6] = Time->Day/10 + '0';
Time->DateString[7] = Time->Day%10 + '0';
Time->DateString[8] = '\0';
}
void TimeToStr(SYSTEMTIME Time)
{
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
Time->TimeString[2] = ':';
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
Time->TimeString[5] = ':';
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
Time->DateString[8] = '\0';
}
void DS1302_Init(void)
{
uchar Second=DS1302_Read(0x80);
if(Second&0x80) DS1302_SetTime(0x80,0);
//时间设置初始化 秒 分 时
DS1302_SetTime(0x80,30);
DS1302_SetTime(0x82,59);
DS1302_SetTime(0x84,23);
DS1302_SetTime(0x8A,6); //周
DS1302_SetTime(0x86,26); //天
DS1302_SetTime(0x88,5); //月
DS1302_SetTime(0x8C,7); //年
}
/调用说明
DS1302_Init();初始化
DS1302_GetTime(&CurrentTime);//取得当前时间
DateToStr(&CurrentTime); //取得当前日期
TimeToStr(&CurrentTime); //取得当前时间
// 数据处理 CurrentTimeDateString 格式"07-05-26"
// CurrentTimeTimeString 格式"00;00;00"
/

主程序:
push ds ;保存数据段
mov ax,0000
mov ds,ax ;数据段清零
mov ax,offset irq7 ;取中断程序入口地址
add ax,2000 ;加装时IP=2000地址
mov si,003c ;填8259中断7中断矢量
mov w[si],ax ;填偏移量矢量
mov ax,0000 ;段地址CS=0000H
mov si,003e
mov w[si],ax ;填段地址矢量
pop ds ;d栈
in al,21 ;读8259中断屏蔽字
and al,7f ;开8259中断7
out 21,al
mov al,b4 ;8253的计数器2为方式2,采用二进制计数,先低后高写入计数值 10110100
out 43,al ;写入方式控制字
mov ax,2e9c 0010 1110 1001 1100B 11932D
out 42,al ;写入低字节计数值 1001 1100
mov al,ah
out 42,al ;写入高字节计数值 0010 1110
mov al,81 ;8255的A口为方式0输出,B口为方式0输出,C口下部输入 1000 0001
out 63,al ;写方式控制字
call first ;调用first子程序,赋计数初值
begi:hlt 延时等待
sti ;开中断
mov ah,01
int 16 ;检测是否按了键盘
jz begi
mov ah,00 ;读键值
int 16
cmp al,0d ;是否按了回车
jnz A1
mov si,4000
not [si+04] ;偏移地址为4004的内存单元内容取反
jmp begi
A1:cmp al,1b ;是否按了ESC键
jnz A2
call first ;重新赋初值,相当于清零
A2:jmp begi
中断程序:
irq7:call disp ;调用disp子程序,用来在数码管显示数据
mov si,4000
cmp [si+04],00 ;判断是否按了第2次回车键
je A4
call addn ;调用addn子程序,用来计数
A4:mov al,20
out 20,al
cli ;关中断
iret ;返回
addn程序:
addn:mov si,4000
add [si+03],01 ;百分之一秒加1
cmp [si+03],0a ;判断是否大于10
jz A5
jmp A9
A5:mov [si+03],00
Add [si+02],01 ;十分之一秒加1
cmp [si+02],0a ;判断是否大于10
jz A6
jmp A9
A6:mov [si+02],00
add [si+01],01 ;秒位加1
cmp [si+01],0a ;判断是否大于10
jz A7
jmp A9
A7:mov [si+01],00
add [si],01 ;十秒位加1
cmp [si],06 ;判断是否大于6
jz A8
jmp A9
A8:mov [si],00 ;大于60:00重新开始
A9: ret
赋初值程序:
first:mov si,4000
mov al,00
mov [si],al
mov [si+01],al
mov [si+02],al
mov [si+03],al
mov [si+04],al
ret
显示程序:
disp:push ax ;保存AX
mov si,4000 ;指向数据缓冲区
mov dl,f7 ;1111 0111 指向数码管
mov al,dl ;al=1111 0111
again:out 60,al ;写端口A
mov al,[si]
mov bx,4100 ;指向数码缓冲区 bx=0100 0001 0000 0000
and ax,00ff ; ax=0000 0000 al
add bx,ax ;得到显示代码 bx=0100 0001 al
mov al,[bx]
out 61,al ;写端口B
call dally :调用延时程序dally
inc si
mov al,dl
test al,01
jz out
ror al,1 ;指向下一个数码管
mov dl,al
jmp again
out: pop ax ;d出AX
ret
dally:push cx ;延时程序
push ax
mov cx,0010
t1 :mov ax,0010
t2 dec ax
jnz t2
loop t1
pop ax
pop cx
ret
数码缓冲区:
0000:4000 3f,06,5b4f,66,6d,7d,07,7f,6f
二、 设计思想
电子秒表要实现的功能:用键盘中断来控制整个程序,按一下回车键启动电子秒表,再按一下暂停,按一下ESC键清零,用七段数码管显示时间。整个程序涉及到8255、8253与8259三个芯片。8253的OUT2,CLK2分别连接8259的IRQ7与PCLK,8253的GATE2连接正5伏电压,采用计数器2每隔001秒产生一次中断并且计数,写入以偏移地址4000H开始的4个内存单元,然后利用8255将内存单元的数据输出到七段数码管。由于键盘中断优先于8259的7号中断,所以程序只有在按一下回车键才启动电子秒表,再按一下暂停,按一下ESC键清零,如果超出了60秒,整个程序自动重新开始。
三、 所用芯片工作原理
8255:接口电路在CPU和I/O设备之间起着信号的变换和传输的作用。 任何接口电路与CPU之间的信息传输方式都是并行的,即CPU与接口电路之间以数据字节/字为单位传送信息。接口电路与I/O设备之间的信息传送方式,有并行和串行两种,相应的接口电路称为并行接口和串行接口。
并行接口是在多根数据线上,以数据字节/字与I/O设备交换信息。在输入过程中,输入设备把数据送给接口,并且使状态线“输入准备好”有效。接口把数据存放在“输入缓冲寄存器”中,同时使“输入回答”线有效,作为对外设的响应。外设在收到这个回答信号后,就撤消数据和“输入准备好”信号。数据到达接口中后,接口会在“状态寄存器”中设置输入准备好标志,或者向CPU发一个中断请求。CPU可用查询方式或中断方式从接口中读取数据。接口中的数据被读取后,接口会自动清除状态寄存器中的标志,且撤消对CPU的中断请求。
在输出过程中,每当输出寄存器可以接收数据,接口就会将状态寄存器中“输出准备好”状态置1或向CPU发一个中断请求,CPU可用查询或中断方式向接口输出数据。当CPU输出的数据到达接口后,接口会清除“输出准备好”状态,把数据送往外设,并向外设发一个“数据输出准备好”信号。外设受到驱动后,便接收数据,并向接口电路发一个“输出回答”信号,接口收到该回答信号后,又将状态寄存器中“输出准备好”置位,以便CPU输出下一个数据。
8253:对CLK信号进行“减1计数”。首先CPU把“控制字”,写入“控制寄存器”,把“计数初始值”写入“初值寄存器”,然后, 定时/计数器按控制字要求计数。计数从“计数初始值 开始,每当CLK信号出现一次,计数值减1,当计数值减为0时,从OUT端输出规定的信号(具体形式与工作模式有关)。当CLK信号出现时,计数值是否减1(即是否计数),受到“门控信号”GATE的影响,一般,仅当GATE有效时,才减1门控信号GATE如何影响计数 *** 作,以及输出端OUT在各种情况下输出的信号形式与定时/计数器的工作模式有关。
8259:1 IR线上提出了中断请求的中断源,即出现请求,IRR中断请求寄存器(共有8位D7~D0)对应于连接在IR0~IR7线上的外设的中断请求,哪一根输入线有请求,哪一根输入线就置1。
2 若OCW1(IMR中断屏蔽寄存器)未使该中断请求屏蔽(对应位为0时不屏蔽),该请求被送入PR(优先权分析器)比较。否则,不送入PR比较。
3 PR把新进入的请求与ISR(服务中寄存器)中正在被处理的中断进行比较。如果新进入的请求优先级较低,则8259不向CPU提出请求。如果新进入的请求优先级较高,则8259使INT引脚输出高电平,向CPU提出请求。
4 如果CPU内部的标志寄存器中的IF(中断允许标志)为0,CPU不响应该请求。若IF=1,CPU在执行完当前指令后,从CPU的INTA引脚上向8259发出两个负脉冲。
5第一个 INTA负脉冲到达8259时,8259完成以下三项工作:
a使IRR(中断请求寄存器)的锁存功能失效。这样一来,在IR7~IR0上的请求信号就不会被8259接收。直到第二个INTA负脉冲到达8259时,才又使IRR的锁存功能有效。
b使ISR(服务中寄存器)中的相应位置1。
c使IRR中的相应位清0。
6第二个INTA负脉冲到达8259时,8259完成以下工作:
a将中断类型码(ICW2中的值)送到数据总线上,CPU将其保存在“内部暂存器”中。
b如果ICW4(它设定级中断联方式之特定完全嵌套方式,将在8259的工作方式中详述ICW4)中设置了中断自动结束方式,则将ISR的相应位清0。

换一个吧
电子密码锁
摘要本文的电子密码锁利用数字逻辑电路,实现对门的电子控制,并且有各种附加电路保证电路能够安全工作,具有极高的安全系数。
关键词电子密码锁、电压比较器、555单稳态电路、计数器、JK触发器、UPS电源。
一、引言
随着人们生活水平的提高,如何实现家庭防盗这一问题也变的尤其的突出,传统的机械锁由于其构造的简单,被撬的事件屡见不鲜,电子锁由于其保密性高,使用灵活性好,安全系数高,受到了广大用户的亲呢。
设计本课题时构思了两种方案:一种是用以AT89C2051为核心的单片机控制方案;另一种是用以74LS112双JK触发器构成的数字逻辑电路控制方案。考虑到单片机方案原理复杂,而且调试较为繁琐,所以本文采用后一种方案。
二、总体方案设计
1、设计思路
共设了9个用户输入键,其中只有4个是有效的密码按键,其它的都是干扰按键,若按下干扰键,键盘输入电路自动清零,原先输入的密码无效,需要重新输入;如果用户输入密码的时间超过40秒(一般情况下,用户不会超过40秒,若用户觉得不便,还可以修改)电路将报警80秒,若电路连续报警三次,电路将锁定键盘5分钟,防止他人的非法 *** 作。
2、总体方框图
三、设计原理分析
电路由两大部分组成:密码锁电路和备用电源(UPS),其中设置UPS电源是为了防止因为停电
造成的密码锁电路失效,使用户免遭麻烦。
密码锁电路包含:键盘输入、密码修改、密码检测、开锁电路、执行电路、报警电路、键盘输
次数锁定电路。
1、键盘输入、密码修改、密码检测、开锁及执行电路
其电路如下图3-1-1所示:

图3-1-1 键盘输入、密码修改、密码检测、开锁、执行电路
开关K1~K9是用户的输入密码的键盘,用户可以通过开关输入密码,开关两端的电容是为了提高开关速度,电路先自动将IC1~IC4清零,由报警电路送来的清零信号经C25送到T11基极,使T11导通,其集电极输出低电平,送往IC1~IC4,实现清零。
密码修改电路由双刀双掷开关S1~S4组成(如图3-1-2所示), 它是利用开关切换的原理实现密码的修改。例如要设定密码为1458,可以拨动开关S1向左,S2向右,S3向左,S4向右,即可实现密码的修改,由于输入的密码要经过S1~S4的选择,也就实现了密码的校验。本电路有16组的密码可供修改。
图3-1-2 密码修改电路
由两块74LS112(双JK触发器,包含IC1~IC4)组成密码检测电路。由于IC1处于计数状态,当用户按下第一个正确的密码后,CLK端出现了一个负的下降沿,IC1计数,Q端输出为高电平,用户依次按下有效的密码,IC2~IC3也依次输出高电平,送入与门IC5,使其输出开锁的高电平信号送往IC13的2脚,执行电路动作,实现开锁。
执行电路是由一块555单稳态电路(IC13),以及由T10、 T11组成的达林顿管构成。若IC13的2脚输入一高电平,则3脚输出高电平,使T10导通,T11导通,电磁阀开启,实现开门,同时T10集电极上接的D5(绿色发光二极管)发亮,表示开门,20秒后,555电路状态翻转,电磁阀停止工作,以节电。其中电磁阀并联的电容C24使为了提高电磁阀的力矩。
2、 报警电路
报警电路实现的功能是:当输入密码的时间超过40秒(一般情况下用户输入不会超过),电路报警80秒,防止他人恶意开锁。
电路包含两大部分,2分钟延时和40秒延时电路。其工作原理是当用户开始输入密码时,电路开始2分钟计时,超出40秒,电路开始80秒的报警。图如下3-2-1所示

图3-2-1 报警电路
有人走近门时,触摸了TP端(TP端固定在键盘上,其灵敏度非常高,保证电路可靠的触发),由于人体自身带的电,使IC10的2脚出现低电平,使IC10的状态发生翻转,其3脚输出高电平,T5导通(可以通过R12控制T1的基极电流),其集电极接的发光二极管D3发光,表示现在电子锁处于待命状态,T6截止,C4开始通过R14充电(充电时间是40秒,此时为用户输入密码的时间,即用户输入密码的时间不能超过40秒,否则电路就开始报警, 由于用户经常输入密码,而且知道密码,一般输入密码的时间不会超过40秒),IC2开始进入延时40秒的状态。
开始报警:当用户输入的密码不正确或输入密码的时间超过40秒,IC11的2脚电位随着C4的充电而下降,当电位下降到1/3Vcc时(即40秒延时结束时候),3脚变成高电位(延时时是低电平),通过R15使(R15的作用是为了限制T7的导通电流防止电流过大烧毁三极管)T7导通,其集电极上面接的红色发光二极管D4发亮,表示当前处于报警状态,T8也随之而导通,使蜂鸣器发声,令贼人生怯,实现报警
停止报警:当达到了80秒的报警时间,IC10的6,7脚接的电容C5放电结束,IC10的3脚变成低电平,T5截止,T6导通,强制使强制电路处于稳态,IC11的3脚输出低电平,使T7,T8截止,蜂鸣器停止报警;或者用户输入的密码正确,则有开锁电路中的T10集电极输出清除报警信号,送至T12(PNP),T12导通,强制使T7基极至低电位,解除报警信号。
3、报警次数检测及锁定电路
若用户 *** 作连续失误超过3次,电路将锁定5分钟。其工作原理如下:当电路报警的次数超过3次,由IC9(74161)构成的3位计数器将产生进位,通过IC7,输出清零信号送往74161的清零端,以实现重新计数。经过IC8(与门),送到IC12(555)的2脚,使3脚产生5分钟的高电平锁定脉冲(其脉冲可由公式T=11RC计算得出),经T9倒相,送IC6输入端,使IC6输出低电平,使IC13不能开锁,到锁定的目的。电路图如下3-3-1所示:
图3-3-1报警次数检测及锁定电路
4、备用电源电路
为了防止停电情况的发生,本电路后备了UPS电源,它包括市电供电电路,停电检测电路,电子开关切换电路,蓄电池充电电路和蓄电池组成。其电路图如下3-4-1所示:
220V市电通过变压器B降压成12V的交流电,再经过整流桥整流,7805稳压到5V送往电子切换电路,由于本电路功耗较少,所以选用10W的小型变压器。

图3-4-1 电源电路
由R8,R9,R6,R7及IC14构成电压比较器,正常情况下,V+<V- IC14输出高电平,继电器的常闭触点和市电相连;当市电断开,V+>V- IC14输出高电平,由T3,T4构成的达林顿管使继电器J开启,将其常开触电将蓄电池和电路相连,实现市电和蓄电池供电的切换,保证电子密码锁的正常工作(视电池容量而定持续时间)。其电路图如下3-4-2所示:
图3-4-2停电检测及电子开关切换电路
T1,T2构成的蓄电池自动充电电路,它在电池充满后自动停止充电,其中D1亮为正在充电,D2为工作指示。由R4,R5,T1构成电压检测电路,蓄电池电压低,则T1,T2导通,实现对其充电;充满后,T1,T2截止,停止充电,同时D1熄灭,电路中C4的作用是滤除干扰信号。其电路图如3-4-3所示:

图3-4-3 蓄电池自动充电电路
五、总结与体会

以上为实习期间所设计的电子密码锁电路,它经过多次修改和整理,以是一个比较不错的设计,可以满足人们的基本要求,但因为水平有限,此电路中也存在一定的问题,譬如说电路的密码不能遗忘,一旦遗忘,就很难打开,这可以通过增加电路解决,但过于复杂,本次设计未其中;用开关作74LS112的CLK脉冲,不是很稳定,可以调换其它高速开关或计数脉冲;电路密码只有16种可供修改,但由于他人不知道密码的位数,而且还要求在规定的时间内按一定的顺序开锁,所以他人开锁的几率很小;电路中未加显示电路,但可通过其它数字模块实现这一功能。这需要一段时间的进一步改进,如果有好的意见,希望老师给以支持。
通过这三周的学习,我感觉有很大的收获:首先,通过学习使自己对课本上的知识可以应用于实际,使的理论与实际相结合,加深自己对课本知识的更好理解,同时实习也段练了我个人的动手能力:能够充分利用图书馆去查阅资料,增加了许多课本以外的知识。能对protel 99、和EWB等仿真软件 *** 作,能达到学以致用。对我们学生来说,理论与实际同样重要,这是我们以后在工作中说明自己能力的一个重要标准。
在实习中,我感受到了老师对学生的那种悔人不卷的精神,每天的固定时间,老师都来给我们指导,使我们少走弯路,顺利完成实习任务,请允许我向你们致意崇高的敬意,感谢你们,老师!

参考文献
[1] 康华光电子技术基础(第四版)北京:高等教育出版社,1998
[2] 《无线电》第2002年合订本。

哈哈 有个1602显示的 不过程序太长 贴不上 给你个数码管的吧 不行再联系

1302c

#include<DS1302h>

#include<keyh>

uchar bit_ser[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};

uchar seven_seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

/时间显示/

void timer0_init(void)  //T0初始化函数,用于时间的动态显示

{

TMOD = 0x21;

TL0 = (65536-5000) % 256;

TH0 = (65536-5000) / 256;

EA = 1;

ET0 = 1;

TR0 = 1;

}

void timer0_isr(void) interrupt 1  //T0中断处理函数

{

char flag;   //flag用于表示调整时闪烁的亮或灭

TR0 = 0;

TL0 = (65536-5000) % 256;

TH0 = (65536-5000) / 256;

TR0 = 1;

flag = x / 100  0xff; //设置闪烁标志,如果x大于100则flag为0xff,小于100则为0x00

x++;

if(x > 200)

x = 0;

switch(i)

{

case 0:

P2 = bit_ser[0];

if(setflag == 3)  //根据setflag的值判断当前位是否需要闪烁

P0 = flag | seven_seg[dis_buffer[0]];

else

P0 = seven_seg[dis_buffer[0]];

break;

case 1:

P2 = bit_ser[1];

if(setflag == 3)

P0 =flag | seven_seg[dis_buffer[1]];

else

P0 =seven_seg[dis_buffer[1]];

break;

case 2:

P2 = bit_ser[2];

if(setflag == 2)

P0 =flag | seven_seg[dis_buffer[2]];

else

P0 =seven_seg[dis_buffer[2]];

break;

case 3:

P2 = bit_ser[3];

if(setflag == 2)

P0 =flag | seven_seg[dis_buffer[3]];

else

P0 =seven_seg[dis_buffer[3]];

break;

case 4:

P2 = bit_ser[4];

if(setflag == 1)

P0 =flag | seven_seg[dis_buffer[4]];

else

P0 =seven_seg[dis_buffer[4]];

break;

case 5:

P2 = bit_ser[5];

if(setflag == 1)

P0 =flag | seven_seg[dis_buffer[5]];

else

P0 =seven_seg[dis_buffer[5]];

break;

}

i++;

if(i >= 6)

{

i = 0;

if(j == 10)

{

j = 0;

if(setflag == 0)

DS1302_GetTime(&Time); //如果setflag是0,就从1302中读出时间,因为setflag不是0时,说明处于调整状态,不需要读时间

dis_buffer[5] = TimeSecond % 10; //把当前时间放入显示缓冲区

dis_buffer[4] = TimeSecond / 10;

dis_buffer[3] = TimeMinute % 10;

dis_buffer[2] = TimeMinute / 10;

dis_buffer[1] = TimeHour % 10;

dis_buffer[0] = TimeHour / 10;

}

j++;

}

}

void main()

{

Initial_DS1302(Time);

timer0_init();

while(1)

{

set_down();

timer_down();

up_down();

down_down();

beepflag_down();

if(setflag == 0 && TimeHour == romhour && TimeMinute == romminute && Beepflag == 1) //判断蜂鸣器是否要响

Beep = !Beep;

}

}

//keyc

#include<reg51h>

#define uchar unsigned char

#define uint unsigned int

uchar i = 0,j = 0,x = 0,setflag,flag_set,flag_timer;   //setflag用来表示调整的位置,flag_set和flag_timer分别表示当前处于调整状态还是定时状态

SYSTEMTIME Time={0,20,15,3,30,6,10};    //系统时间的初始值2010年6月30日星期三,15时20分0秒

char dis_buffer[6];    //存放显示数据的缓冲区

sbit Beep_flag = P3^2;    //蜂鸣器的接口

sbit key_timer = P3^4;    //定时按钮

sbit key_set = P3^5;    //调整按钮

sbit key_up = P3^6;    //增加按钮

sbit key_down = P3^7;    //减小按钮

char romhour,romminute,romsec;    //分别存放定时的时,分,秒

bit Beepflag;    //标记闹钟是否开启

//延时函数

void delays(uchar x)

{

while(x) x--;

}

//设置键的处理函数

void set()

{

setflag ++;

flag_set = 1;

if(setflag >= 4)

{

setflag = 0;

flag_set = 0;

Initial_DS1302(Time);

}

}

//定时间的处理函数

void timer()

{

setflag ++;

flag_timer = 1;

if(setflag == 1)

{

TimeHour = romhour;

TimeMinute = romminute;

TimeSecond = romsec;

}

else if(setflag >= 4)

{

setflag = 0;

flag_timer = 0;

romhour = TimeHour;

romminute = TimeMinute;

romsec = TimeSecond;

}

}

//增加键的处理函数

void up()

{

switch(setflag)

{

case 0:

break;

case 1:

TimeSecond ++;

if(TimeSecond >= 60)

TimeSecond = 0;

break;

case 2:

TimeMinute ++;

if(TimeMinute >= 60)

TimeMinute = 0;

break;

case 3:

TimeHour ++;

if(TimeHour >= 24)

TimeHour = 0;

break;

}

}

//减小键的处理函数

void down()

{

switch(setflag)

{

case 0:

break;

case 1:

TimeSecond --;

if(TimeSecond < 0)

TimeSecond = 59;

break;

case 2:

TimeMinute --;

if(TimeMinute < 0)

TimeMinute = 59;

break;

case 3:

TimeHour --;

if(TimeHour < 0)

TimeHour = 23;

break;

}

}

//设置键的扫描函数

void set_down()

{

if(key_set == 0 && flag_timer == 0)

{

delays(100);

if(key_set == 0)

{

set();

}

while(!key_set);

}

}

//定时键的扫描函数

void timer_down()

{

if(key_timer == 0 && flag_set == 0)

{

delays(100);

if(key_timer == 0)

{

timer();

}

while(!key_timer);

}

}

//增加键的扫描函数

void up_down()

{

if(key_up == 0 && setflag != 0)

{

delays(100);

if(key_up == 0)

{

up();

while(!key_up);

}

}

}

//减少键的处理函数

void down_down()

{

if(key_down == 0 && setflag != 0)

{

delays(100);

if(key_down == 0)

{

down();

while(!key_down);

}

}

}

//定时开关的扫描处理函数

void beepflag_down()

{

if(Beep_flag == 0)

{

delays(100);

{

Beepflag = !Beepflag;

while(!Beep_flag);

}

}

}

//ds1302h

#ifndef _REAL_TIMER_DS1302

#define _REAL_TIMER_DS1302

#include <REG51h>

sbit  DS1302_CLK = P1^1;              //实时时钟时钟线引脚

sbit  DS1302_IO  = P1^2;              //实时时钟数据线引脚

sbit  DS1302_RST = P1^3;              //实时时钟复位线引脚

sbit  ACC0 = ACC^0;

sbit  ACC7 = ACC^7;

sbit  Beep = P2^7;

typedef struct __SYSTEMTIME__

{   char Second;

char Minute;

char Hour;

char Week;

char Day;

char Month;

char Year;

}SYSTEMTIME; //定义的时间类型

#define AM(X) X

#define PM(X) (X+12)               // 转成24小时制

#define DS1302_SECOND 0x80          //秒寄存器

#define DS1302_MINUTE 0x82          //分寄存器

#define DS1302_HOUR 0x84

#define DS1302_WEEK 0x8A

#define DS1302_DAY 0x86

#define DS1302_MONTH 0x88

#define DS1302_YEAR 0x8C

#define DS1302_RAM(X) (0xC0+(X)2)    //用于计算 DS1302_RAM 地址的宏

void DS1302InputByte(unsigned char d)  //实时时钟写入一字节(内部函数)

{   unsigned char i;

ACC = d;

for(i=8; i>0; i--)

{ DS1302_IO  = ACC0;            //相当于汇编中的 RRC

DS1302_CLK = 1;

DS1302_CLK = 0;                 //发一个高跳变到低的脉冲

ACC = ACC >> 1;

}

}

unsigned char DS1302OutputByte(void)  //实时时钟读取一字节(内部函数)

{  unsigned char i;

for(i=8; i>0; i--)

{ ACC = ACC >>1;          //相当于汇编中的 RRC

ACC7 = DS1302_IO;

DS1302_CLK = 1;

DS1302_CLK = 0;                 //发一个高跳变到低的脉冲

}

return(ACC);

}

void Write1302(unsigned char ucAddr, unsigned char ucDa)//ucAddr: DS1302地址, ucData: 要写的数据

{ DS1302_RST = 0;

DS1302_CLK = 0;

DS1302_RST = 1;

DS1302InputByte(ucAddr);        // 地址,命令

DS1302InputByte(ucDa);        // 写1Byte数据

DS1302_CLK = 1;

DS1302_RST = 0;                  //RST 0->1->0,CLK 0->1

}

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据

{ unsigned char ucData;

DS1302_RST = 0;

DS1302_CLK = 0;

DS1302_RST = 1;                      //enable

DS1302InputByte(ucAddr|0x01);        // 地址,命令

ucData = DS1302OutputByte();         // 读1Byte数据

DS1302_CLK = 1;                      //RST 0->1->0,CLK 0->1

DS1302_RST = 0;

return(ucData);

}

void DS1302_SetProtect(bit flag)        //是否写保护

{ if(flag)

Write1302(0x8E,0x80); //WP=1,不能写入

else

Write1302(0x8E,0x00);//WP=0,可以写入

}

void DS1302_SetTime(unsigned char Address, unsigned char Value)        // 设置时间函数

{ DS1302_SetProtect(0);

Write1302(Address, ((Value/10)<<4 | (Value%10))); //高4位为十位,低4位为个位

DS1302_SetProtect(1);

}

//获取时间函数,从DS1302内读取时间然后存入Time内

void DS1302_GetTime(SYSTEMTIME Time)

{ unsigned char ReadValue;

ReadValue = Read1302(DS1302_SECOND);

Time->Second = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);//转换成10进制的秒

ReadValue = Read1302(DS1302_MINUTE);

Time->Minute = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_HOUR);

Time->Hour = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_DAY);

Time->Day = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_WEEK);

Time->Week = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_MONTH);

Time->Month = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_YEAR);

Time->Year = ((ReadValue&0x70)>>4)10 + (ReadValue&0x0F);

}

//利用STime初始化DS1302

void Initial_DS1302(SYSTEMTIME STime)

{ unsigned char Second=Read1302(DS1302_SECOND);

if(Second&0x80)   DS1302_SetTime(DS1302_SECOND,0);  //如果第七为1(表明没有启动), 则启动时钟

DS1302_SetTime(DS1302_SECOND,STimeSecond);  //设定起始时间

DS1302_SetTime(DS1302_MINUTE,STimeMinute);

DS1302_SetTime(DS1302_HOUR,STimeHour);

DS1302_SetTime(DS1302_DAY,STimeDay);

DS1302_SetTime(DS1302_MONTH,STimeMonth);

DS1302_SetTime(DS1302_YEAR,STimeYear);

DS1302_SetTime(DS1302_WEEK,STimeWeek);

}

#endif

数字电子技术基础课程设计(一)——电子钟
数字电子技术基础
课程设计
电子秒表
一.设计目的:
1、了解计时器主体电路的组成及工作原理;
2、熟悉集成电路及有关电子元器件的使用;
3、学习数字电路中基本RS触发器、时钟发生器及计数、译码显示等单元电路的综合应用。
二.设计任务及说明:
电子秒表电路是一块独立构成的记时集成电路芯片。它集成了计数器、、振荡器、译码器和驱动等电路,能够对秒以下时间单位进行精确记时,具有清零、启动计时、暂停计时及继续计时等控制功能。
设计一个可以满足以下要求的简易秒表
1秒表由5位七段LED显示器显示,其中一位显示“min”,四位显示“s”,其中显示分辩率为001 s,计时范围是0—9分59秒99毫秒;
2具有清零、启动计时、暂停计时及继续计时等控制功能;
3控制开关为两个:启动(继续)/暂停记时开关和复位开关
三.总体方案及原理:
电子秒表要求能够对时间进行精确记时并显示出来,因此要有时钟发生器,记数及译码显示,控制等模块,系统框图如下:
时钟发生器 记数器 译码器
显示器
控制器
图1系统框图
其中:
(1)时钟发生器:利用石英震荡555定时器构成的多谐振荡器做时钟源,产生100HZ的脉冲;
(2)记数器:对时钟信号进行记数并进位,毫秒和秒之间10进制,秒和分之间60进制;
(3)译码器:对脉冲记数进行译码输出到显示单元中;
(4)显示器:采用5片LED显示器把各位的数值显示出来,是秒表最终的输出,有分、秒、和毫秒位;
(5)控制器:控制电路是对秒表的工作状态(记时开始/暂停/继续/复位等)进行控制的单元,可由触发器和开关组成。
四.单元电路设计,参数计算和器件选择:
1时钟发生单元
时钟发生器可以采用石英晶体震荡产生100HZ时钟信号,也可以用555定时器构成的多谐振荡器,555定时器是一种性能较好的时钟源,切构造简单,采用555定时器构成的多谐振荡器做为电子秒表的输入脉冲源。
因输出要求为100HZ的,选择占空比为55%,可根据
T=( )Cln2=001
可选择的电阻进行连接可在输出端3获得频率为100HZ的矩形波信号,即T=001S的时钟源,当基本RS触发器Q=1时,门5开启,此时100HZ脉冲信号通过门5作为计数脉冲加于计数器①的计数输入端CP2。
图2时钟发生器555定时器构成的多谐振荡器
2记数单元
记数器74160、74ls192、74ls90等都能实现十进制记数,本设计采用二—五—十进制加法计数器74LS90构成电子秒表的计数单元,如图3所示,555定时器构成的多谐振荡器作为计数器①的时钟输入。计数器①及计数器②接成8421码十进制形式,其输出端与实验装置上译码显示单元的相应输入端连接,可显示001~009秒;01~09秒计时,计数器②及计数器③,计数器③和计数器④也接成8421码十进制形式,计数器④和计数器⑤接成60进制的形式,实现秒对分的进位。
集成异步计数器74LS90简介
74LS90是异步二—五—十进制加法计数器,它既可以作二进制加法计数器,又可以作五进制和十进制加法计数器。
图3为74LS90引脚排列,表1为功能表。
通过不同的连接方式,74LS90可以实现四种不同的逻辑功能;而且还可借助R0(1)、R0(2)对计数器清零,借助S9(1)、S9(2)将计数器置9。其具体功能详述如下:
(1)计数脉冲从CP1输入,QA作为输出端,为二进制计数器。
(2)计数脉冲从CP2输入,QDQCQB作为输出端,为异步五进制加法计数器。
(3)若将CP2和QA相连,计数脉冲由CP1输入,QD、QC、QB、QA作为输出端,
则构成异步8421码十进制加法计数器。
(4)若将CP1与QD相连,计数脉冲由CP2输入,QA、QD、QC、QB作为输出端,
则构成异步5421码十进制加法计数器。
(5)清零、置9功能。
a) 异步清零
当R0(1)、R0(2)均为“1”;S9(1)、S9(2)中有“0”时,实现异步清零功能,即QDQCQBQA=0000。
b) 置9功能
当S9(1)、S9(2)均为“1”;R0(1)、R0(2)中有“0”时,实现置9功能,即QDQCQBQA=1001。
图374LS90引脚排列(下)
输 入 输 出 功 能
清 0 置 9 时 钟 QD QC QB QA
R0(1)、R0(2) S9(1)、S9(2) CP1 CP2
1 1 0
× ×
0 × × 0 0 0 0 清 0
0
× ×
0 1 1 × × 1 0 0 1 置 9
0 ×
× 0 0 ×
× 0 ↓ 1 QA 输 出 二进制计数
1 ↓ QDQCQB输出 五进制计数
↓ QA QDQCQBQA输出8421BCD码 十进制计数
QD ↓ QAQDQCQB输出5421BCD码 十进制计数
1 1 不 变 保 持
表1 74LS90功能表
10秒到分位的6进制位可在十进制的基础上将QB、QC连接到一个与门,它的置零信号与系统的置零信号通过一个或门连接接至R0(1),即当记数为6或有置零信号是均置零,如图4所示。
图4 74ls90组成的6进制记数器
3 译码显示单元
74LS248(74LS48)是BCD码到七段码的显示译码器,它可以直接驱动共阴极数码管。它的管脚图如图5所示 显示器用 LC5011-11 共阴极LED显示器(注:在multisim中仿真可以用译码显示器DCD_HEX代替译码和显示单元)。
图5 74LS248管脚图
4 控制单元
(1) 启动(继续)/暂停记时开关
采用集成与非门构成的基本RS触发器。属低电平直接触发的触发器,有直接置位、复位的功能。
它的一路输出作为单稳态触发器的输入,另一路输出Q作为与非门5的输入控制信号。
按动按钮开关B(接地),则门1输出 =1;门2输出Q=0,K2复位后Q、状态保持不变。再按动按钮开关K1 ,则Q由0变为1,门5开启, 为计数器启动作好准备。由1变0,送出负脉冲,启动单稳态触发器工作。
(2) 清零开关
通过开关对每个计数器的R0(2)给以高电平能实现系统的清零。
五:在MULTISIM中进行仿真
将各个芯片在MULTISIM8中连接并进行仿真,仿真如图6所示,结果正确。
六:设计所需元件
555触发器一片,74ls90五片,74ls248五片,LC5011-11 共阴极LED显示器五片,
电容、电阻若干。
七:设计心得
本次课程设计对数字电子技术有了更进一步的熟悉,实际 *** 作和课本上的知识有很大联系,但又高于课本,一个看似很简单的电路,要动手把它设计出来就比较困难了,因为是设计要求我们在以后的学习中注意这一点,要把课本上所学到的知识和实际联系起来,同时通过本次电路的设计,不但巩固了所学知识,也使我们把理论与实践从真正意义上结合起来,增强了学习的兴趣,考验了我们借助互联网络搜集、查阅相关文献资料,和组织材料的综合能力。

参考资料:

>#include <NEW_8051h>"
#include <taskh>
//
sbit T_CLK=P3^5;      //DS1302引脚连接
sbit T_IO =P3^6;
sbit T_RST=P3^7;

sbit ACC0=ACC^0;           //1bit数据存储位
sbit ACC7=ACC^7;

uchar starts_time[7]={0x00,0x10,0x22,0x20,0x05,0x04,0x10};  //初始化后设置
uchar Sec;
uchar Cent;
uchar Hour;
uchar Year;
uchar Day;
uchar Week;
uchar Month;

//

//根据选择调整相应项目
void Set(uchar sel,uchar sel_1)
{
  uchar address,time;
  uchar max,min;
 if(sel==1)  {address=0x84; max=23;min=0;}    //小时
 if(sel==2)  {address=0x82; max=59;min=0;}    //分钟
 if(sel==3)  {address=0x88; max=12;min=1;}    //月
 if(sel==4)  {address=0x86; max=31;min=1;}    //日
 if(sel==5)  {address=0x8a; max=7;min=1;}    //星期
  time=R1302(address+1)/1610+R1302(address+1)%16;    //变成BCD码
  if (sel_1==1) time++;  else time--;
  if(time>max) time=min;  
  if(time<min) time=max;
          
  W1302(0x8e,0x00);
  W1302(address,time/1016+time%10);  
  W1302(0x8e,0x80); 
}

//DS1302读写程序///
函 数 名:RTInputByte()
功    能:实时时钟写入一字节
说    明:往DS1302写入1Byte数据 (内部函数)
入口参数:d 写入的数据
返 回 值:无 
/
void RTInputByte(uchar d)
{
    uchar h;
    ACC = d;
    for(h=8; h>0; h--)
    {
        T_IO = ACC0;           /相当于汇编中的 RRC /
        T_CLK = 1;
        T_CLK = 0;
        ACC = ACC >> 1;
    }
}
uchar RTOutputByte(void)
{
    uchar h;
    for(h=8; h>0; h--)
    {
        ACC = ACC >>1;         /相当于汇编中的 RRC /
        ACC7 = T_IO;
        T_CLK = 1;
        T_CLK = 0;
    }
    return(ACC);
}
//
void W1302(uchar ucAddr, uchar ucDa)
{
    T_RST = 0;
    T_CLK = 0;
    T_RST = 1;
    RTInputByte(ucAddr);       / 地址,命令 /
    RTInputByte(ucDa);       / 写1Byte数据/
    T_CLK = 1;
    T_RST = 0;
}
/
函 数 名:R1302()
功    能:读取DS1302某地址的数据
说    明:先写地址,后读命令/数据 (内部函数)
调    用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址
返 回 值:ucData :读取的数据
/
uchar R1302(uchar ucAddr)
{
    uchar ucData;
    T_RST = 0;
    T_CLK = 0;
    T_RST = 1;
    RTInputByte(ucAddr);             / 地址,命令 /
    ucData = RTOutputByte();         / 读1Byte数据 /
    T_CLK = 1;
    T_RST = 0;
    return(ucData);
}

/
函 数 名:Set1302()
功    能:设置初始时间
说    明:先写地址,后读命令/数据(寄存器多字节方式)
调    用:W1302()
入口参数:pClock: 设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年
                               7Byte (BCD码)1B 1B 1B 1B 1B  1B  1B
返 回 值:无
/
void Set1302(uchar pClock)
{
    uchar h;
    uchar ucAddr = 0x80;
    W1302(0x8e,0x00);           / 控制命令,WP=0,写 *** 作/
    for(h =7; h>0; h--)
    {
        W1302(ucAddr,pClock);  / 秒 分 时 日 月 星期 年 /
        pClock++;
        ucAddr +=2;
    }
 W1302(0xc0,0x01);
 W1302(0XC2,0X03);   //初始自动转换显示时间为3秒。
    W1302(0x8e,0x80);           / 控制命令,WP=1,写保护/

}

void Auto_Set1302(uchar pClock)
{
    uchar h;
    uchar ucAddr = 0x80;
 if(((R1302(0x81))&0x80)==0x80)
 {
     W1302(0x8e,0x00);           / 控制命令,WP=0,写 *** 作/
     for(h =7; h>0; h--)
     {
         W1302(ucAddr,pClock);  / 秒 分 时 日 月 星期 年 /
         pClock++;
         ucAddr +=2;
     }
    W1302(ucNumRows_adder,0);
    W1302(ucNumRows_p_adder,0);
    W1302(DISP_TIME_adder,170);
  W1302(0xc0,0x01);
  W1302(0XC2,0X03);   //初始自动转换显示时间为3秒。
     W1302(0x8e,0x80);           / 控制命令,WP=1,写保护/

 }
}
/读取DS1302中的时间/
void du1302()
{
      Sec=R1302(0x81);   //对取 秒 分 时 日 月 星期 年
   Cent=R1302(0x83);
   Hour=R1302(0x85);
   Day=R1302(0x87);
   Month=R1302(0x89);
   Week=R1302(0x8b);
   Year=R1302(0x8d);    
   //b=R1302(0xc1);
      //a=R1302(0xc3);
   //a=a/1610+a%16;
 
}
void  write_1302Data (uchar  ucAddr,uchar  Value)
{  
 W1302(0x8e,0x00);           / 控制命令,WP=0,写 *** 作/
    W1302(ucAddr,Value);        //地址和数据
    W1302(0x8e,0x80);           / 控制命令,WP=1,写保护/
}

用vhdl设计秒表全功略!
根据要求, 秒表的设计要有三个输入端:runstop,rst和clk runstop是开关, 按一下开始计时, 再按一下停止计时, 显示时间 可以使用一个T触发器来实现 当我们把T触发器的T端接高电平时, 它将实现翻转功能 然后用输入端口runstop 来控制, 当runstop 被按一下, 一个时钟到来, T触发器就进行一次翻转 我们也可以用D触发器来代替T触发器, 需要用一个反馈信号, 将输出的信号反馈到D端口 Rst 是复位, 当按下rst 时, 秒表的显示变为0 Clk是时钟, 实验中的时钟信号是250KHZ,为了实现秒表的正确计时功能, 需要进行2500分频 所以clk首先就应该接到一个分频器, 然后再为其他模块提供时钟 接着我们把秒表划分为以下几个模块:分频器, 计数器, T触发器, 扫描器, 八选一选择器, 七段译码器, 另外还有一个模块要在分, 秒和毫秒之间做一个划分(BAR) 计数器的功能是要实现毫秒,秒,分的计数,比较麻烦我们再将它分成几个模块, 可以是六进制的计数器和十进制的计数器进行级联来实现也可以是用100进制的计数器和60进制的计数器进行级联 我两种方法都尝试了一下发现后一种方法编程要复杂的多, 级联的时候可以稍微简单一些 因为D触发器,八选一选择器是程序包里有的,所以可以不编 把这些模块都编好了以后要做的就是把他们连在一起 有两种方法 一是用画图的方法, 二是用编程的方法, 用port map语句 同样, 这两种方法我也都尝试了 我觉得用画图的方法要简单一些
1程序如下:分频器: library ieee; use ieeestd_logic_1164all; use ieeestd_logic_unsignedall; entity df is port(clkin:in std_logic; dout:out std_logic);
end; architecture behavioral of df is begin process(clkin) variable df: std_logic_vector(7 downto 0):="00000000"; begin if (clkin'event and clkin='1')then if df/="11111010" then df:=df+1; else df:="00000001"; end if; end if; dout<=df(7); end process; end behavioral; 扫描器: library ieee; use ieeestd_logic_1164all; use ieeestd_logic_unsignedall;
entity scan is port(clk:in std_logic; s:out std_logic_vector(2 downto 0)); end scan;
architecture behavioral of scan is variable scan:std_logic_vector(2 downto 0); begin process(clk) begin if(clk'event and clk='1')then scan:=scan+1; end if; s<=scan; end process; end behavioral; 七段译码器: library ieee; use ieeestd_logic_1164all;
entity bcd is port(o:in std_logic_vector(3 downto 0); q:out std_logic_vector(6 downto 0)); end bcd ;
architecture behavioral of bcd is begin process(o) begin case o is when"0000"=>q<="0111111"; when"0001"=>q<="0000110"; when"0010"=>q<="1011011"; when"0011"=>q<="1001111"; when"0100"=>q<="1100110"; when"0101"=>q<="1101101"; when"0110"=>q<="1111101"; when"0111"=>q<="0100111"; when"1000"=>q<="1111111"; when"1001"=>q<="1101111"; when others=>q<="0000000"; end case; end process; end behavioral; 当然,以上的100进制和60进制计数器的设计过于复杂,可以由六进制和十进制的计数器级联代替,程序如下:六进制: library ieee; use ieeestd_logic_1164all; use ieeestd_logic_unsignedall; entity c6 is port(count:out std_logic_vector(3 downto 0); cout:out std_logic; cin,rst,clk:in std_logic); end c6; architecture behavioral of c6 is signal counter:std_logic_vector(2 downto 0); begin process(clk,rst) begin if rst='1'then counter<="000";cout<='0'; elsif clk'event and clk='1' then if cin='1' then if counter="101"then counter<="000";cout<='1'; else counter<=counter+"001"; cout<='0'; end if; end if; end if; end process; count(2 downto 0)<=counter; count(3)<='0'; end behavioral;
十进制: library ieee; use ieeestd_logic_1164all; use ieeestd_logic_unsignedall;
entity c10 is port(count:out std_logic_vector(3 downto 0); cout:out std_logic; cin,rst,clk:in std_logic); end c10;
architecture behavioral of c10 is signal counter:std_logic_vector(3 downto 0); begin process(clk,rst) begin if rst='1'then counter<="0000";cout<='0'; elsif clk'event and clk='1' then if cin='1' then if counter="1001"then counter<="0000";cout<='1'; else counter<=counter+"0001"; cout<='0'; end if; end if; end if; end process; count<=counter; end behavioral;
最后用画图讲这些模块连接起来


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/12940900.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-29
下一篇 2023-05-29

发表评论

登录后才能评论

评论列表(0条)

保存