此设计为笔者实验课期末设计,仅供参考,博客贴出实现方法和C语言部分程序源代码,实现过程用时不长,故没有对代码进行优化,但功能已实现。工程文件提交到CSDN下载当中,需要可以下载,https://download.csdn.net/download/g_curry/10855434另外还有设计报告,如需要可私信博主获取。
要求必须使用Verilog和Sopc两项功能,故在硬件部分使用Verilog编写出数码管的驱动程序,使用NiOS II编写实现过程。
1.功能需求
1)实现数字时钟准确实时的计时与显示功能;
2)实现闹钟功能,即系统时间到达闹钟时间时闹铃响;
3)实现时间和闹钟时间的调时功能;
4)实现流水灯指示功能。
2.设计方案
1)使用Qsys生成的定时器timer_1ms实现计时功能;
2)使用8个数码管显示时间;
3)使用3个按钮实现调时间和闹钟时间的功能。
按键1:更换模式(模式0:正常显示时间;模式1:调当前时间的小时;模式2;调当前时间的分钟;模式3:当前时间的秒;模式4:调闹钟时间的小时;模式5:调闹钟时间的分钟);
按键2:在非模式0下给需要调节的时间数加一,但不溢出;
按键3:在非模式0下给需要调节的时间数减一,但不小于零;
实现时间和闹钟时间的调时功能;
4)加入闪烁标志,给正在调整的位闪烁,判断是哪一位在调整;
5)按键按下时,对应一个led灯点亮;
6)使用蜂鸣器实现闹钟功能,闹钟响时实现流水灯指示功能。
3.硬件规划
在硬件系统组织规划中系统需使用的外围器件包括:
1)数码管:数子钟显示屏幕;
2)按键:数子钟设置功能键;
3)LED灯:8位LED灯做指示灯;
4)蜂鸣器:闹钟响铃。存储软、硬件程序;
在SOPC Qsys中建立系统添加的模块包括:
1)连接数码管的PIO;
2)Interval Timer;
3)按键PIO;
4)On-Chip Memory RAM;
5)On-Chip Memory ROM;
6)System ID Peripheral;
#include <sys/unistd.h>
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_timer_regs.h"
#include "sys/alt_irq.h"
int hour = 23,minute = 59,second = 50;
int hour1 = 0,minute1 = 0,n =0;
int segtab[12]={0x0,0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,0xf,0xe};
int model_flag = 0,S_flag = 0,BEEP = 0,beep_flag = 0,beep_flag1 = 0;
int key_set = 1,key_add = 1,key_sub = 1,key_rst = 1;
int a[8]={0,0,0,0,0,0,0,0};
void write_data()
{
IOWR(DIG_1_BASE,0,a[7]);
IOWR(DIG_2_BASE,0,a[6]);
IOWR(DIG_3_BASE,0,a[5]);
IOWR(DIG_4_BASE,0,a[4]);
IOWR(DIG_5_BASE,0,a[3]);
IOWR(DIG_6_BASE,0,a[2]);
IOWR(DIG_7_BASE,0,a[1]);
IOWR(DIG_8_BASE,0,a[0]);
}
void rst()
{
if(key_rst==0)
{
key_rst =1;
a[0]=2;
a[1]=3;
a[2]=segtab[10];
a[3]=5;
a[4]=9;
a[5]=segtab[10];
a[6]=5;
a[7]=5;
write_data();
}
}
void set_led(int led_flag, int state)
{
if ( led_flag == 1) {
IOWR(LED_BASE,0,0xff);
}
else if ( led_flag == 2){
IOWR(LED_BASE,0,state);
}
else {
IOWR(LED_BASE,0,0x00);
}
}
void delay(int us)// 延时函数
{
int i,j;
for ( i = us; i > us; i--) {
for ( j = 50; j > 0; j--);
}}
int read_key()
{
int status = 0;
status = IORD(KEY_BASE,0);
return status;
}
int tmp = 0;
void check_key()
{
delay(10);
int status = IORD(KEY_BASE,0);
if ( status) {
tmp ++;
if ( tmp == 50) {
if ( status & 0x01) {
key_set = 0;
set_led(2,0x01);
}
else if ( status & 0x01 << 1) {
key_add =0;
set_led(2,0x02);
}
else if ( status & 0x01<< 2){
key_sub = 0;
set_led(2,0x04);
}
else if ( status & 0x01<< 3){
key_rst = 0;
set_led(2,0x08);
}
else
{
tmp = 0;
}}}
else {
tmp = 0;
}}
void delay(int us)// 延时函数
{
int i,j;
for ( i = us; i > us; i--) {
for ( j = 50; j > 0; j--);
}
}
int flag = 0,ss_add = 0;
void ISR_timer(void * context, alt_u32 id)
{
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1S_BASE, 0);
ss_add++;
if(ss_add >= 500)
{
ss_add = 0;
S_flag =! S_flag; //闪烁标志位
}
flag = 1;
}
void display()
{
switch(model_flag)
{
case 0:
{
a[0]=segtab[hour/10];
a[1]=segtab[hour%10];
a[2]=segtab[10];
a[3]=segtab[minute/10];
a[4]=segtab[minute%10];
a[5]=segtab[10];
a[6]=segtab[second/10];
a[7]=segtab[second%10];
write_data();
}break;
case 1:
{
if(S_flag==1)
{
a[0]=segtab[hour/10];
a[1]=segtab[hour%10];
}
else
{
a[0]=segtab[11];
a[1]=segtab[11];
}
a[2]=segtab[10]; //横线-
a[3]=segtab[minute/10];
a[4]=segtab[minute%10];
a[5]=segtab[10];
a[6]=segtab[second/10];
a[7]=segtab[second%10];
write_data();
}
break;
case 2:
{
a[0]=segtab[hour/10];
a[1]=segtab[hour%10];
a[2]=segtab[10];
if(S_flag==1)
{
a[3]=segtab[minute/10];
a[4]=segtab[minute%10];
}
else
{
a[3]=segtab[11];
a[4]=segtab[11];
}
a[5]=segtab[10];
a[6]=segtab[second/10];
a[7]=segtab[second%10];
write_data();
}break;
case 3:
{
a[0]=segtab[hour/10];
a[1]=segtab[hour%10];
a[2]=segtab[10];
a[3]=segtab[minute/10];
a[4]=segtab[minute%10];
a[5]=segtab[10];
if(S_flag==1)
{
a[6]=segtab[second/10];
a[7]=segtab[second%10];
}
else
{
a[6]=segtab[11];
a[7]=segtab[11];
}
write_data();
}break;
case 4:
{
if(S_flag==1)
{
a[0]=segtab[hour1/10];
a[1]=segtab[hour1%10];
}
else
{
a[0]=segtab[11];
a[1]=segtab[11];
}
a[2]=segtab[10];
a[3]=segtab[minute1/10];
a[4]=segtab[minute1%10];
a[5]=segtab[10];
a[6]=segtab[11];
a[7]=segtab[11];
write_data();
}break;
case 5:
{
a[0]=segtab[hour1/10];
a[1]=segtab[hour1%10];
a[2]=segtab[10];
if(S_flag==1)
{
a[3]=segtab[minute1/10];
a[4]=segtab[minute1%10];
}
else
{
a[3]=segtab[11];
a[4]=segtab[11];
}
a[5]=segtab[10];
a[6]=segtab[11];
a[7]=segtab[11];
write_data();
}
}
}
void key_model()
{
if(key_set==0)
{
key_set = 1;
model_flag++;
if(model_flag==6)
model_flag=0;
}
if(model_flag!=0)
{
switch(model_flag)
{
case 1: //模式——调时
{
if(key_add==0)
{
key_add = 1;
if(hour<23) hour++;
else hour=0;
}
if(key_sub==0)
{
key_sub = 1;
if(hour> 0) hour--;
else hour=23;
}
} break;
case 2: //模式——调分
{
if(key_add==0)
{
key_add = 1;
if(minute<59) minute++;
else minute=0;
}
if(key_sub==0)
{
key_sub = 1;
if(minute>0) minute--;
else minute=59;
}
} break;
case 3: //模式——调秒
{
if(key_add==0)
{
key_add = 1;
if(second<59) second++;
else second=0;
}
if(key_sub==0)
{
key_sub = 1;
if(second>0) second--;
else second=59;
}
} break;
case 4: //模式——闹钟调时
{
if(key_add==0)
{
key_add = 1;
if(hour1<23)
hour1++;
else hour1=0;
}
if(key_sub==0)
{
key_sub = 1;
if(hour1>0)
hour1--;
else hour1=23;
}
} break;
case 5: //模式——闹钟调分
{
if(key_add==0)
{
key_add = 1;
if(minute1<59)
minute1++;
else minute1=0;
}
if(key_sub==0)
{
key_sub = 1;
if(minute1>0)
minute1--;
else minute1=59;
}
} break;
}
}
}
void naozhong()
{
if(hour1==hour&&minute1==minute&&second<10) //闹钟时间到
{
beep_flag = ~beep_flag;
if (beep_flag == 0)
IOWR(BEEP_BASE,0,0);
else
IOWR(BEEP_BASE,0,1);
if(S_flag==1)
{
set_led(2,0x55);
}
else
{
set_led(2,~0x55);
}
}
}
int main()
{
alt_irq_register(TIMER_1S_IRQ,0,ISR_timer);
flag = 0;
while(1)
{
check_key();
key_model();
if (flag)
{
rst();
naozhong();
flag = 0;
n++;
if(n == 1000)
{
n = 0;
second++;
if(second >= 60)
{
minute++;
second = 0;
}
if(minute >= 60)
{
hour++;
minute = 0;
}
if(hour >= 24)
{
hour = 0;
}
}
display();
}
}
return 0;
}