⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer0.c

📁 NIOS系统中的定时器编程实现
💻 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 + -