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)
{
PWM.TCFG0 = (PWM.TCFG0 & (~(
0xff <<
8))) | (
99 <<
8);
PWM.TCFG1 = (PWM.TCFG1 & (~(
0xf <<
8))) | (
0b0000 <<
8);
PWM.TCNTB2 =
1000000;
PWM.TCON = (PWM.TCON & (~(
0xf <<
12))) | (
0b1010 <<
12);
PWM.TCON = (PWM.TCON & (~(
0xf <<
12))) | (
0b1001 <<
12);
PWM.TINT_CSTAT |= (
1 <<
2);
fun_p[
71] = timer2_int;
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)
{
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 timer2_int(
void)
{
printf(
"timer2\n");
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.CON = (GPX1.CON & (~(
0xf <<
4))) | (
0xf <<
4);
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;
ICDISER.ICDISER1 |= (
1 <<
25);
ICDIPTR.ICDIPTR14 = (ICDIPTR.ICDIPTR14 & (~(
0xff <<
8))) | (
0b00000001 <<
8);
ICDDCR =
1;
CPU0.ICCICR =
1;
}
main()中须添加init_key();,然后死循环等待中断触发
Timer 2初始化函数(计时消抖)
void init_timer2(
int ms)
{
PWM.TCFG0 = (PWM.TCFG0 & (~(
0xff <<
8))) | (
99 <<
8);
PWM.TCFG1 = (PWM.TCFG1 & (~(
0xf <<
8))) | (
0b0000 <<
8);
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;
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;
}
void key2_interrupt(
void)
{
init_timer2(
20);
EXT_INT41_PEND = (
1 <<
1);
ICDICPR.ICDICPR1 = (
1 <<
25);
}
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);
}
程序执行过程中,按键按下触发 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;
GPF3.CON = (GPF3.CON & (~(
0xf <<
20))) | (
0x1 <<
20);
WDT.WTCON = (WDT.WTCON & (~(
0xff <<
0))) | (
0xff39 <<
0);
WDT.WTCNT =
6000;
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);
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;
}
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;
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);
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;
}
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
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;
}
特别的,ADC有两种开启方式。 在ADCCON寄存器中
ENABLE_START = 1 , A/D conversion starts and this bit is automatically cleared after the start-up. 所以每次采样都需要使能一次
READ_START读启动,必须只读位ECFLG = 1才可启动, 所以设置读启动后,要先象征性读一次ECFLG才可启动采样