定时器中断---那些年我们一起玩mini2440(arm9)裸机

(时钟体系)

时钟概念:

★时钟脉冲:一个按一定电压幅度,一定时间间隔连续发出的脉冲信号;

★时钟频率:在单位时间(如:1秒)内产生的时钟秒冲数;

时钟的作用:

时钟信号是时序逻辑的基础,它用于决定逻辑单元中的状态何时更新。数字芯片中众多的晶体管都工作在开关状态,它们的导通和关断动作无不是按照时钟信号的节奏进行的。

时钟的作用(简洁版)

系统中的设备需要有个时间来和它进行同步—即靠时钟!

时钟的产生-晶振

晶振:晶体振荡器,是用石英晶体精密切割做成。

优点:振荡频率非常稳定;振荡频率很准确;结构简单、噪声低。

缺点:生产成本高,交货周期较长,不利于客户加快产品上市时间,而且难以获得非常标准的频率。

时钟产生-PLL

PLL:(锁相环)合成器是一种更为复杂的系统时钟源。通过PLL合成器需要一个外部晶体并包含一个能够对晶体的特定频率加倍或分频的集成锁相环PLL电路。

S3C2440时钟体系

S3C2440的主时钟晶振来自外部晶振(XTIPLL),或者是外部时钟(EXTCLK)。时钟生成器包含了一个振荡器(振荡放大器),其连接外部晶振,可以产生需要的高频,通过引脚OM[3:2]来决定时钟源时Crystal还是EXTCLK.

S3C2440时钟体系

S3C2440有两个PLL:(1)MPLL和(2)UPLL

UPLL专用于USB设备。

MPLL 用于CPU及其他外围器件。

通过MPLL会产生三个部分的时钟频率:FCLK、HCLK、PLCK.

FCLK:用于CPU核;

HCLK:用于AHB(常用于高速外设)总线的设备,比如:SDRAM;

PCLK:用于APB(常用于低速外设)总线的设备,比如:UART.

时钟启动流程:

1.上电几毫秒后,外部晶振输出稳定,FCLK=外部晶振频率(12MHZ),nRESET

信号恢复高电平后,CPU开始执行命令。

 

2.在设置MPLL的几个寄存器后,需要等待一段时间(Lock Time),MPLL的输出才稳定。在这段时间(Lock Time)内,FCLK停振,CPU停止工作。

Lock Time的长短由寄存器LOCKTIME设定。

 

3.Lock Time之后,MPLL输出正常,CPU工作在新的FCLK(如:400MHZ)下。

寄存器:

设置S3C2440的时钟频率就是设置相关的几个寄存器:

1.LOCKTIME寄存器

2.MPLLCON寄存器

3.CLKDIVN寄存器

 

寄存器-LOCKTIME

MPLL启动后需要等待一段时间(Lock Time),使得其输出稳定。

位[31:16]用于UPLL,

位[15:0]用于MPLL.

使用缺省值0xffff ffff

寄存器-MPLLCON

该寄存器用于设置FCLK(cpu的时钟频率)与Fin的倍数(Fin:输入的时钟频率)

位[19:12]的值称为MDIV

位[9:4]的值称为PDIV

位[1:0]的值称为SDIV

FCLK与Fin的计算关系式如下:

MPLL(FCLK) = (2*m*Fin)/(p*2^s)

其中:m= MDIV+8  ,p=PDIV+2 , s= SDIV

寄存器-CLKDIVN

该寄存器用于设置FCLK、HCLK、PCLK三者的比例

★  HDIVN:位[2:1],用来设置HCLK与FCLK比例关系

★  PDIVN:位[0],用来设置PCLK与HCLK比例关系

 

例如:

FCLK:HCLK:PCLK=4:2:1

FCLK=400MHZ(主频)

HCLK=200M

PCLK=100M

巧计,速记2图:

S3C2440定时器

S3C2440共有5个16位的定时器。其中定时器0、1、2、3有PWM功能,他们都有一个输出引脚,可以通过定时器来控制引脚周期性的高、低电平变化;

定时器4没有输出引脚。

S3C2440定时器

定时器部件的时钟源为--PCLK,(经过两次分频)

首先通过两个8位的预分频器降低频率:定时器0、1共用第一预分频器,

定时器2、3、4公用第二个预分频器。

再次预分频器的输出将进入第二级分频器,它们输出5种频率的时钟:2分频、4分频、8分频、16分频或者外部时钟TCLK0、TCLK1,每个定时器的工作时钟也可以从这5种频率中选择。

定时器初始化:步骤:

1.定时器时钟频率

(定时器的时钟频率需要经过两次的分频)例如:定时器的时钟频率50--表示:每一秒钟把定时器的初始值减去50;

2.设置定时器计数值;

--即设置定时器的初始值(比较值为0)

3.设置中断处理函数;--即定时器到时间时去处理什么函数

定时器输出时钟频率 =PCLK/{prescaler value+1} /{divider value}

{prescaler  value} =0 ~255 (第一次预分频通过TCFG0设置)

{divider value} = 2, 4, 8, 16 (第二次预分频通过TCFG1设置)

TCMPB0:定时器n的比较值

TCNTB0:初始计数值(放到TCNT0后TCNT0会自动减一直到减到== TCMPB0)

之后设置TCON会自动重新装载TCMPB0和TCNTB0再次重新计数

 

定时器工作流程

1.      程序初始化,设置TCMPBn、TCNTBn这两个寄存器,它们表示定时器n的比较值、初始计数值。

2.      设置TCON寄存器定时器n,这时TCMPBn、TCNTBn的值将被装入其内部寄存器TCMPn、TCNTn中。在定时器n的工作频率下,TCNTn开始减一计数,其值可以通过读取TCNTOn寄存器得知。

3.      当TCNTn的值等于TCMPn的值时,定时器n的输出管脚TOUTn反转;TCNTn继续减一计数。

4.      当TCNTn的值到达0时,器输出管脚TOUTn再次反转,并触发定时器n的中断。

5.      当TCNTn的值到达0时,如果TCON寄存器中将定时器n设为“自动加载”,则TCMPB0和TCNTB0寄存器的值被自动装入TCMP0和TCNT0寄存器中,下一个计数流程开始。

 

  1. #define   GLOBAL_CLK           1
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "def.h"
  5. #include "option.h"
  6. #include "2440addr.h"
  7. #include "2440lib.h"
  8. #include "2440slib.h"
  9. #include "mmu.h"
  10. #include "profile.h"
  11. #include "memtest.h"
  12. void Timer0_init(void);
  13. static void __irq IRQ_Timer0_Handle(void);
  14. void Set_Clk(void);
  15. static void cal_cpu_bus_clk(void);
  16. void Led1_init(void);
  17. void Led1_run(void);
  18. /*************************************************
  19. Description    : 延时函数
  20. **************************************************/
  21. void delay(int times)
  22. {
  23. int i,j;
  24. for(i=0;i<times;i++)
  25. for(j=0;j<400;j++);
  26. }
  27. /*************************************************
  28. Description    : 主功能函数
  29. **************************************************/
  30. void Main(void)
  31. {
  32. Set_Clk();
  33. MMU_Init();
  34. //Uart_Init(0,115200);
  35. //Uart_Select(0);
  36. Led1_init();
  37. Timer0_init();
  38. while(1);
  39. }
  40. /*************************************************
  41. Description    : 定时器的初始化
  42. **************************************************/
  43. void Timer0_init(void)
  44. {
  45. //Timer 0 init
  46. rTCFG0 = 49;              //pclk/(49+1)
  47. rTCFG1 = 0x03;            //16分频=62500HZ
  48. rTCNTB0 = 62500/2;          //TCNTB0[15:0]=计数值
  49. rTCMPB0 = 0;
  50. rTCON |=(1<<1);           //将计数值装入TCNTB0、TCMPB0
  51. rTCON =0x09;
  52. rPRIORITY = 0x00000000;     // 默认优先级
  53. rINTMOD = 0x00000000;       // 默认优先级
  54. ClearPending(BIT_TIMER0);
  55. /*当达到0.5秒时,执行中断函数IRQ_Timer0_Handle */
  56. pISR_TIMER0 = (U32)IRQ_Timer0_Handle;
  57. EnableIrq(BIT_TIMER0);
  58. }
  59. /*************************************************
  60. Description    : 定时器0的中断处理函数
  61. **************************************************/
  62. static void __irq IRQ_Timer0_Handle(void)
  63. {
  64. ClearPending(BIT_TIMER0);  //清中断
  65. Led1_run();
  66. }
  67. /*************************************************
  68. Description    : 设置CPU的时钟频率
  69. MDIV: 19~12  所以MDIV是92;
  70. PDIV : 9~4  所以PDIV是4
  71. SDIV : 1~0  所以SDIV是1
  72. 根据公式:FCLK与Fin的计算关系式如下:
  73. MPLL(FCLK) = (2*m*Fin)/(p*2^s)
  74. 其中:m= MDIV+8  ,p=PDIV+2 , s= SDIV
  75. 所以:MPLL(FCLK) = (2*100*12)/(3*2^1)=400
  76. **************************************************/
  77. void Set_Clk(void)
  78. {
  79. int i;
  80. U8 key;
  81. U32 mpll_val = 0 ;
  82. i = 2 ;                  //don‘t use 100M!
  83. //boot_params.cpu_clk.val = 3;
  84. switch ( i ) {
  85. case 0:    //200
  86. key = 12;
  87. mpll_val = (92<<12)|(4<<4)|(1);
  88. break;
  89. case 1:    //300
  90. key = 13;
  91. mpll_val = (67<<12)|(1<<4)|(1);
  92. break;
  93. case 2:    //400
  94. key = 14;
  95. mpll_val = (92<<12)|(1<<4)|(1);
  96. break;
  97. case 3:    //440!!!
  98. key = 14;
  99. mpll_val = (102<<12)|(1<<4)|(1);
  100. break;
  101. default:
  102. key = 14;
  103. mpll_val = (92<<12)|(1<<4)|(1);
  104. break;
  105. }
  106. //init FCLK=400M, so change MPLL first
  107. ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);   //set the register--rMPLLCON
  108. ChangeClockDivider(key, 12);    //the result of rCLKDIVN [0:1:0:1] 3-0 bit//经过CLKDIVE设置FCLK、HCLK、PCLK三者之间的关系
  109. cal_cpu_bus_clk();    //HCLK=100M   PCLK=50M
  110. }
  111. /*************************************************
  112. Description    : 设置PCLK\HCLK\FCLK的频率
  113. 寄存器-CLKDIVN
  114. 该寄存器用于设置FCLK、HCLK、PCLK三者的比例
  115. ★   HDIVN:位[2:1],用来设置HCLK与FCLK 比例关系
  116. ★   PDIVN:位[0],用来设置PCLK与HCLK 比例关系
  117. **************************************************/
  118. static void cal_cpu_bus_clk(void)
  119. {
  120. static U32 cpu_freq;
  121. static U32 UPLL;
  122. U32 val;
  123. U8 m, p, s;
  124. val = rMPLLCON;
  125. m = (val>>12)&0xff;
  126. p = (val>>4)&0x3f;
  127. s = val&3;
  128. //(m+8)*FIN*2 不要超出32位数!
  129. FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  FIN=12000000
  130. val = rCLKDIVN;
  131. m = (val>>1)&3;
  132. p = val&1;
  133. val = rCAMDIVN;
  134. s = val>>8;
  135. switch (m) {
  136. case 0:
  137. HCLK = FCLK;
  138. break;
  139. case 1:
  140. HCLK = FCLK>>1;
  141. break;
  142. case 2:
  143. if(s&2)
  144. HCLK = FCLK>>3;
  145. else
  146. HCLK = FCLK>>2;
  147. break;
  148. case 3:
  149. if(s&1)
  150. HCLK = FCLK/6;
  151. else
  152. HCLK = FCLK/3;
  153. break;
  154. }
  155. if(p)
  156. PCLK = HCLK>>1;
  157. else
  158. PCLK = HCLK;
  159. if(s&0x10)
  160. cpu_freq = HCLK;
  161. else
  162. cpu_freq = FCLK;
  163. val = rUPLLCON;
  164. m = (val>>12)&0xff;
  165. p = (val>>4)&0x3f;
  166. s = val&3;
  167. UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
  168. UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
  169. }
  170. /*************************************************
  171. Description    : 初始化Led1
  172. **************************************************/
  173. void Led1_init(void)
  174. {
  175. rGPBCON &= ~(0x3<<10);
  176. rGPBCON |=  (0x1<<10);
  177. }
  178. /*************************************************
  179. Description    : 运行Led1
  180. **************************************************/
  181. void Led1_run(void)
  182. {
  183. //rGPBDAT = rGPBDAT^(0x1<<5);
  184. if(rGPBDAT &(1<<5))
  185. rGPBDAT &=~(1<<5);
  186. else
  187. rGPBDAT |=(1<<5);
  188. }
时间: 2024-10-04 15:51:45

定时器中断---那些年我们一起玩mini2440(arm9)裸机的相关文章

按键中断---那些年我们一起玩mini2440(arm9)裸机

ARM中断控制系统 按键驱动程序设计 一.Arm中断控制系统 1.查询方式 程序不断地查询设备的状态,并做出相应的反应.该方式实现比较简单,常用在比较单一的系统中,比如:一个温控系统中可以实用查询的方式不断检测温度变化. 特点:实现简单:但CPU利用率很低,不适合多任务的系统. 2.中断方式 当事件发生时,硬件会设置某个寄存器:CPU在每执行完一个指令时,查看这个寄存器,如果所关注的事件发生了,则中断当前程序,跳转到一个固定的地址处理这个事件,处理完后返回到被中断的程序中继续运行. 特点:实现相

uart串口发送---那些年我们一起玩mini2440(arm9)裸机

Uart工作原理: 数据通信方式为:并行通信与串行通信两种: §并行通信:利用多条数据线将数据的各位同时传送. 它的特点是:传输速度快,是用于短距离通信: §串行通信:利用一条数据线将数据一位位地顺序传送. 特点是通信线路简单,利用简单的线缆就实现通信,低成本,是用于远距离通信.   异步通信: ª异步通信:以一个字符为传输单位,通过两个字符间的时间间隔是不固定的,然而同一字符中的两个相邻位之间的时间间隔是固定的. ª通信协议:是指通信双方约定的一些规则.在异步通讯时,对数据格式有如下约定:规定

AD电阻转换---那些年我们一起玩mini2440(arm9)裸机

ADC驱动程序设计 ADC:模/数转换器. 一种将模拟信号转换成数字信号的装置: DAC:数/模转换器. 一种将数字信号转换成模拟信号的装置. 模拟信号转换为数值信号的步骤: 1.     取值: 2.     量化: 3.     编码: S3C2440ADC S3C2440芯片内部共有8路A/D转换通道AIN0~AIN7,但是转换器只有一个. 转换精度为10位,故转换后的值最小时会接近0,最大时会接近1024. 最大的转换率在2.5MHZ转换时钟下能达到500KSPS(每秒采样5000千次)

79.ZYNQ内部私有定时器中断

上篇文章实现了了PS接受来自PL的中断,本片文章将在ZYNQ的纯PS里实现私有定时器中断.每个一秒中断一次,在中断函数里计数加1,通过串口打印输出. *本文所使用的开发板是Miz702(兼容zedboard) PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2* 中断原理 中断对于保证任务的实时性非常必要,在ZYNQ里集成了中断控制器GIC(Generic Interrupt Controller).GIC可以接受I/O外设中断IOP和PL中断,将这些中断发给CP

Arduino101学习笔记(十二)&mdash;&mdash; 101定时器中断

一.API 1.开定时器中断 //********************************************************************************************* //函数名称:CurieTimerOne.start(int timerPeriodUsec, userCallBack) //输入参数:timerPeriodUsec:: 多少微妙产生中断 // userCallBack : 中断函数 //函数返回:无 //函数功能:开定时器

定时器中断各个寄存器含义

中断寄存器,定时器/计数器相关寄存器本身或者相关位用来做初始化,中断函数的内容主要是体现发生中断后所需要的操作(在中断函数内写代码). 1.中断允许寄存器IE 图1.中断寄存器IE 中断寄存器用来设定各个中断源的打开和关闭,IE在特殊功能寄存器中,字节地址为A8H,位地址(由低位到高位)分别是A8H~AFH,该寄存器运行位寻址,即可对该寄存器的每一位进行单独操作.单片机复位时IE全部被清零.下面列举各位的在不同状态下的具体含义: EA-------全局中断允许位 EA = 1,打开全局中断控制,

stm32通用定时器中断问题

在使用stm32的通用定时器定时中断的时候,发现定时器在完成初始化配置后,定时器UIF位会立刻置位,导致在使能中断后,程序会立刻进入定时器中断. 如果设计代码时不希望定时器配置完成后,立刻进入中断,可以在定时器配置完成后,立刻清除UIF标志位(TIMx->SR &= 0xFFFE) ,再使能定时器更新中断.比如用库函数这么写: TIM_ClearITPendingBit(TIM4, TIM_IT_Update  ); TIM_ITConfig(TIM4,TIM_IT_Update,ENABL

用定时器中断,单片机中断处理时间大于定时器定时时间会怎样?

如果是不同的中断类型是可以根据优先级嵌套,如果是同一中断类型(如题), 有三种结果:1.马上进入新的中断处理(中断嵌套) 2.等待中断处理完再进入新的中断处理 3.出错. 单片机中断处理时间大于定时器定时时间,在下次中断时间到时,因为中断是同一类型.同一优先级,所以不会马上进入新的中断处理. 而是在本次中断处理结束后,单片机又马上进入新的定时器中断函数,主函数中的语句可能会没有机会运行下去,会影响后面中断的实时性.所以答案为2. 如果为了避免中断嵌套(同一优先级不会发生),在中断处理中人为的在进

奶爸业余单片机学习之:定时器中断的使用方法——进入中断TF0(TF1)值硬件自动重置

/*============定时器中断的使用方法—---TF0(TF1)值硬件重置法======== 第一:打开总中断第二:打开定时器 中断第三:设置特殊功能寄存器TMOD,配置好工作模式. 第四:设置计数寄存器TH0和TL0的初值. 第五:设置TCON,通过TR0置1来让定时器开始计数.*/ //LED由三极管及73HC138控制//用定时器0实现亮与灭之间的1秒延时 # include <reg52.h> sbit led2 = P0^0; sbit addr0 = P1^0;sbit a