实验前的准备
既然是关于定时器的实验,肯定要用到系统时钟,所以一定要保证系统时钟设置好,在这里需要的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 #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,仿真就可以了。
上一篇:2440+dm9000A裸机以太网通讯
下一篇:mini2440也即S3C2440地址分配问题
推荐阅读
史海拾趣
随着电子元器件市场的不断扩大,富捷电子积极实施产能扩张计划。自2020年起,公司相继启动了多个扩产项目,包括一期100亿产能生产基地项目建设和二期车规电阻产能扩充项目。这些项目的顺利实施,极大地提升了公司的生产能力和市场响应速度,有效满足了智能终端、5G、工业互联网等重要行业对电子元器件的旺盛需求。同时,富捷电子还通过优化生产流程、提升设备自动化水平等措施,进一步提高了生产效率和产品质量。
在追求经济效益的同时,Cermetek Microelectronics公司也积极履行社会责任。公司注重环保和可持续发展,采用环保材料和生产工艺,减少对环境的影响。此外,公司还积极参与社会公益事业,为社会做出贡献。这种负责任的态度不仅赢得了社会各界的认可,也为公司的长远发展注入了正能量。
这五个故事展示了Cermetek Microelectronics公司在电子行业中的发展历程和取得的成就。通过技术积累、品质管理、持续创新、国际化战略和社会责任等方面的努力,公司逐渐在微电子领域树立起了自己的品牌形象和市场地位。
Catalyst公司深知品质是企业生存和发展的根本。因此,公司始终将品质管理放在首位,从原材料采购到生产加工、产品检验等各个环节都进行严格把控。公司还建立了完善的售后服务体系,确保客户在使用过程中能够得到及时、专业的技术支持。这些举措不仅提升了Catalyst产品的品质水平,也赢得了客户的信任和好评。
在电子行业竞争激烈的年代,CDI始终坚持品质至上的原则。公司建立了严格的质量控制体系,从原材料采购到生产流程,再到成品检验,每一个环节都严格把关。正是这种对品质的执着追求,使得CDI的产品在客户中赢得了良好的口碑。随着口碑的积累,CDI逐渐发展成为电子元件领域的知名品牌。
面对国内外市场的激烈竞争,CDI积极寻求与合作伙伴的共赢发展。公司与多家知名电子设备制造商建立了长期稳定的合作关系,共同开发新产品、拓展新市场。通过合作,CDI不仅提升了自身的技术水平,还成功打入了多个国际市场,实现了业务的快速增长。
随着技术的不断积累和市场需求的扩大,聚洵半导体在产品研发上取得了显著突破。公司不仅继续深化在运算放大器领域的研发,还成功扩展了产品线,涵盖了模拟开关、电压基准、线性稳压器、电平转换器等多种产品。这些产品广泛应用于通讯网络、消费电子、工业控制等多个领域,满足了市场多样化的需求。同时,聚洵还获得了多项技术专利和荣誉,如集成电路布图设计专利和发明专利等,进一步巩固了其在行业中的地位。
我的连线方式是:板子+TTL转RS232+RS232转USB+PC。 “+”代表连接,这样转换会有什么问题么,为什么收不到数据呢。 直接将TTL转232接到PC机上就能收到,并且RS232转USB的线肯定是好的,希望懂得朋友指点迷津,谢谢了… 查看全部问答∨ |
|
为何总提示要在.NET Frame 1.1下安装,可我的系统(winxp)已经装了 microsoft visual studio 2005 和 microsoft .net Framework SDK V2.0 ???… 查看全部问答∨ |
请问下 用到EDB数据库编程时 在“VS2005|项目|属性|属性配置|C/C++|预处理器”是怎样设置的。 我的做法是在后面加了“EDB”,但出现好多错误: error C2065: \'CEPROPSPEC\' : undeclared identifier ……… 查看全部问答∨ |
我用的是2440+ce5.0,是优龙的BSP,后来发现原来用的是UART1作为调试串口,而UART0用做功能串口。现在我把bootloader里面和BSP下面的相应的UART0和UART1的地址定义交换了,发现UART0是可以做调试串口了,但是UART1却无法收发数据。在platform.reg下 ...… 查看全部问答∨ |
我想从头自学嵌入式,就在网上买了套MINI2440开发板,那个店主说调试要用到并口,我的电脑没有并口,一定要买那个JLINK吗,要180元,好贵。。。… 查看全部问答∨ |
常见ecc 源码中: static const u_char nand_ecc_precalc_table[] = { 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x ...… 查看全部问答∨ |
你们好,各位DSP高手。我现在在利用2812的AD功能进行模数转换,看见TI的示例程序中使用了EV定时器。程序如下: // Configure EVA // Assumes EVA Clock is already enabled in InitSysCtrl(); EvaRegs.T1CMPR = 0x0380; ...… 查看全部问答∨ |