ARM_Linux_NOTE_5

ARM_Linux NOTE_5

Vine Farer
2016.08.12

4、Timer定时中断

1)基本的定时(计时)中断

  • 配置定时器中断,需要额外设置TINT_CSTAT寄存器

    Timer 2为例

    Timer 2 interrupt enable 置一,使能Timer 2

    Timer 2 interrupt status 置一,清除中断状态

  • Timer 2中断模式初始化(code)
    void init_timer2(int ms) 
    {
        //-------------------Timer2----------------------//
        //----------- 39  71  ¨C  TIMER2-----------------//
        PWM.TCFG0 = (PWM.TCFG0 & (~(0xff << 8))) | (99 << 8); 
        // 100M / 100 = 1MHz
        PWM.TCFG1 = (PWM.TCFG1 & (~(0xf << 8))) | (0b0000 << 8);
        // 1M / 1 = 1MHz
    
        PWM.TCNTB2 = 1000000;// 1M / 1M 获得一秒的周期,初值自减到0,无需设置占空比
        PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b1010 << 12); 
        PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b1001 << 12); 
        //依旧循环自动装载,保证每1s减到0能触发一次中断
        PWM.TINT_CSTAT |= (1 << 2); //Timer 2 中断使能
    
        fun_p[71] = timer2_int;//装载定时器中断处理函数
    
        //------------------GIC中断设置------------------//
        ICDISER.ICDISER2 |= (1 << 7); 
        ICDIPTR.ICDIPTR17 = (ICDIPTR.ICDIPTR17 & (~(0xff << 24))) | (1 << 24); 
    
        ICDDCR = 1; 
        CPU0.ICCICR = 1; 
    }

    作定时器中断时,只须设置PWM.TCNTB2初值,确定一个计时的长度,自减到0触发中断即可。无需设置占空比

  • Timer 2中断处理代码(code)
    void (*fun_p[160])(void);
    
    void do_irq(void) //Timer定时中断也属IRQ,依旧调用do_irq()
    {
        int irq_number;
        irq_number = CPU0.ICCIAR & 0x3ff; 
        printf("irq:%d\n", irq_number);
    
        (*fun_p[irq_number])(); 
    
        CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_number; 
        //CPU0.ICC关闭对57号中断源的响应
    }
    
    void timer2_int(void)
    {
        printf("timer2\n"); //每1s触发一次中断,打印信息
    
        PWM.TINT_CSTAT = (PWM.TINT_CSTAT & (~(0b11111 << 5))) | (1 << 7);
        ICDICPR.ICDICPR2 = (1 << 7);
    }
    

    定时器中断也属IRQ,一样进入do_irq()处理,再调用timer2_int()

2)用Timer 2中断处理按键消抖

  • 按键的外部中断初始化函数(code)
    void init_key()
    {
        /*gpx1_1 >> xeint_9 >> eint[9] >> 25  57  ¨C  EINT[9]*/
        GPX1.CON = (GPX1.CON & (~(0xf << 4))) | (0xf << 4);//配置GPIO端口为接收中断状态
        //配置中断源相关寄存器
        EXT_INT41_CON = (EXT_INT41_CON & (~(0xf << 4))) | (0x2 << 4);
        EXT_INT41_FLTCON0 |= (1 << 15);
        EXT_INT41_FLTCON0 &= ~(1 << 14); 
        EXT_INT41_MASK &= ~(1 << 1);
    
        fun_p[57] = key2_int;
    
        //日常GIC中断控制器设置
        ICDISER.ICDISER1 |= (1 << 25); //打开57号中断控制
        ICDIPTR.ICDIPTR14 = (ICDIPTR.ICDIPTR14 & (~(0xff << 8))) | (0b00000001 << 8); 
        //对应57号中断,选择CPU0处理
        ICDDCR = 1; //开中断混合器,等待外设中断触发
        CPU0.ICCICR = 1; //使能中断信号发送给CPU0
    }

    main()中须添加init_key();,然后死循环等待中断触发

  • Timer 2初始化函数(计时消抖)
    void init_timer2(int ms) 
    {
        //-----------------Timer2--------------------//
        PWM.TCFG0 = (PWM.TCFG0 & (~(0xff << 8))) | (99 << 8); // 100M / 100 = 1MHz
        PWM.TCFG1 = (PWM.TCFG1 & (~(0xf << 8))) | (0b0000 << 8); // 1M / 1 = 1MHz
    
        PWM.TCNTB2 = 1000 * ms; //可传参设置定时量
        PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b1010 << 12); 
        PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b0001 << 12); 
        //必须关闭自动装载,按键触发中断后,只须一轮计时
        PWM.TINT_CSTAT |= (1 << 2);
    
        fun_p[71] = timer2_int;
        /* 39  71  ¨C  TIMER2*/
        ICDISER.ICDISER2 |= (1 << 7); 
        ICDIPTR.ICDIPTR17 = (ICDIPTR.ICDIPTR17 & (~(0xff << 24))) | (0b00000001 << 24); 
        ICDDCR = 1;
        CPU0.ICCICR = 1; 
    }
  •  中断处理函数
    void (*fun_p[160])(void);//函数指针数组,存放各个中断源处理函数
    
    void do_irq(void) 
    {
        int irq_number;
        irq_number = CPU0.ICCIAR & 0x3ff; 
        printf("irq:%d\n", irq_number);
    
        (*fun_p[irq_number])();
    
        CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_number;
        //CPU0.ICC关闭对71号中断源的响应
    }
    
    void key2_interrupt(void) 
    {
        init_timer2(20);
    
        EXT_INT41_PEND = (1 << 1); //清除中断源
        ICDICPR.ICDICPR1 = (1 << 25); //清除ICD对中断响应
    }
    
    void timer2_interrupt(void) 
    {
        printf("timer2\n");
        if (0 == (GPX1.DAT & (1 << 1)))
                printf(">>>>>>>>>>>key2\n");
        PWM.TINT_CSTAT = (PWM.TINT_CSTAT & (~(0b11111 << 5))) | (1 << 7);//清除中断状态
        ICDICPR.ICDICPR2 = (1 << 7); //清除ICD对中断响应
    }

    程序执行过程中,按键按下触发 57 号外部中断,进入do_irq()后调用按键中断处理函数key2_interrupt()
    key2_interrupt()中初始化了Timer 2定时中断,开始计时,并且按键中断响应结束;
    等待 n ms后触发Timer 2定时中断,再次进入do_irq()调用timer2_interrupt(),打印信息。



5、Watchdog Timer

  • Watchdog Timer定时喂狗,使整个硬件重启

    两级分频器,WTDATWTCNT、复位信号生成器
    WTCONWatchdog timer control register
    WTDATWatchdog Timer Data
    WTCNTWatchdog Timer Counter
    WTCLRINTWatchdog timer interrupt clear register
  • 定时重启 code

    int i = 10000;
    
    /*led5  GPX3_5*/
    GPF3.CON = (GPF3.CON & (~(0xf << 20))) | (0x1 << 20);
    
    //两级分配系数:255、128,最后为3khz
    WDT.WTCON = (WDT.WTCON & (~(0xff << 0))) | (0xff39 << 0);
    WDT.WTCNT = 6000;//计数从6000开始减,结束时过去2秒
    
    //正常情况下,看门狗计数减不到0循环就结束了,不会触发喂狗
    //但最后i = 10000,延时很长可以等到喂狗触发,硬件重启
    while (1)
    {
        WDT.WTCNT = 6000;
    
        GPF3.DAT ^= (1 << 5);
        mydelay_ms(500);
        GPF3.DAT ^= (1 << 5);
        mydelay_ms(500);
    
        GPF3.DAT ^= (1 << 5);
        mydelay_ms(i);
    }
  • Watchdog Timer定时器中断

    一般来说不会用此定时器中断



6、RTC实时时钟

  • 基本功能

    自带Alarm FunctionTick Time Interrupt
    Supports BCD Number支持BCD码格式的年月日时间
    Supports Leap Year Generator支持闰年发生器
    Supports Independent Power Pin (RTCVDD)
    Supports millisecond tick time interrupt for RTOS kernel time tick.
  • RTC实时时钟的时间显示

    用BCD码配置初始时间信息,启动RTC时间开始走

    int main(void)
    {
        int sec,min,hour,week,day,mon,year;
    
        RTCCON = (RTCCON & (~(0xff << 0))) | (0b0001 << 0);
        //you can change the BCD time count setting开启时间设置功能
    
        RTC.BCDSEC = 0x48;
        RTC.BCDMIN = 0x59;
        RTC.BCDHOUR = 0x04;
        RTC.BCDWEEK = 0x3;
        RTC.BCDDAY = 0x22;
        RTC.BCDMON = 0x10;
        RTC.BCDYEAR = 0x016;
    
        RTCCON = RTCCON & (~(0xff << 0));//关闭时间设置功能
    
        while(1)
        {
            printf("%x-%x-%x week:%x %x:%x:%x\n",
                    RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,
                    RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);
        }
        return 0; // mov pc,lr  bx lr
    }
  • RTC定时闹钟

    本质是定时中断的闹钟系统

    void do_irq(void) 
    {
        int irq_number;
        irq_number = CPU0.ICCIAR & 0x3ff; 
        printf("irq:%d\n", irq_number);
    
        (*fun_p[irq_number])();
    
        CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_number; 
    }
    void alarm_int(void)
    {
        printf("alarm\n");
    
        RTCINTP = (1 << 1);
        ICDICPR.ICDICPR2 = (1 << 12);
    }
    int main(void) 
    {
        int i = 500;
    
        //依旧重设初始时间线
        RTCCON |= 1;
        RTC.BCDYEAR = 0x016;//(0 << 8)|(1 << 4)|(6 << 0);
        RTC.BCDMON = 0x08;
        RTC.BCDDAY = 0X31;
        RTC.BCDWEEK = 0X7;
        RTC.BCDHOUR = 0X23;
        RTC.BCDMIN = 0X59;
        RTC.BCDSEC = 0X55;
        RTCCON &= ~1;
    
        RTCALM.SEC = 0x2;//每分钟的第二秒触发中断
        RTCALM.ALM |=  (1 << 6) | (1 << 0);
        //  44  76  RTC_ALARM
        fun_p[76] = alarm_int;
    
        ICDISER.ICDISER2 |= (1 << 12); 
        ICDIPTR.ICDIPTR19 = (ICDIPTR.ICDIPTR19 & (~(0xff << 0))) | (0b00000001 << 0); 
        ICDDCR = 1; 
        CPU0.ICCICR = 1; 
    
        while(1){
            printf("2%03x-%02x-%02x week:%x %02x:%02x:%02x\n",
            RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,
            RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);
    
            mydelay_ms(500);
        }
    
        return 0; // mov pc,lr  bx lr
    }
    



7、ADC模数转换器

  • KEY Features of ADC for motor control

    Resolution: 10-bit / 12-bit (optional)
    Differential Nonlinearity Error: ± 2.0 LSB (Max.)
    Integral Nonlinearity Error: ± 4.0 LSB (Max.)
    Top Offset Error : 0 ~ + 55 LSB
    Bottom Offset Error : 0 ~ - 55 LSB
    Maximum Conversion Rate: 1 MSPS
    Low Power Consumption
    Power Supply Voltage: 1.8V (Typ.), 1.0V (Typ., Digital I/O Interface)
    Analog Input Range: 0 ~ 1.8V
    samsung / david.pang at 14:21,2012.05.07

  • 寄存器

    ADCCONADC Control Register
    ADCDLYADC Start or Interval Delay Register
    ADCDATADC Conversion Data Register
    CLRINTADCClear ADC Interrupt
    ADCMUXSpecifies the Analog input channel selection
  • ADC采集可调电阻的电压值code

    int main(void)
    {
        int value;
    
        ADCCON = (ADCCON & (~(0xf << 0)));
        ADCCON = (ADCCON & (~(0xff << 6)))| (99 << 6);
        ADCCON |= (1 << 14);
        ADCCON |= (1 << 16);
        ADCMUX = 0b0011;
    
        while(1)
        {
            ADCCON |= 1;
            printf("---\n");
            if((ADCCON & (1 << 15)) != 0){
                value = ADCDAT & 0xfff;
                printf(">>>>>>> value: %d\n",value);
            }
            mydelay_ms(500);
        }
    
        return 0; // mov pc,lr  bx lr
    }
    

    特别的,ADC有两种开启方式。
    ADCCON寄存器中

    • ENABLE_START = 1 ,
      A/D conversion starts and this bit is automatically cleared after the start-up.

      所以每次采样都需要使能一次

    • READ_START读启动,必须只读位ECFLG = 1才可启动,
      所以设置读启动后,要先象征性读一次ECFLG才可启动采样



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值