ARM

    xiaoxiao2025-01-10  14

    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定时喂狗,使整个硬件重启

    两级分频器,WTDAT和WTCNT、复位信号生成器

    WTCON:Watchdog timer control register

    WTDAT:Watchdog Timer Data

    WTCNT:Watchdog Timer Counter

    WTCLRINT:Watchdog 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 Function和Tick 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

    寄存器

    ADCCON:ADC Control Register

    ADCDLY:ADC Start or Interval Delay Register

    ADCDAT:ADC Conversion Data Register

    CLRINTADC:Clear ADC Interrupt

    ADCMUX:Specifies 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才可启动采样


    转载请注明原文地址: https://ju.6miu.com/read-1295331.html
    最新回复(0)