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

发布者:梦幻之光最新更新时间:2021-11-04 来源: eefocus关键字:mini2440  裸机开发  定时器0 手机看文章 扫描二维码
随时随地手机看文章

实验前的准备 


既然是关于定时器的实验,肯定要用到系统时钟,所以一定要保证系统时钟设置好,在这里需要的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

#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芯片的一些地址的宏定义

            #include"timer.h"


 /***************************************************************

* 函数名称:void Timer0_Init(void)

* 参数说明:无

* 全局变量:无

* 返 回 值:无

* 功    能:对于50MHz的PCLK,经过分频获得62.5KHz的定时器0

*     的输入时钟。

***************************************************************/

void Timer0_Init(void)

{

 TCFG0&=~(0xff);          //设置第1级分频系数,分频系数为99

 TCFG0|=99;


 TCFG1&=~(0xf);            //设置第2级分频系数,分频系数为8

 TCFG1|=0x02;               //62.5KHz=50MHz/(99+1)/8


 TCNTB0=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);


#endif


led.c文件内容:


/*

*  在我的mini2440开发板上,4个led灯对应的GPIO引脚如下

*   LED1----GPB5

*   LED2----GPB6

* LED3----GPB7

*   LED4----GPB8

*   当GPIO引脚输出低电平时,对应的led灯亮,输出高电平时,对应的led灯灭。

*/


#include 

#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,如有需要可自行下载:http://download.csdn.net/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级分频系数,分频系数为99

 TCFG0|=99;


 TCFG1&=~(0xf);      //设置第2级分频系数,分频系数为8

 TCFG1|=0x02;        //62.5KHz=50MHz/(99+1)/8

                                //此时定时器0的工作频率为62500Hz


 TCNTB0=62;                  //由于此时定时器0的工作频率为62500Hz,即每秒种可以计数62500次,而其初始值为62,所以产生的方波

                                       //的频率为62500/62=1008Hz。又因为TCMP0=TCNT0/2,所以产生的方波高电平持续时间和低电平持续时间

 TCMPB0=TCNTB0/2;   //各占一半。


 TCON|=(1<<1); //开启手动更新位,即当定时器开启后,TCMPB0和TCNTB0中的值会加载到寄存器TCMP0和TCNT0中

 TCON=0x0d;     //关闭手动更新位,设置自动加载位,同时开启定时器,设置当TCMP0=TCNT0时,TOUT0引脚电平发生翻转

}


程序总体流程:


①开启定时器0后,TCNTB0、TCMPB0中的值分别装入TCNT0和TCMP0中,然后,TCNT0从初值62开始减1计数;


②当TCNT0=TCMP0=31时,TOUT0引脚电平发生翻转;


③TCNT0继续减1计数,当TCNT0减为0时,TOUT0引脚电平再次发生翻转,此时恰好产生一个方波;


④TCNTB0、TCMPB0中的值被自动装入TCNT0、TCMP0中,TCNT0继续从初值62开始减1计数。


上述程序,占空比为50%,如果将 TCMPB0=TCNTB0/2 改为 TCMPB0=TCNTB0/4,那么输出方波的占空比发生了变化,变为75%,这就是所谓的PWM功能。


由于咱们的开发板的GPB0连接着蜂鸣器,所以你可以通过调节占空比来改变蜂鸣器的频率,将上述初始化函数修改后,直接make,仿真就可以了。

关键字:mini2440  裸机开发  定时器0 引用地址:一起学mini2440裸机开发(五)--定时器0的基础实验

上一篇:2440+dm9000A裸机以太网通讯
下一篇:mini2440也即S3C2440地址分配问题

推荐阅读最新更新时间:2024-11-09 11:23

linux-2.6.32在mini2440开发板上移植 配置USB外设
编者:因为LINUX内核对S3C2440的Host驱动的已经支持,而且支持的外设相当的丰富,所以这一部分只是进行配置就可以使用。因为配置的东西较多,没有给出详细的截图,看手册上介绍的就很明白。需要手册的请留下邮箱索取。 1 配置和测试USB 键盘、扫描器和鼠标 在内核源代码目录的终端输入:make menuconfig,依次选择如下子菜单项: Device Drivers --- HID Devices --- 按空格键选中“USB Human Interface Device (full HID) support”,这样就配置好了USB键盘和鼠标项。 提示:这里的配置选项对应的内核源代码目录是:
[单片机]
【番外篇】mini2440裸机开发——程序下载SRAM,NorFlash方法
一、开发准备 开发板:mini2440, NorFlash:SST39VF1601 2MByte大小,CPU:S3C2440A 。 开发环境:MDK5.13 仿真器:Jlink v8 二、开发流程 先介绍讲程序下载到Nor Flash中的方法: 编写分散加载文件RuninFlash.sct ;************************************************************* ; *** Scatter-Loading Description File generated by uVision ; ***************************
[单片机]
【番外篇】<font color='red'>mini2440</font><font color='red'>裸机</font><font color='red'>开发</font>——程序下载SRAM,NorFlash方法
mini2440 简单的dma工作原理实验
以驱动方式测试dma的工作原理,用户层程序不停调用ioctl触发驱动里面完成的dma操作,把内存的数据块从一个连续地址搬到另一个连续地址,然后用memcmp测试搬移后的数据和搬移前是不是完全一样。 简单的驱动代码: #include linux/module.h #include linux/kernel.h #include linux/device.h #include linux/fs.h #include linux/mm.h #include linux/init.h #include linux/delay.h #include linux/interrupt.h #include linux/
[单片机]
<font color='red'>mini2440</font> 简单的dma工作原理实验
ARM裸机开发:按键输入实验
一、硬件平台: 正点原子I.MX6U阿尔法开发板 二、原理图分析 按键输入是配置GPIO作为输入,检测按键引脚电平,采用扫描的方式读取按键按下的信息,IMX6UL的按键引脚如下: 可以看到按键引脚接到 GPIO1_IO18 口,按键的原理就是默认接一个上拉电阻,按键按下接地,可以有效控制 IO 电平 三、配置代码 按键工程我们基于上一节工程进行开发,添加 BSP_KEY 工程文件 编写 bsp_key.h 文件 #ifndef __BSP_KEY_H #define __BSP_KEY_H #include fsl_iomuxc.h #include MCIMX6Y2.h #include bsp
[单片机]
ARM<font color='red'>裸机</font><font color='red'>开发</font>:按键输入实验
U-boot-2014.04移植到MINI2440(10) 移植nand flash保存环境变量、添加分区
一.保存环境变量到nand flash 第一步:修改mini2440.h 由于我们执行saveenv这个命令,然后保存环境变量,u-boot的命令都是在common下实现的,切进去执行gerp “saveenv” –nr ./*.c,查找出如下结果: 这里出现了很多,打开Makefile: # environment obj-y += env_attr.o obj-y += env_callback.o obj-y += env_flags.o obj-$(CONFIG_ENV_IS_IN_DATAFLASH) +=env_dataflash.o obj-$(CONFIG_ENV_IS_IN_E
[单片机]
U-boot-2014.04移植到<font color='red'>MINI2440</font>(10) 移植nand flash保存环境变量、添加分区
u-boot2011.12在mini2440上的移植1
以u-boot中的smdk240为原型移植到mini2440, gcc版本4.4.3,u-boot版本2011.12 1. 复制board/samsung/smdk2410 到board/samsung/mini2440; 将board/samsung/mini2440下的smdk2410.c重命名为mini2440.c; 修改board/samsung/mini2440的Makefile,将COBJS := smdk2410.o改为COBJS := mini2440.o; 2. 复制include/configs/smdk2410.h到include/configs/mini2440.h 3. 在根目录下的boa
[单片机]
玩转mini2440开发板之【制作和修改linux启动logo图片】
今天玩一玩linux启动logo图片的修改和制作。 对于我手头的mini2440开发板,其实厂家友善之臂原本是有配一个转换工具的,用起来会比较简单。但是,它那个工具仅针对32位的Fedora 9系统开发,而我目前使用的是64位的Ubuntu 14.04的系统,因此根本用不了,于是干脆自己研究一下。 一、准备工作 请自己准备一张图片,必须是png格式的。如果不是,请先用win系统自带的画图工具进行转换。 同时,该图片的分辨率不能大于你的LCD显示屏的分辨率,以我的mini2440开发板为例,其LCD的分辨率为320*240,因此我本次设计的图片就是一张320*240的图片。 二、格式转换 目的是将png格式的图片转换
[单片机]
玩转<font color='red'>mini2440</font><font color='red'>开发</font>板之【制作和修改linux启动logo图片】
mini2440烧写裸机程序
1、实现1+2+3------+100 AREA test02,CODE,READONLY start MOV R0,#0 MOV R1,#1 MOV R2,#1 LOOP ADD R2,R2,R0 ADD R1,R1,#1 CMP R1,#101 BEQ label ADD R2,R2,R1 B LOOP label NOP NOP NOP END 2、汇编LED测试 /************************************ *注意修改段名为testLED(两处修改) *在MDK中,要添加簇文件RuninRAM.sct *在MDK中,要添加初始化文件Ext_RAM.ini
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved