📄 timer0.c
字号:
/*************************************************************************
* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. *
* All rights reserved. All use of this software and documentation is *
* subject to the License Agreement located at the end of this file below.*
*************************************************************************/
/******************************************************************************
*
* Description
* *************
* A simple program which, using an 8 bit variable, counts from 0 to ff,
* repeatedly. Output of this variable is displayed on the LEDs, the Seven
* Segment Display, and the LCD. The four "buttons" (SW0-SW3) are used
* to control output to these devices in the following manner:
* Button1 (SW0) => LED is "counting"
* Button2 (SW1) => Seven Segment is "counting"
* Button3 (SW2) => LCD is "counting"
* Button4 (SW3) => All of the peripherals are "counting".
*
* Upon completion of "counting", there is a short waiting period during
* which button/switch presses will be identified on STDOUT.
* NOTE: These buttons have not been de-bounced, so one button press may
* cause multiple notifications to STDOUT.
*
* Requirements
* **************
* This program requires the following devices to be configured:
* an LED PIO named 'led_pio',
* a Seven Segment Display PIO named 'seven_seg_pio',
* an LCD Display named 'lcd_display',
* a Button PIO named 'button_pio',
* a UART (JTAG or standard serial)
*
* Peripherals Exercised by SW
* *****************************
* LEDs
* Seven Segment Display
* LCD
* Buttons (SW0-SW3)
* UART (JTAG or serial)
* Software Files
* ****************
* count_binary.c ==> This file.
* main() is contained here, as is the lion's share of the
* functionality.
* count_binary.h ==> Contains some very simple VT100 ESC sequence defines
* for formatting text to the LCD Display.
*
*
* Useful Functions
* *****************
* count_binary.c (this file) has the following useful functions.
* static void sevenseg_set_hex( int hex )
* - Defines a hexadecimal display map for the seven segment display.
* static void handle_button_interrupts( void* context, alt_u32 id)
* static void init_button_pio()
* - These are useful functions because they demonstrate how to write
* and register an interrupt handler with the system library.
*
* count_binary.h
* The file defines some useful VT100 escape sequences for use on the LCD
* Display.
*/
/* Button pio functions */
/*
Some simple functions to:
1. Define an interrupt handler function.
2. Register this handler in the system.
*/
/*******************************************************************
* static void handle_button_interrupts( void* context, alt_u32 id)*
* *
* Handle interrupts from the buttons. *
* This interrupt event is triggered by a button/switch press. *
* This handler sets *context to the value read from the button *
* edge capture register. The button edge capture register *
* is then cleared and normal program execution resumes. *
* The value stored in *context is used to control program flow *
* in the rest of this program's routines. *
******************************************************************/
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"
#include <stdio.h>
#include <unistd.h>
#include "altera_avalon_timer.h"
#include "altera_avalon_uart.h"
#include "altera_avalon_timer_regs.h"
#include "io.h"
//全局变量
//static np_timer* timer=na_timer1;//定时器指针
const long nTimerPeriod=50000000;//定时周期1s
static int nTimerCount=0;//秒时间计数值,每次定时中断变化
static int nTimerDir=1;//计时方向,0为暂停,1为正向,-1为反向
//LED分钟数显示
void show_led(int secCount)
{
//np_pio *pio=na_led_pio;//得到LED指针
//如果secCount计数值超出范围,最多显示8min
if (secCount>=60*9)
secCount=60*8;
//用LED所亮个数来表示计时分钟数
IOWR_ALTERA_AVALON_PIO_DATA(LEDPIO_BASE,(1<<(secCount/60))-1);//pio->np_piodata=(1<<(secCount/60))-1;
}
//数码管BCD码显示
void show_seg_bcd(int code)
{
//np_pio* seg_pio=na_seven_seg_pio;//得到数码管指针
//将显示数据转为BCD码显示
if (code>=0 && code<10000)
{
IOWR_ALTERA_AVALON_PIO_DATA(SEVENSEGPIO_BASE,(((code/1000)%10)<<12)+(((code/100)%10)<<8)+(((code/10)%10)<<4)+(code%10));//seg_pio->np_piodata=
}
}
//数码管秒钟数显示
void show_decimal(int secCount)
{
//如果secCount计数已满9min,显示60s
if (secCount==60*9)
show_seg_bcd(60);
else
{secCount %=60;//取计时数值的秒钟数
show_seg_bcd(secCount);
}
}
//启动定时器
void start_timer(void)
{
//定时器控制寄存器stop位清零,start位写1
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE,~ ALTERA_AVALON_TIMER_CONTROL_STOP_MSK);
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE,ALTERA_AVALON_TIMER_CONTROL_START_MSK);
}
//暂停定时器
void pause_timer(void)
{
//定时器控制寄存器start位清零,stop位写1
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE,~ALTERA_AVALON_TIMER_CONTROL_START_MSK);
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE,ALTERA_AVALON_TIMER_CONTROL_STOP_MSK);
}
//定时器中断服务子程序
void my_timer_isr(int context)
{
//np_timer *timerT=(np_timer *)context;//得到定时器指针
//根据计时方向(正向计时或倒计时),计时数值加1或减1
if (nTimerDir==-1&&nTimerCount>0)
nTimerCount--;
else if (nTimerDir>0&&nTimerCount<60*9)
nTimerCount++;
//判断计时是否完成
if ((nTimerDir>0&&nTimerCount==60*9)||(nTimerDir<0 && nTimerCount==0))
{nTimerDir=0;//暂停计时
//计时完成,停止计时
pause_timer();
}
//在串口终端上显示计时时间
printf("%d'%d\"\t",nTimerCount/60,nTimerCount%60);
if (nTimerCount%10==0)
printf("\n");
//LED分钟数显示
show_led(nTimerCount);
//数码管秒钟数显示
show_decimal(nTimerCount);
//清除定时器中断状态
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER1_BASE,0x0);
}
//定时器初始化
void init_timer(void)
{
//设置定时周期1s
IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER1_BASE,(short)(nTimerPeriod&0x0000ffff));
IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER1_BASE,(short)((nTimerPeriod>>16)&0x0000ffff));
//安装定时器中断服务子程序
alt_irq_register(TIMER1_IRQ,0, my_timer_isr); //nr_installuserisr(na_timer1_irq,my_timer_isr,(long)timer);
//设置定时器循环工作,定时器允许中断
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE,ALTERA_AVALON_TIMER_CONTROL_CONT_MSK+ALTERA_AVALON_TIMER_CONTROL_ITO_MSK);
}
//main主程序
int main(void)
{
//按键变量
int buttons,buttonsLast=0x000F;
IOWR_ALTERA_AVALON_PIO_DATA(BUTTONPIO_BASE,0X0);
//按键指针
//np_pio *pio=buttonpio;
//设置按键端口全为输入端口
//pio->np_piodirection=0;
//初始化定时器设置
init_timer();
//开启定时器
start_timer();
//循环检测串口输入是否位Esc键的键值
while (1)
{
//读取按键数据端口输入码
buttons=IORD_ALTERA_AVALON_PIO_DATA(BUTTONPIO_BASE);//buttons=pio->np_piodata;
//判断是否有按键按下
if (buttons!=buttonsLast&&buttonsLast==0x000F)
{
switch(buttons&0x000F)
{
case 0x000E://SW0,定时器清零或置数
pause_timer();//暂停
//按一次清零,再按则置数
if (nTimerCount>0)
nTimerCount=0;
else
nTimerCount=60*9;
//刷新LED和数码管显示内容
show_led(nTimerCount);
show_decimal(nTimerCount);
break;
case 0x000D://SW1,置数
//每按一次SW1置数时间加60s,超出则清零
if (nTimerCount==60*9)
nTimerCount=0;
else if(nTimerCount>60*8)
nTimerCount=60*9;
//刷新LED和数码管显示内容
show_led(nTimerCount);
show_decimal(nTimerCount);
break;
case 0x000B://SW2,向上计时或暂停
if(nTimerDir!=0)
{
pause_timer();//暂停
nTimerDir=0;
}
else
{
//向上计时开始
start_timer();
nTimerDir=1;
}
break;
case 0x0007://SW3,倒计时或暂停
if (nTimerDir!=0)
{
pause_timer();//暂停
nTimerDir=0;
}
else
{
//倒计时开始
start_timer();
nTimerDir=-1;
}
break;
case 0x000F://没有按键按下
buttons=buttonsLast=0x000F;
break;
default:
break;
}
}
//保存当前按键键值到buttonLast变量
buttonsLast=buttons;
}
//卸载定时器中断服务子程序,关闭定时器中断
alt_irq_register(TIMER1_IRQ,0,0);
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE,~ALTERA_AVALON_TIMER_CONTROL_ITO_MSK);
//显示程序退出信息,\004即Ctrl-D,表示程序已结束
printf("\nExit mytimer.\n\004");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -