本文转载至:http://www.cnblogs.com/Neddy/archive/2010/07/18/1780249.html,在此对原作者的辛勤劳作表示深深的敬意!
在LCD1602上面显示时间、日期和星期
因为用到了SDRAM,首先我们添加一个PLL
输入时钟 50MHz
输出时钟 C0 50MHz ,相位-75度,给SDRAM提供时钟,引脚命名为sd_clk
C1 50NHz , 相位 0 度,给NIOS提供时钟信号,与NIOS CLK相连
1、打开SOPC,添加CPU,选择NIOS II/s即可
2、添加SDRAM,Presets选择Custom,Data width:16,其他的不动,点击Finish……
3、添加timer,Period:1s,Presets:Full-featured
4、添加Character LCD,没有参数设置
5、添加PIO,Width:4 ,INPUT
第二张参数设定画面,下降沿capture,边沿中断
更名为key
6、CPU的Reset Vector和Exception vector都为sdram
7、Auto-Assign Base Addresses和Auto-Assign IRQs,再Generate……
8、在原理图里面添加SOPC,更改PIN名,如下图:
9、引脚锁定,根据实际情况做
10、Start Compilation and progammer
11、NIOS II 代码:
#include "system.h" //包含基本的硬件描述信息
#include "altera_avalon_timer_regs.h" //定义内核寄存器的映射,提供对底层硬件的符号化访问
#include "altera_avalon_pio_regs.h" //包含基本的I/O口信息
#include "alt_types.h" //Altera定义的数据类型
#include "sys/alt_irq.h"
#include "unistd.h" //延时函数usleep
#include "stdio.h"
//定义端口
#define key *(volatile unsigned char *) KEY_BASE
//函数声明
void Timer_Init();
void Timer_ISR(void* context, alt_u32 id);
void display();
void KeyDown_ISR(void* context, alt_u32 id);
void KeyDown_Init();
//变量定义
alt_u8 num_s[8] = {0,0,0xbf,0,0,0xbf,0,0};//时间每位显示
alt_u8 num_d[8] = {0,0,0,0,0,0,0,0};//日期每位显示
alt_u8 second,min,hour,day,month,weekday;
alt_u16 year;
char *week[]={"SUN","MON","TUE","WED","THU","FRI","SAT"}; //星期
void init_value(void)
{
second=0;
min=0;
hour=12;
day=1;
month=1;
year=2010;
weekday=0;
}
//按键中断服务函数
void KeyDown_ISR(void* context, alt_u32 id)
{
if(key == 0x06) { second = 0; while(key == 0x06){display();} } //秒调设置
if(key == 0x05) { min++; if(min==60) min = 0; while(key == 0x05){display();} } //分调设置
if(key == 0x03) { hour++; if(hour == 24) hour = 0; while(key == 0x03){display();} }//小时设置
if(key == 0x0e) //日期设置
{
day++;
if( ( month<=7 && month%2 ) || ( month>=8 && (!(month%2)) ) ) //大月31天
{
if(day==32) day=1;
}
else //小月30
{
if(month==2) //2月 是28天还是29天
{
if( (!(year%4) && year%100) || (!(year%400) ) )// 闰年 29天
{ if(day==30) day=1; }
else if(day==29) day=1; //平年 28天
}
else if(day==31) day=1;
}
while(key == 0x0e) display();
}
if(key == 0x0c) { weekday++; if(weekday == 7) weekday = 0; while(key == 0x0c){display();} }//月份设置
if(key == 0x0d) { month++; if(month == 13) month = 1; while(key == 0x0d){display();} }//月份设置
if(key == 0x0b) { year--; if(year == 1900) year = 2010; while(key == 0x0b){display();} }//年份设置,递减
if(key == 0x08) { year++; if(year == 2100) year = 2010; while(key == 0x08){display();} }//年份设置,递加
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x00); //清中断捕获寄存器
}
//按键中断初始化
void KeyDown_Init()
{
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE, 0x07); //开KEY中断
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x00); //清中断捕获寄存器
alt_irq_register(KEY_IRQ,0,KeyDown_ISR); //注册中断函数
}
//定时器初始化
void Timer_Init()
{
alt_irq_register(TIMER_IRQ,0,Timer_ISR); //注册中断函数
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_BASE, 0); //清状态标志
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_BASE, 7); //启动定时器允许中断,连续计数
}
//定时器中断服务函数
void Timer_ISR(void* context, alt_u32 id)
{
second++;
if(second == 60) { min++; second = 0;}
if(min == 60) { hour++; min = 0;}
if(hour == 24) { day++;weekday++;hour = 0;}
if(weekday == 7) weekday = 0;
if( ( month<=7 && month%2 ) || ( month>=8 && (!(month%2)) ) )
{
if(day==32)
{
day=1;
month++;
}
}
else
{
if(month==2)
{
if( (!(year%4) && year%100) || (!(year%400) ) )
{
if(day==30)
{
day=1;
month++;
}
}
else if(day==29)
{
day=1;
month++;
}
}
else if(day==31)
{
day=1;
month++;
}
}
if(month==13) { month = 1; year ++; }
if(year==2100) year = 2010;
//if(second % 2) duan[10] = 0xff;
//else duan[10] = 0xbf; //秒闪烁
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_BASE, 0); //清状态寄存器
}
//数码管显示函数
void display()
{
num_s[0] = second % 10;
num_s[1] = second / 10;
num_s[2] = 10;
num_s[3] = min % 10;
num_s[4] = min / 10;
num_s[5] = 10;
num_s[6] = hour % 10;
num_s[7] = hour / 10;
num_d[0] = day%10;
num_d[1] = day/10;
num_d[2] = month%10;
num_d[3] = month/10;
num_d[4] = year%10;
num_d[5] = year/10%10;
num_d[6] = year/100%10;
num_d[7] = year/1000;
printf(" %d%d%d%d-%d%d-%d%d\n %d%d-%d%d-%d%d %s\n",
num_d[7],num_d[6],num_d[5],num_d[4],num_d[3],num_d[2],num_d[1],num_d[0],
num_s[7],num_s[6],num_s[4],num_s[3],num_s[1],num_s[0],week[weekday]);
//LCD6102显示
}
//主函数
int main(void)
{
KeyDown_Init(); //按键中断初始化
Timer_Init(); //定时器初始化
init_value();
while(1)
{
display(); //显示
}
return 0;
}
按键复用写的不好,根据实际情况更改……