目录
第一部分、前言
1、闲话
这个设计也是我们《SOPC技术及应用》课程结束的期末作业,也相当于期末考试。我自己的是老师题库里的第五题、驱动AD9854这个模块,题目要求在《【NiosII训练】第一篇、FPGA驱动AD9854基础篇:https://blog.youkuaiyun.com/Learning1232/article/details/111193587》已经说到了,想回去看的铁子们可以回去看。这个定时闹钟的设计是我❤,她抽签抽到的第十八题,她不是很会,So。。。。题目要求如下。
第二部分、题目要求
1、图片
2、文字描述
使用sopc技术中的定时器设计一个能够定时的闹钟,能够在某款lcd上显示当前时间与定的闹钟的时间,当定的时间到时,ac620上的蜂鸣器能够响起来。
第三部分、工程代码
1、软核的搭建
这里核心的部分就是LCD9341的IP核、定时器的IP核、一个控制蜂鸣器的IP核和一个控制LED的IP核。工程还是一样基于之前小梅哥家的LCD9341的例程修改的,因为这个工程里面包含了LCD9341的IP核。
2、顶层文件的代码
预编译过后,将蜂鸣器的引脚分配为PB6(我这里没有用板载蜂鸣器,用的是一个外接的有源的低电平触发蜂鸣器,简单)
module AC620_GHRD(
input wire clk, // clk.clk
input wire reset_n, // reset.reset_n
output wire lcd_rst, // lcd_rst.export
output wire lcd_rd_n, // lcd_rd.export
output wire lcd_bl, // lcd_bl.export
output wire lcd_wr_n, // lcd_wr.export
output wire lcd_rs, // lcd_rs.export
output wire lcd_cs_n, // lcd_cs.export
inout wire [15:0] lcd_data, // lcd_db.export
output wire sdram_clk, // sdram_clk.clk
output wire [11:0] sdram_addr, // sdram.addr
output wire [1:0] sdram_ba, // .ba
output wire sdram_cas_n, // .cas_n
output wire sdram_cke, // .cke
output wire sdram_cs_n, // .cs_n
inout wire [15:0] sdram_dq, // .dq
output wire [1:0] sdram_dqm, // .dqm
output wire sdram_ras_n, // .ras_n
output wire sdram_we_n, // .we_n
input wire uart_0_rxd, // uart_0.rxd
output wire uart_0_txd, // .txd
output wire epcs_dclk, // epcs.dclk
output wire epcs_sce, // .sce
output wire epcs_sdo, // .sdo
input wire epcs_data0, // .data0
output wire [3:0] pio_led,
output wire pio_buzzer
);
mysystem u0 (
.clk_clk (clk), // clk.clk
.reset_reset_n (reset_n), // reset.reset_n
.uart_0_rxd (uart_0_rxd), // uart_0.rxd
.uart_0_txd (uart_0_txd), // .txd
.epcs_dclk (epcs_dclk), // epcs.dclk
.epcs_sce (epcs_sce), // .sce
.epcs_sdo (epcs_sdo), // .sdo
.epcs_data0 (epcs_data0), //
.lcd_rst_export (lcd_rst), // lcd_rst.export
.lcd_bl_export (lcd_bl), // lcd_bl.export
.lcd_wr_n (lcd_wr_n), // lcd.wr_n
.lcd_rd_n (lcd_rd_n), // .rd_n
.lcd_data (lcd_data), // .data
.lcd_rs (lcd_rs), // .rs
.lcd_cs_n (lcd_cs_n), //
.sdram_clk_clk (sdram_clk), // sdram_clk.clk
.altpll_0_phasedone_conduit_export (), // altpll_0_phasedone_conduit.export
.altpll_0_locked_conduit_export (), // altpll_0_locked_conduit.export
.altpll_0_areset_conduit_export (), // altpll_0_areset_conduit.export
.sdram_addr (sdram_addr), // sdram.addr
.sdram_ba (sdram_ba), // .ba
.sdram_cas_n (sdram_cas_n), // .cas_n
.sdram_cke (sdram_cke), // .cke
.sdram_cs_n (sdram_cs_n), // .cs_n
.sdram_dq (sdram_dq), // .dq
.sdram_dqm (sdram_dqm), // .dqm
.sdram_ras_n (sdram_ras_n), // .ras_n
.sdram_we_n (sdram_we_n), // .we_n
.pio_buzzer_export (pio_buzzer), // pio_buzzer.export
.pio_led_export (pio_led) // pio_led.export
);
endmodule
3、Ecplise代码
#include "lcd9341.h"
#include "system.h"
#include "altera_avalon_timer_regs.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"
#include "unistd.h"
#include <stdio.h>
#include "priv/alt_legacy_irq.h"
/************************************************************/
/*蜂鸣器I/o接 B6 管脚
/*
************************************************************/
//时间变量的定义
unsigned int s=0,m=20,h=12,led=0;//设置当前时间
unsigned int s1=0,m1=21,h1=12; //设置闹钟时间
unsigned char ss[10],ms[10],hs[10],ss1[10],ms1[10],hs1[10];
unsigned char s1s[10],m1s[10],h1s[10],s1s1[10],m1s1[10],h1s1[10];
//函数声明
alt_u32 timer_isr_context; //定义全局变量以储存 isr_context 指针
void Timer_Initial(void); //定时器中断初始化
void Timer_ISR_Interrupt(void); //定时器中断服务子程序
//---------------------------------------------------------------------------
//-- 名称 : Timer_Initial()
//-- 功能 : 定时器中断初始化
//-- 输入参数 : 无
//-- 输出参数 : 无§4 Qsys 丰富多彩的内置 IP 核 161
//---------------------------------------------------------------------------
void Timer_Initial(void)
{
//改写 timer_isr_context 指针以匹配 alt_irq_register()函数原型
void* isr_context_ptr = (void*) &timer_isr_context;
//设置 PERIOD 寄存器
//PERIODH << 16 | PERIODL = 计数器周期因子 * 系统时钟频率因子 - 1
//PERIODH << 16 | PERIODL = 1s*100M - 1 = 99 999 999 = 0x05F5_E0FF
IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE, 0x05F5);
IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE, 0xE0FF);//5F5E0FF
//设置 CONTROL 寄存器
//位数 | 3 | 2 | 1 | 0 |
//CONTROL | STOP | START | CONT | ITO |
//ITO 1,产生 IRO; 0,不产生 IRQ
//CONT 1,计数器连续运行直到 STOP 被置一; 0,计数到 0 停止
//START 1,计数器开始运行; 0,无影响
//STOP 1,计数器停止运行; 0,无影响
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE,
ALTERA_AVALON_TIMER_CONTROL_START_MSK | //START = 1
ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | //CONT = 1
ALTERA_AVALON_TIMER_CONTROL_ITO_MSK); //ITO = 1
//注册Timer1中断
alt_irq_register(TIMER_0_IRQ, NULL, Timer_ISR_Interrupt);
}
//---------------------------------------------------------------------------
//-- 名称 : Timer_Initial()
//-- 功能 : 定时器中断服务子程序
//-- 输入参数 : timer_isr_context,用于传递中断状态寄存器的值,id,中断号
//-- 输出参数 : 无
//---------------------------------------------------------------------------
void Timer_ISR_Interrupt(void)
{
//用户中断代码
s++;
if(s == 60)
{
s = 0;
m++;
if(m == 60)
{
m = 0;
h++;
if(h == 24)
{
h = 0;
}
}
}
led ++;
//应答中断,将 STATUS 寄存器清零
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE,~ALTERA_AVALON_TIMER_STATUS_TO_MSK);
}
//---------------------------------------------------------------------------
//-- 名称 : main()
//-- 功能 : 程序入口
//-- 输入参数 : 无
//-- 输出参数 : 无
//---------------------------------------------------------------------------
int main(void)
{
alt_u32 led_state = 0xff; //初始化 Led
Timer_Initial(); //初始化定时器中断
LCD9341_Init();
printf("Welcome To Timer Ip Demo Program... \n");
IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, 0xff);//使 led熄灭
IOWR_ALTERA_AVALON_PIO_DATA(PIO_BUZZER_BASE, 1);//蜂鸣器关闭
while(1)
{
POINT_COLOR=RED;
LCD_ShowString(50,30,"Alarm Clock Test");
LCD_ShowString(66,70,"Time: ");
printf("%d\n",h);
printf("%d\n",m);
printf("%d\n",s);
sprintf(hs,"%d",h/10);
sprintf(hs1,"%d",h%10);
sprintf(ms,"%d",m/10);
sprintf(ms1,"%d",m%10);
sprintf(ss,"%d",s/10);
sprintf(ss1,"%d",s%10);
sprintf(h1s,"%d",h1/10);
sprintf(h1s1,"%d",h1%10);
sprintf(m1s,"%d",m1/10);
sprintf(m1s1,"%d",m1%10);
sprintf(s1s,"%d",s1/10);
sprintf(s1s1,"%d",s1%10);
LCD_ShowString(114,70,hs);
LCD_ShowString(122,70,hs1);
LCD_ShowString(130,70,":");
LCD_ShowString(138,70,ms);
LCD_ShowString(146,70,ms1);
LCD_ShowString(154,70,":");
LCD_ShowString(162,70,ss);
LCD_ShowString(170,70,ss1);
LCD_ShowString(10,90,"Alarm Clock: ");
LCD_ShowString(114,90,h1s);
LCD_ShowString(122,90,h1s1);
LCD_ShowString(130,90,":");
LCD_ShowString(138,90,m1s);
LCD_ShowString(146,90,m1s1);
LCD_ShowString(154,90,":");
LCD_ShowString(162,90,s1s);
LCD_ShowString(170,90,s1s1);
if(h1 == h && m1==m && s1 == s)
{
led = 0;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, 0);//使 led 全亮
IOWR_ALTERA_AVALON_PIO_DATA(PIO_BUZZER_BASE, 0);//蜂鸣器叫
}
if(led == 5)//5秒后停止叫
{
led = 0;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, 0xff);//使 led熄灭
IOWR_ALTERA_AVALON_PIO_DATA(PIO_BUZZER_BASE, 1);//蜂鸣器关闭
}
}
}
第四部分、总结
1、实现的功能阐述
这个里面的实时时间Time和闹钟Alarm Clock是自己手动从代码中输入进去的,当Time的时间和Alarm Clock的时间一样时,蜂鸣器叫,我这里蜂鸣器是外接的一个模块,低电平就叫唤,叫唤5秒后停止叫唤,然后你又得从Ecplise软件中更改代码或者重新仿真一次。最后毕竟题目要求很宽泛,所以这样的效果足以满足老师的检查。
2、结果演示
这里只展示图片,视频文件我已经上传到群文件,你也可以点击这里看一下演示效果(https://live.youkuaiyun.com/v/121242)。
3、完整工程
嫖嫖时间,完整的工程,我整理了好了,扫码加群,群文件里面有、要么留下邮箱,我看到了我会发链接给你或者你想大气一下,请点击这里,谢谢老板“🐶”“🐶”“🐶”(https://download.youkuaiyun.com/download/Learning1232/13694624)!
对了有问题直接留言或私信哈!