一起学mini2440裸机开发(五)--定时器0的基础实验

合集下载

TQ2440之定时器中断0——volatile关键字的重要作用

TQ2440之定时器中断0——volatile关键字的重要作用

TQ2440之定时器中断0——volatile关键字的重要作用
近日,在学习《ARM 处理器裸机开发实战机制而非策略》一书,在
TQ2440 开发板上,按照书中实例以及光盘配套程序源代码进行Timer0 中断试验,编译成功后烧写到开发板上,没有任何反应,反复检查代码,一直没有找
出哪里有问题,就是到开发板上没有预期效果。

(让人纠结的很)最终参考了
TQ2440 之定时器中断0 的程序代码,编译成功后,烧写到板子上,惊喜出现了。

绝对是久旱逢甘霖的感觉,在这里对TQ2440 之定时器中断0 的原创作者
表示感谢。

后来,经过代码对比,发现两个可疑的地方:
(1)之前的Timer0 的初始化中没有rTCMPB0 = 0;这条语句。

而后来参考TQ2440 之定时器中断0 中的代码是有这条语句的。

后来经过验证,这里无关紧要。

(2)之前对于Led1 灯亮灭控制语句是放在Main 函数中的:
而后来参考的TQ2440 之定时器中断0 中是将这段代码放在了中断服务函数
当中:
不过,按道理来讲,这个地方不加修改应该是可以的。

暂且先总结这样一条经验吧:如果一些控制语句(比如控制Led 灯亮、灭)
是要通过中断来驱动执行,那么最好将这些控制语句放在中断服务程序(也叫
中断处理程序)中。

如果只是在中断服务程序中控制一个全局变量(比如flag),。

裸机定时器中断控制LED灯程序设计实验报告

裸机定时器中断控制LED灯程序设计实验报告

裸机定时器中断控制LED灯程序设计一、实验要求:基于mini2440开发板,设计裸机定时器中断控制LED灯闪烁的程序。

二.设计目的1,巩固学习嵌入式软件方面的基本知识,进一步熟悉基本概念。

2,熟练常用控件,文件,图形等方面的操作了解基本的流程。

3,运用所用学的嵌入式知识,编写出较为实用的小软件,增进对一些实际问题的软,硬件知识的掌握。

4,培养查阅资料,独立思考问题的能力。

三. 实验步骤:四.基本思路及关键问题的解决方法;基本思路:1. 按照步骤程序设计原理说明,使用”CodeWarrior for ARM Developer Suite”软件编写程序并进行编译,建立一个新的文件单击【File】菜单中的【New File】选项,然后出现下面的对话框,输入文件名(加上后缀“.c”),单击保存按钮,在编译过程中如果出现错误,修改程序直到没有错误为止,编译过程中出现警告一般可以不必考虑,但特殊时也要通过修改程序消除警告。

程序编写完成后,将程序所在文件保存到2440test.mcp中,如图所示:2.用开发板测试程序代码:(1)首先设置开发板的拨动开关S2 为Nor Flash 启动,连接好附带的USB 线和电源(可以不必连接串口线)。

(2)设置超级终端(3)开机进入BIOS 模式,此时开发板上的绿色LED1 会呈现闪烁状态,其启动界面,如下图:输入”d”(4)安装USB 下载驱动(5)点击DNW 程序的“USB Port” “Transmit”,选择这个2440test.mcp文件,接着点“打开”,这样就开始下载了五.流程图及电路原理图1.绘制所需的流程图,如图所示:六.课程设计心得体会此次课程设计中我们的收获:我了解到了和小组成员合作的愉快,我意识到了知识的乐趣性,并感觉到当知识运用于实践的时候是一件多么幸福的事情。

我也发现自己的知识功底还远远不够。

平时不仅要将知识点理解掌握,还得勤动手做实验。

在以后的学习中我会更努力,在掌握理论知识的基础上,提高自己的动手能力。

一起学mini2440裸机开发(一)--第一个led灯点亮

一起学mini2440裸机开发(一)--第一个led灯点亮

一起学mini2440裸机开发(一)--第一个led灯点亮开发板:mini2440,NandFlash:K9F2G08U0B 256M大小,CPU:S3C2440A 。

开发环境:MDK4.11仿真器:Jlink v8这是我用csdn发表的第一个文章,之前使用过arm-linux-gcc裸机开发mini2440,但是很多函数什么的不能直接调用(我的技术问题),准备重新整理一下ARM裸机,整理好之后准备下一阶段学习。

关于软件MDK4.11和它的注册机,我传不上去,说是由于文件太大,又想要的直接加Q470868560要就行了。

下面开始我们的第一个LED灯的点亮程序吧!1、新建一个项目工程双击MDK图标进入开发环境,如下图,单击Project/New uVision Project,选择你要创建文档的位置,文档名为test,单击保存选择CPU为Samsung/S3C2440A,单击OK单击完OK按钮后,咱们先看一下原来的空test文件夹里多了什么文件,当然你也可以不用看,我是看看MDK到底是默认给咱们提供了什么方便,下图为单击OK后多出的文档很容易看出多出来一个test工程文档。

在上一步单击完OK后,会弹出下图,该图是为了让你选择是不是将Samsung S3C2440的启动代码复制添加的你的工程文档。

这段启动代码咱们以后分析,在这里先选择“是”选择“是”后,一个工程文档建好了,如下图所示。

你看上图,可以看到工程文档自动添加了S3C2440.s,这就是上一步选择“是”后自动添加的启动代码,咱们再看看test文件夹里多了什么文件。

很容易可以看出多了三个文件,其中一个就是S3C2440.s,这个代码很重要啊。

咱们现在先不管他,接着下一步。

2、新建一个文件。

选择File/New,新建一个文件。

将该文件保存并命名为test1,注意后面要加后缀.c,单击保存将test1.c文件添加到你的工程,对着Source Group1右击,选择“Add Files to Group "Source Group 1"...”选择刚才建立的test1.c,单击Add,该文件就被加到了工程中。

一起学mini2440裸机开发(四)--S3C2440定时器学习

一起学mini2440裸机开发(四)--S3C2440定时器学习

一起学mini2440裸机开发(四)--S3C2440定时器学习S3C2440定时器原理概述s3c2440有5个16位定时器,定时器0、1、2和3有脉冲宽度调制(PWM)功能,因此这4个定时器也被称为PWM定时器。

定时器4是一个内部的定时器,没有外部输出引脚。

定时器的时钟源是PCLK,定时器工作所需频率并不等于PCLK,还要进一步将PCLK 通过内部的分频器分频才能得到。

这里也可以看出外部设备所需的工作频率不一定等于它的时钟源。

其中,定时器0、1公用一个分频器,另外3个定时器公用一个分频器。

分频器输入信号经过第2级分频器进一步降低时钟频率,然后输出作为定时器工作的时钟。

下图为由PCLK得到定时器工作时钟的框图:虽然S3C2440定时器有5个,但是它们的工作原理都是相同的,只需要理解一个定时器的工作原理即可。

对于某一个定时器,其内部结构原理如图2所示。

寄存器TCMPBn和TCNTBn用于缓存定时器n的比较值和初始值;TCON用于控制定时器的开启与关闭;可以通过读取寄存器TCNTOn得到定时器的当前计数值。

注意图2所示的是PWM定时器,也就是定时器0-3,不包含定时器4,定时器4也没有外部输出引脚。

定时器工作原理概述:●首先,将定时器的比较值和初始值装入寄存器TCMPBn和TCNTBn中●然后,设置定时器控制寄存器TCON,启动定时器。

此时,TCMPBn和TCNTBn 中的值会加载到寄存器TCMPn和TCNTn中●此时,定时器会减1计数,即TCNTn进行减1计数,当TCMPn=TCNTn时,TOUTn引脚输出取反。

S3C2440定时器相关寄存器●定时器控制寄存器TCON由于各个定时器的工作原理相似,下面以定时器0为例进行讲解。

在定时器控制寄存器TCON中,位[3:0]用于控制定时器0,其含义如表1所示:位功能简述描述0开启/停止0:停止定时器1:开启定时器1手动更新0:未使用1:TCMPB0和TCNTB0中的值会加载到寄存器TCMP0和TCNT0中2输出控制0:当TCMP0=TCNT0时,TOUTO0引脚输出不翻转1:当TCMP0=TCNT0时,TOUTO0引脚输出翻转3自动加载0:自动加载1:当TCNTO0的值减到0时,TCMPB0中的值会加载到寄存器TCMPB0和TCNTB0中●定时器比较值缓存寄存器TCMPBn、计数值缓存寄存器TCNTBn这两个寄存器用于存储定时器的比较值初始值和计数值初始值。

实验3 定时器0

实验3 定时器0

实验3 定时器0和定时器1一、实验目的1、学会用C语言进行定时器应用程序的设计。

二、实验内容1、在同一个程序中实现:用定时器0的方式1实现第一个LED灯以1000ms间隔闪烁,用定时器1的方式1实现数码管前两位59秒循环计时。

三、实验步骤1、硬件连接(1)使用MicroUSB数据线,将实验开发板与微型计算机连接起来;(2)在实验开发板上,用数据线将相应接口连接起来;2、程序烧入软件的使用使用普中ISP软件将HEX文件下载至单片机芯片内。

查看结果是否正确。

四、实验结果——源代码#include <reg52.h>typedef unsigned int u16;typedef unsigned char u8;sbit led = P2^0;sbit LSA=P2^2;sbit LSB=P2^3;sbit LSC=P2^4;u16 t1;u16 t2;u8 sec;u8 DisplayData[2];u8 code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void Time0Init(){TMOD |= 0x01;TH0=0xFc;TL0=0x18;EA=1;ET0=1;TR0=1;}void Time1Init(){TMOD |= 0x10;TH1=0Xd8;TL1=0Xf0;EA=1;ET1=1;TR1=1;}void delay(u16 i){while(i--);}void datapros(){DisplayData[0]=smgduan[sec%10];DisplayData[1]=smgduan[sec/10]; }void DigDisplay(){u8 i;for(i=0;i<2;i++){switch(i){case 0:LSA=0;LSB=0;LSC=0;break;case 1:LSA=1;LSB=0;LSC=0;break;}P0=DisplayData[i];delay(100);P0=0x00;}}void main(){Time0Init();Time1Init();while(1);}void Time0() interrupt 1{TH0=0xFC;TL0=0x18;t1++;if(t1==1000){t1=0;led=~led;}}void Time1() interrupt 2{TH1=0Xd8;TL1=0Xf0;t2++;if(t2==100){t2=0;sec++;if(sec>=60){sec=0;}}datapros();DigDisplay();}五、实验体会——结果分析位定义P2.0、P2.2、P2.3、P2.4口,P2.0控制第一个LED灯,初始化定时器0,选择工作方式1,也就是16位定时/计数器,赋初值为1ms,编写定时器0中断函数,定义全局变量t1,当t1自增到1000即计数了1000次,每次1ms,重置定时器0,并使第一个LED灯状态翻转,实现第一个LED灯以1000ms间隔闪烁;定时器1初始化方式同定时器0,但初值为10ms,定义全局变量t2,当t2自增到100即计数100次每次10ms相当于1s时,使全局变量sec自增1,当sec 增加到第60s时,数码管重新以00开始计时,数码管段选保存在数组里,位选只有1和2位,因为只显示0-59s计数,通过循环选择。

mini2440上qtopia应用程序开发步骤(x86-qtopia版本)(精)

mini2440上qtopia应用程序开发步骤(x86-qtopia版本)(精)

FriendlyARM 在光盘中提供了开发 Qtopia-2.2.0的开发环境和软件, 因此只要对其中的软件好好加以利用就可以开发出能够在 mini2440上运行的程序,下面我把我自己开发经历做一个交流, 我相信在我们这群技术的热爱者中不乏高人和大牛, 所以我也是抛砖引玉, 如果有说的不对的请大家提出来,这样才能更好进步。

好,闲话不多说,进入正题,我先讲讲 FriendlyARM 中提供的开发环境和软件的作用:按照 FriendlyARM 文档安装所有软件后,可以发现 mini2440文件夹下包含了两个 qtopia 文件夹,一个是 x86-qtopia 另一个是 arm-qtopia ,对于这两个文件夹我是这么理解的, x86-qtopia 提供了我们在主机上开发 qtopia 的软件环境, 开发过 wince 的人都知道 SDK 的重要性,这里我们也可以把 x86-qtopia 理解为提供给我们的 SDK 或者说模拟器,只不过它的功能还要大的多,你可以使用里面的工具设计图形界面编译程序,并在 qvfb 中运行,它的存在就是为了方便我们开发 qtopia ; arm-qtopia 则是提供在目标机上运行软件的编译工具,但是一般地它不具有 qvfb ,所以这两个文件夹需要结合起来使用,才能达到最佳效果。

下面我来谈谈 x86-qtopia 的编程步骤,在这里我采用了比较繁琐的步骤,主要是讲一下流程,后面会提到比较简捷的方法。

主机环境:RedHat9编译工具:arm-linux-gcc-4.3.21、进入 x86-qtopia ,建立目标文件夹,即存放工程文件, .cpp.h 文件的文件夹2、设置开发环境,执行命令 # source qtopia-2.2.0-FriendlyARM/setQpeEnv3、创建工程 # progen -t app -o (工程名 .pro4、进入 qtopia-2.2.0-FriendlyARM/qt2/bin,启动 Qt designer # ./designer,即可以进行图形界面的设计5、将 .ui 文件存放在工程文件夹中6、生成 .h 和 .cpp 文件,运用 .ui 文件, # uic -o *.h *.ui # uic -o *.cpp -impl *.h *.ui7、在 .h 和 .cpp 文件中添加需要的代码8、编写 main.cpp9、修改 .pro 文件,为其中的 HEADERS= SOURCES= TARGET=添加文件, HEADERS 指头文件,若有多个用空格分隔 SOURCES 为源文件, TARGET 为目标文件,即最后生成的可执行文件名10、生成 Makefile(1查看环境变量, # echo $TMAKEPATH 查看结尾是否为 /qws/linux-generic-g++(2修改 tmake/lib/qws/linux-generic-g++/tmake.conf将 TMAKE_LINK=gcc和TMAKE_SHLIB=gcc改为 =g++(3生成 Makefile # tmake -o Makefile *.pro(4修改 Makefile 为 LIBS=添加 -lqtopia2 -lqtopia -lqpe11、编译 # make12、运行 # ./可执行文件名 -qws(不可少上面就是一般步骤,但是比较繁琐,个人觉得程序设计的重点应该放在对 .cpp和 .h 文件的编写,以及调试中错误的纠正所以下面我再把常用的,也是比较方便的方法介绍下1、进入 x86-qtopia ,建立工程目录2、将编写好的 .cpp .h拷贝至工程目录3、产生工程文件执行命令 # qmake -project4、修改 .pro 工程文件在文件最后架上 TARGET=可执行文件名5、拷贝 x86-qtopia 中例程 hello 中的脚本文件 build 至工程目录, 并执行# ./build, 该脚本已经将设置环境变量调用相应库生成 Makefile ,生成可执行文件写入其中。

定时器0的使用


- 专业电子技术交流社区 电子工程师网上家园 -
电子
第 3页
定时器 0 的使用
电子园
位。EA=1,CPU 开放中断;EA=0,CPU 禁止所有的中断请求。总允许 EA 好比一个总开关。 这里我们只需要将 ET0 和 EA 置位即可。
第五步是通过对 TCON 寄存器的操作来完成的。
各位定义如下: TF1:定时器 1 溢出标志位。当字时器 1 计满溢出时,由硬件使 TF1 置“1”,并且申请 中断。进入中断服务程序后,由硬件自动清“0”,在查询方式下用软件清“0”。 TR1:定时器 1 运行控制位。由软件清“0”关闭定时器 1。当 GATE=1,且 INT1 为高电 平时,TR1 置“1”启动定时器 1;当 GATE=0,TR1 置“1”启动定时器 1。 TF0:定时器 0 溢出标志。其功能及操作情况同 TF1。 TR0:定时器 0 运行控制位。其功能及操作情况同 TR1。 IE1:外部中断 1 请求标志。 IT1:外部中断 1 触发方式选择位。 IE0:外部中断 0 请求标志。 IT0:外部中断 0 触发方式选择位。 可见,我们只要将 TR0 置位即可。 第七步,我们需要编写自己的中断函数。 中断函数的格式如下: void 函数名(void) interrupt 中断代号{} 其中函数名是可以任意命名的,为了方便起见,我们在这里将其命名为 Timer0。后面 的终端代号根据不同类型的中断需要不同的赋值。其赋值所代表的中断类型如下:
void Timer0_Init(void); //定时器初始化
unsigned char ucCount;
//主函数 void main(void) {
- 专业电子技术交流社区 电子工程师网上家园 -
电子

关于mini2440的一个裸机程序

关于mini2440的一个裸机程序[html]view plaincopy1.<span style="font-size:18px;">/*2.*File : main.c3.*Description : When you press the key,4.* the LED will show the key_value of key by the binary5.* and produce the buzzer.6.*Author : Cong7.*Copyright : Cong8.*9.*10.*History11.*---------------------12.*Rev :0.013.*Date :2011/11/2614.*Creat.15.*--------------------16.*17.*18.*/19.20.//--------------------Include Files------------------------------------//21.#include "2440addr.h"22.#include "2440slib.h"23.24.25.//---------------------Define Valurable-------------------------------//26.27.#define GLOBAL_CLK 128.29.#define LED1_ON ~(1<<5)30.#define LED2_ON ~(1<<6)31.#define LED3_ON ~(1<<7)32.#define LED4_ON ~(1<<8)33.34.#define LED1_OFF (1<<5)35.#define LED2_OFF (1<<6)36.#define LED3_OFF (1<<7)37.#define LED4_OFF (1<<8)38.39.#define BEEP 040.41.#define LED1 1042.#define LED2 1243.#define LED3 1444.#define LED4 1645.46.#define KEY1 047.#define KEY2 648.#define KEY3 1049.#define KEY4 1250.#define KEY5 1451.#define KEY6 2252.53.//--------------------Function Prototype------------------------------//54.static void LEDKEY_port_init(void);55.static void Show_num(int num);56.static void Beep_run(void);57.static void delay(unsigned int times);58.static void __irq key_handler(void);59.60./*61.*62.*程序入口63.*/64.65.66.void Main(void)67.{68.LEDKEY_port_init();69.while(1)70.{71.72.}73.}74./*75.*===================Function========= =============76.* Name :Port_init77.* Discription :init the GPIO78.*================================== ===============79.*/80.static void LEDKEY_port_init(void)82.//初始化LED与BEEP所要用到的IO 用到的这五个端口都配置为输出83.rGPBCON &= ~((3<<BEEP)|(3<<LED1)|(3<<LED2)|(3< <LED3)|(3<<LED4));84.rGPBCON |= (1<<BEEP)|(1<<LED1)|(1<<LED2)|(1<<LE D3)|(1<<LED4);85.86.//初始化KEY所用的IO 所有的KEY端口都初始化为中断方式87.rGPGCON &= ~((3<<KEY1)|(3<<KEY2)|(3<<KEY3)|(3< <KEY4)|(3<<KEY5)|(3<<KEY6));88.rGPGCON |= (2<<KEY1)|(2<<KEY2)|(2<<KEY3)|(2<<KE Y4)|(2<<KEY5)|(2<<KEY6);89.90.//中断初始化EINT891.// rEXTINT1 &=~((0xf)|(0xf<<12)|(0xf<<20)|(0xf<<24 )|(0xf<<28)); //设置K1的低电平中断92.rEXTINT1 &=~0xfff0f00f;93.rEXTINT2 &=~(0xf<<12);94.rEINTPEND |=(1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<1 5)|(1<<19); //清除K1的中断标志95.rEINTMASK = ~((1<<8)|(1<<11)|(1<<13)|(1<<14)|(1< <15)|(1<<19)); //打开EINT8的中断使能96.97.pISR_EINT8_23 = (U32)key_handler;98.EnableIrq(BIT_EINT8_23);//外部中断8-23共用的中断位使能,与ClearPending对应99.}100.102.*===================Function========= =============103.* Name :Show_num104.* Discription :init the GPIO of Key105.*================================== ===============106.*/107.static void Show_num(int data)108.{109.if(data & 0x08) rGPBDAT = rGPBDAT&(LED4_ON);110.else rGPBDAT = rGPBDAT|(LED4_OFF);111.if(data & 0x04) rGPBDAT = rGPBDAT&(LED3_ON);112.else rGPBDAT = rGPBDAT|(LED3_OFF);113.if(data & 0x02) rGPBDAT = rGPBDAT&(LED2_ON);114.else rGPBDAT = rGPBDAT|(LED2_OFF);115.if(data & 0x01) rGPBDAT = rGPBDAT&(LED1_ON);116.else rGPBDAT = rGPBDAT|(LED1_OFF);117.}118.119./*120.*===================Function========= =============121.* Name :Beep_run122.* Discription :produce the buzzer123.*================================== ===============124.*/125.static void Beep_run(void)126.{127.rGPBDAT |= (0x1<<0);128.delay(50);129.rGPBDAT &= (0x0<<0);130.delay(50);131.}132.133./*134.*===================Function========= =============135.* Name :delay136.* Discription :produce delay ,the time is times.137.*================================== ===============138.*/139.static void delay(unsigned int times)140.{141.unsigned int i;142.for(;times>0;times--)143.{144.for(i=400;i>0;i--);145.}146.}147./*148.*===================Function========= =============149.* Name :key_handler150.* Discription :when the key is pressed,151.* the IRQ service will be run.152.*================================== ===============154.static void __irq key_handler(void) 155.{156.Beep_run();157.if(rEINTPEND & (1<<8))158.{159.rEINTPEND |=1<<8;160.Show_num(1);161.}162.else if(rEINTPEND & (1<<11)) 163.{164.rEINTPEND |=1<<11;165.Show_num(2);166.}167.else if(rEINTPEND & (1<<13)) 168.{169.rEINTPEND |=1<<13;170.Show_num(3);171.}172.else if(rEINTPEND & (1<<14)) 173.{174.rEINTPEND |=1<<14;175.Show_num(4);176.}177.else if(rEINTPEND & (1<<15)) 178.{179.rEINTPEND |=1<<15;180.Show_num(5);181.}182.else if(rEINTPEND & (1<<19))184.rEINTPEND |=1<<19;185.Show_num(6);186.}187.ClearPending(BIT_EINT8_23); //用来清除中断标志位;针对全局的中断188.}189.</span>实现的功能:当按下mini2440下键盘下的6个按键中的一个时,蜂鸣器发出声音,并且4个发光二极管将以2进制的形式显示出按键的值。

06-mini2440之定时器中断

#define GLOBAL_CLK 1#include "def.h"#include "option.h"#include "2440addr.h"#include "2440lib.h"#include "2440slib.h"#include "mmu.h"void led_port_init(void);void timer0_init(void);void __irq timer0_handle(void);int Main(void){led_port_init();MMU_Init();timer0_init();while (1);return 0;}void led_port_init(void){rGPBCON = 0x00015400; //设置LED口为输出rGPBDA T = 0xe<<5; //初始化为全暗}void timer0_init(void){/*系统时钟初始化在其它文件中已经完成*/rTCFG0 = 99; //预分频的值为(199 + 1)rTCFG1 = 0x3; //1/16的再分频50MHz/100/16 = 31250Hz rTCNTB0 = 31250;// rTCMPB0 = 0; 默认值就是0,所以没必要设置rTCON = 1<<1; //第一次需要手动更新。

把初值填入rTCNT0rTCON = 0x9; //三个功能:自动加载,清除手动更新,启动定时器pISR_TIMER0 = (unsigned int)timer0_handle; //注册中断ClearPending(BIT_TIMER0); //清除原来可能有的中断EnableIrq(BIT_TIMER0); //总掩码打开。

中断使能}void __irq timer0_handle(void){static unsigned char count;ClearPending(BIT_TIMER0);switch(++count % 4){case 0:rGPBDA T |= (1<<8);rGPBDA T &= ~(1<<5);break;case 1:rGPBDA T |= (1<<5);rGPBDA T &= ~(1<<6);break;case 2:rGPBDA T |= (1<<6);rGPBDA T &= ~(1<<7);break;case 3:rGPBDA T |= (1<<7);rGPBDA T &= ~(1<<8);break;}}。

mini2440test之蜂鸣器

mini2440 test之蜂鸣器2蜂鸣器(BEEP)void Buzzer_Freq_Set( U32 freq ){rGPBCON&= ~3; //set GPB0 as tout0, pwm outputrGPBCON |= 2;rTCFG0 &= ~0xff;rTCFG0 |= 15; //prescaler = 15+1rTCFG1 &= ~0xf;rTCFG1 |= 2; //mux = 1/8rTCNTB0 = (PCLK>>7)/freq;rTCMPB0 = rTCNTB0>>1; // 50%rTCON&= ~0x1f;rTCON |= 0xb; //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0rTCON&= ~2; //clear manual update bit}void Buzzer_Stop( void ){rGPBCON&= ~3; //set GPB0 as outputrGPBCON |= 1;rGPBDAT&= ~1;}//***************************[ BOARD BEEP ]******************************* void Beep(U32 freq, U32 ms){Buzzer_Freq_Set( freq ) ;Delay( ms ) ;Buzzer_Stop() ;}/**************************************************************************** 【功能说明】蜂鸣器PWM测试****************************************************************************/ void BUZZER_PWM_Test( void ){U16 freq = 1000 ;Uart_Printf( "/nBUZZER TEST ( PWM Control )/n" );Uart_Printf( "Press +/- to increase/reduce the frequency of BUZZER !/n" ) ;Uart_Printf( "Press 'ESC' key to Exit this program !/n/n" );Buzzer_Freq_Set( freq ) ;while( 1 ){U8 key = Uart_Getch();if( key == '+' ){if( freq< 20000 )freq += 10 ;Buzzer_Freq_Set( freq ) ;}if( key == '-' ){if( freq> 11 )freq -= 10 ;Buzzer_Freq_Set( freq ) ;}Uart_Printf( "/tFreq = %d/n", freq ) ;if( key == ESC_KEY ){Buzzer_Stop() ;return ;}}}有四个函数蜂鸣器频率的设定:void Buzzer_Freq_Set( U32 freq )蜂鸣器停止:void Buzzer_Stop( void )板上蜂鸣器测试:void Beep(U32 freq, U32 ms)蜂鸣器PWM测试:void BUZZER_PWM_Test( void )1)蜂鸣器频率的设定:void Buzzer_Freq_Set( U32 freq ){rGPBCON&= ~3; //set GPB0 as tout0, pwm outputrGPBCON |= 2;rTCFG0 &= ~0xff;rTCFG0 |= 15; //prescaler = 15+1rTCFG1 &= ~0xf;rTCFG1 |= 2; //mux = 1/8rTCNTB0 = (PCLK>>7)/freq;rTCMPB0 = rTCNTB0>>1; // 50%rTCON&= ~0x1f;rTCON |= 0xb; //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0rTCON&= ~2; //clear manual update bit}首先设置端口GPB0为TOUT0功能rGPBCON&= ~3; //set GPB0 as tout0, pwm outputrGPBCON |= 2;然后设置预分频和分割值,计数器的输入时钟(CCLK)频率:PCLK/(预分频+1)/分割值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一起学mini2440裸机开发(五)--定时器0的基础实验本篇文章接上一篇关于定时器原理:/mybelief321/article/details/8916775实验前的准备既然是关于定时器的实验,肯定要用到系统时钟,所以一定要保证系统时钟设置好,在这里需要的PCLK为50MHz。

第二节分析MDK自带的S3C2440.c可以知道,默认的是不初始化系统时钟(是否选择初始化可以通过修改S3C2440.s中的CLOCK_SETUP来选择)。

那么在这里首先修改一下S3C2440.s,对时钟进行初始化。

在这里只需要设置一处即可将CLOCK_SETUP EQU 0修改为CLOCK_SETUP EQU 1,这样系统在启动时就会对咱们的芯片进行初始化,初始化之后的系统时钟值为:FCLK=300MHz,HCLK=100MHz,PCLK=50MHz。

实验1实验实现的功能:使用定时器0的定时功能,是LED每秒钟闪烁一次。

因为在启动代码阶段,已经对系统时钟进行初始化,PCLK=50MHz,定时器的输入频率由PCLK分频得到,如图1所示展示了从晶振输入频率到定时器工作频率产生的整体过程。

下图是我的定时器工程的文件布局图:从上图可以看出,这个工程需要咱们自己编写的文件一共有5个:main.c timer.c timer.h led.c led.h实验代码:main.c文件内容:/** 使用定时器0的定时功能,使LED灯每秒钟闪烁一次*/#include<s3c2440.h>#include"timer.h"#include"led.h"int main(){int flag=0;Led_Init(); //对LED初始化为全灭Timer0_Init(); //定时器0初始化,打开定时器0,定时器0开始进行减1计数。

while(1){if(SRCPND&(1<<10)) //当TCNT0中的计数值减为0时,定时器0中断标志会置位{ //因此,在程序中可以通过不断的检测该位是否置位来判断1s定时flag=!flag; //是否到达。

定时器0中断标志位位于SRCPND寄存器的第10位SRCPND|=(1<<10); //清除定时器0中断标志位}if(1==flag) //判断falg是否为1,这里使用一个小技巧,使用if(1==flag)。

也可以//使用if(flag==1)。

{Led1_On();}else{Led1_Off();}}}timer.c文件内容#include<s3c2440.h> //s3c2440.h对S3C2440芯片的一些地址的宏定义#include"timer.h"/**************************************************************** 函数名称:void Timer0_Init(void)* 参数说明:无* 全局变量:无* 返回值:无* 功能:对于50MHz的PCLK,经过分频获得62.5KHz的定时器0* 的输入时钟。

***************************************************************/void Timer0_Init(void){TCFG0&=~(0xff); //设置第1级分频系数,分频系数为99TCFG0|=99;TCFG1&=~(0xf); //设置第2级分频系数,分频系数为8TCFG1|=0x02; //62.5KHz=50MHz/(99+1)/8TCNTB0=62500; //1s中断一次。

经过上述分频器得到定时器0的输入时钟频率为62.5kHz,即定时//器每秒钟计数62500次。

因此,初始化时,定时器0计数值初始值为62500,在这//里我们可以看出TCMPBn没有设置,因为咱们用它的默认值0,所以就不需要设置TCON|=(1<<1); //开启手动更新位,即当定时器开启后,TCMPB0和TCNTB0中的值会加载到寄存//器TCMP0和TCNT0中TCON=0x09; //关闭手动更新位,设置自动加载位,同时开启定时器,这样,TCNT0进行减1计//数,当TCNT0中的计数值减到0时,TCNTB0、TCMPB0中的数据分别会//自动加载到TCNT0、TCMP0中并进行新一轮的减1计数}timer.h文件内容:#ifndef __TIMER_H__#define __TIMER_H__/**************************************************************** 函数名称:void Timer0_Init(void)* 参数说明:无* 全局变量:无* 返回值:无* 功能:对于50MHz的PCLK,经过分频获得62.5KHz的定时器0* 的输入时钟。

***************************************************************/void Timer0_Init(void);#endifled.c文件内容:/** 在我的mini2440开发板上,4个led灯对应的GPIO引脚如下* LED1----GPB5* LED2----GPB6* LED3----GPB7* LED4----GPB8* 当GPIO引脚输出低电平时,对应的led灯亮,输出高电平时,对应的led灯灭。

*/#include<s3c2440.h>#include"led.h"/**************************************************************** 函数名称:void Led_Init(void)* 参数说明:无* 全局变量:无* 返回值:无* 功能:led初始化函数,使4个led初始化为灭* 的输入时钟。

***************************************************************/void Led_Init(void){GPBCON&=~((3<<10)|(3<<12)|(3<<14)|(3<<16)); //注意这里设置寄存器的方式,采用先与后或的方式GPBCON|=((1<<10)|(1<<12)|(1<<14)|(1<<16)); //设置GPB5、6、7、8为输出功能GPBUP&=~((1<<5)|(1<<6)|(1<<7)|(1<<8)); //上拉电阻使能。

上拉电阻的作用是:当GPIO引脚处于//第三态(既不是输出高电平,也不是输出低电平,而是呈//高阻态,即相当于没接芯片)时,它的电平状态由上拉//电阻、下拉电阻确定GPBDAT|=((1<<5)|(1<<6)|(1<<7)|(1<<8)); //初始化这4个引脚输出高电平,即4个led 灯全灭。

}led.h文件内容:#ifndef __LED_H__#define __LED_H__#define Led1_On() {GPBDAT&=(~(1<<5));} //在程序调用函数时,调用函数需要保存函数的返回地址,#define Led1_Off() {GPBDAT|=(1<<5);} //然后从函数返回是需要将返回地址赋值给PC,这些都会#define Led2_On() {GPBDAT&=(~(1<<6));} //使程序执行速度变慢。

为了改善这种情况,对于这种#define Led2_Off() {GPBDAT|=(1<<6);} //代码量很小的程序段,可以使用宏的形式实现。

#define Led3_On() {GPBDAT&=(~(1<<7));}#define Led3_Off() {GPBDAT|=(1<<7);}#define Led4_On() {GPBDAT&=(~(1<<8));}#define Led4_Off() {GPBDAT|=(1<<8);}/**************************************************************** 函数名称:void Led_Init(void)* 参数说明:无* 全局变量:无* 返回值:无* 功能:led初始化函数,使4个led初始化为灭* 的输入时钟。

***************************************************************/void Led_Init(void);#endif以上实验1的代码我已经上传到csdn,如有需要可自行下载:/detail/mybelief321/5371577,mske编译成功后,就可以仿真看到结果了。

上述实验1的已经说完了,再强调一下,我没有再编写代码另外设置系统时钟,而是用MDK自带的S3C2440.s来初始化的,只需要修改一处地方,本文章开头所示。

还有一处需要说明一下,那就是关于main函数里的中断。

虽然定时器0中断标志还没有讲,但是我们可以先了解以下三点:①SRCPND寄存器中的每一位代表一种类型的中断标志,当该位置1时,说明相应的中断发生了。

②定时器0中断标志位于SRCPND寄存器的第10位,当定时器0中的计数值减到0时,会触发定时器0中断标志,即SRCPND寄存器第10位会置1.③清除定时器0中断标志的方法是:想SRCPND寄存器的第10位写入1即可。

实验2实验1主要是针对定时器的原理进行的实验,下面的实验是为了展示定时器0的脉冲宽度调制功能。

从下图可以看出,当TCMP0=TCNT0时,TOUT0引脚电平会发生翻转;当TCNT0中计数值减为0时,TOUT0引脚电平再次发生翻转。

因此,可以利用TOUT0引脚电平的两次翻转进行脉冲宽度调制,即PWM。

查询S3C2440数据手册可以得到,TOUT0引脚对应的是GPB0引脚。

在实验1的基础上,修改timer.c中定时器0初始化函数。

修改后的定时器0初始化函数如下:void Timer0_Init(void){GPBCON&=~(3<<0);GPBCON|=(1<<1);TCFG0&=~(0xff); //设置第1级分频系数,分频系数为99TCFG0|=99;TCFG1&=~(0xf); //设置第2级分频系数,分频系数为8TCFG1|=0x02; //62.5KHz=50MHz/(99+1)/8//此时定时器0的工作频率为62500HzTCNTB0=62; //由于此时定时器0的工作频率为62500Hz,即每秒种可以计数62500次,而其初始值为62,所以产生的方波//的频率为62500/62=1008Hz。

相关文档
最新文档