基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟

发布者:柳絮轻风最新更新时间:2016-09-09 来源: eefocus关键字:ARM7  TDMI-S  LPC2103  多功能电子钟 手机看文章 扫描二维码
随时随地手机看文章
一、课程设计内容与要求

1)时钟显示功能,采用数码管的动态扫描工作方式,可通过键盘分别选择显示年或者月/日或者时/分或者分/秒,

2)在键盘电路中,第一次中断判断有无键按下,若有按下则实行定时一次,下一次中断开始扫描。

3)具有校准年、月、日、时、分的功能。

4)闹钟功能,可按设定的时间闹时,随时开启或关闭闹钟。

 

二、元器件的介绍

       我在这次的课程设计中使用的主芯片是LPC2103,下面对其进行简要的介绍。

       LPC2103是一个基于支持实时仿真的16/32位ARM7 TDMI-S CPU的微控制器,并带有32kB的嵌入高速Flash存储器,128位宽度的存储器接口和独特的加速结构使32位代码能够在最大时钟速率下运行。

较小的封装和极低的功耗使LPC2103适用于访问控制器和POS机等小型应用系统中;由于内置了宽范围的串行通信接口(2个UART、SPI、SSP和2个I2C)和8KB的片内SRAM,LPC2103也适合用在通信网关和协议转换器中。32/16位定时器、增强型10位ADC、定时器输出匹配PWM特性、多达13个边沿、电平触发的外部中断、32条高速GPIO,使得LPC2103微控制器特别适用于工业控制和医疗系统中。

 

器件信息:

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 

管脚信息:(LQFP48管脚配置 )

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 

三、设计方案

 

硬件电路设计介绍:

1、键盘模块

 

 

   整个硬件上总共使用了10个独立键盘,4个是开发板上原有的按键,6个是我利用多余的IO引脚焊接的按键。按键在没有被按下时,10个按键(P0.16 P0.14 P0.15 P0.18 P0.2 P0.3 P0.4 P0.5 P0.27 P0.6 P0.7)通过10K的电阻连接到3.3V的高电平,当按键被按下时,和GND相连接,被置为低电平。

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 

2、数码管显示模块

 

使用串行输入/并行输出的8位移位寄存器74HC164,该移位寄存器是上升沿有效,将8位笔段码送给共阳数码管。(注:DATA为数据输入端,接P0.26;CLK为时钟输入端,接P0.13),与三极管相连的是数码管的位选端,选择哪位数码管被点亮,用于数码管的动态显示。

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 

3、蜂鸣器模块

 

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN

  

该蜂鸣器是一个无源蜂鸣器,要使用PWM驱动。其连接的是芯片的P0.5端。

  

4、LED模块

LED的连接如图所示,当管脚置为低电平时,可以将LED点亮,6个LED分别与LPC2103的P0.25 P0.12 P0.11 P0.10 P0.24 P0.23相连。

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN

 

 

5、UART接口电路模块

 

由于开发板是3.3V供电系统,需要使用电平转换芯片SP3232E来进行RS-232电平转换。SP3232E的工作电压为3.3V,电平转换电路如图所示。当使用ISP功能下载程序时,需要将PC机的串口与开发板的串口相连,按下与P0.14相连的按键,短接P0.14,在系统复位时,进入ISP状态,用于下载HEX文件。这个开发板有两个串口,一个用于下载程序进主芯片,另外一个用于串口在上位机上输出显示各个变量的值,可用于调试程序。

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 

按键功能介绍:(用户使用说明书)

 Key1(P0.16):对显示的数码管进行年月日时分秒的显示切换

Key2(P0.14):在时间设置或者闹钟设置按键有效的情况下,进行自加1的向上调节,对时间或者闹钟进行设置,其余情况下该按键是无效状态

Key3(P0.15):在时间设置或者闹钟设置按键有效的情况下,进行自减1的向下调节,对时间或者闹钟进行设置,其余情况下该按键是无效状态

Key4(P0.18):时间设置按键,按下表示开始进行时间设置或跳出时间设置

Key5(P0.2 ):闹钟设置按键,按下表示开始进行闹钟设置

Key6(P0.3 ):闹钟设置移位按键,按下表示进行闹钟时和分的切换设置

Key7(P0.4 ):闹钟设置结束按键,按下表示跳出闹钟设置模式;另外可以关闭蜂鸣器

Key8(P0.27):闹钟开启按键,在Key5按下的情况下按下此键表示开启该组闹钟

Key9(P0.6 ):闹钟关闭按键,在Key5按下的情况下按下此键表示关闭该组闹钟

Key10(P0.7):用于串口输出信息,可以输出当前的时间和显示开启的闹钟设置时间

当Key10按下时,会在串口中输出信息如图所示:(RTC为输出当前时间,接下来是闹钟)

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 
 
 
程序设计及流程图:
 主程序流程图:
单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
  

时间和闹钟设置程序流程图:

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 

 

IO口的初始化模块:

 

LPC2103控制器的引脚都具有多种功能,但是每个引脚在某一时刻只能选择一种功能。当使用一个功能外设时,如果需要相应的引脚参与(如GPIO等),则必须在实现这一功能之前先设置好引脚的功能,否则无法实现该外设功能。LPC2103具有两个PINSEL寄存器,PINSEL0和PINSEL1,PINSEL0和PINSEL1寄存器中的每两个位控制着一个引脚的功能,所以一个引脚最多可以有4种不同的功能选择。当引脚选择GPIO功能时,使用寄存器IODIR可以控制引脚的方向,另外IOCLR、IOSET两个寄存器分别可以将引脚初始化设置为低电平或者高电平。所以,在主程序开始是时的GPIO初始化中包含如下几个子函数:

void GPIO_init(UINT8 GPIO_num);                             将管脚初始为GPIO功能

void GPIO_inout(UINT8 GPIO_num,UINT8 in_out);     设置GPIO为输入或者输出

UINT8 GPIO_READ(UINT8 GPIO_num);                    读出GPIO当前的状态

void GPIO_SET(UINT8 GPIO_num,UINT8 High_Low);       GPIO初始化后置1或者置0

 

定时器的初始化模块:

       该程序中使用了3个定时器,定时器0、1、2。定时器0设置为PWM输出模式,产生2kHZ的方波,用于驱动无源蜂鸣器,当设置的闹钟时间和当前时间匹配时,将定时器0启动,产生方波驱动蜂鸣器发出响声提醒。

       定时器1用于时间计数,即当前时钟的计时器,它设置为1秒钟产生一次中断,其中断程序分配为最高的优先级,当一秒的定时时间到时,在服务程序中首先清除中断标志位,然后秒变量进行自加1(miao++),另外还进行秒闪烁标志位(g_Dot)的取反标志,使秒标志位能够闪烁。

       定时器2的初始化有多个功能。定时器2的优先级是次于定时器1的,定时器设置为5毫秒产生一次中断,首先是用于四位八段LRD的动态扫描显示,使四位数码管的刷新频率为50Hz,另外是10mS的标志位(time10)自加1,当10mS标志位计时时间到时,就执行一次键盘扫描程序,即10个独立键盘每10mS被扫描一次。最后是清除中断标志位,通知中断服务程序结束。

 

时间更新子函数模块:

       该函数主要是对当前时间的处理,定时器1对秒变量进行了计数,而此程序就是对时分秒年月日变量的值进行判断和限制,使其超过最大值后对其进行归零,比如分秒的值不能大于59,时的最大值为23。大小月以及二月份天数的处理是通过调用UINT8  yue_deal()这个函数实现的。该函数主要是使用一个switch  case  语句,对大月份返回一个值31,小月份返回30,另外通过调用UINT8  nian_deal()来判断是平年还是闰年【闰年条件:if((nian%4==0&&nian%100!=0)||nian%400==0)】,闰年返回29,平年返回28。具体的程序见附录。

 

数码管动态显示模块程序:

       四位数码管的刷新频率为50Hz,即一位显示时间为(1∕50×4)即5mS,用定时器2每5ms产生一次中断进行刷新,每次中断产生时只将一位数码管的位选端点亮,用void Refresh_LED(UINT16 dat)函数实现这一功能,由于数码管的笔段码输入端接的是8位移位寄存器74HC164,故需要使用移位将笔段码送到数码管笔段输入端【void data_shift(UINT8 dat)函数】。

       注:显示程序负责当前时间的显示和闹钟设置时的显示内容,需要改变的是将要显示的数值用变量display进行保存成为十进制的四位数。

 

键盘扫描程序:

       如果10毫秒定时时间到的标志位有效,就进入键盘扫描的子程序UINT8 GetKey()中。通过查找资料,该部分的程序设计采用的是状态机的思想,用如下图所示,其中系统的输入信号是与按键连接的I/O口电平,“1”表示按键处于开放状态,“0”表示按键处于闭合状态。而系统的输出信号则表示检测和确认到一次按键的闭合操作,用“1”表示。
单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 

上图给出了一个简单按键状态机的状态转换图。在图中,将一次按键完整的操作过程分解为3个状态,采用时间序列周期为10ms。下面对该图做进一步的分析和说明,并根据状态图给出软件的实现方法。首先,要充分体会时间序列的作用。在这个系统中,采用的时间序列周期为10ms,它意味着,每隔10ms检测一次按键的输入信号,并输出一次按键的确认信号,同时按键的状态也发生一次转换。图中“状态0”为按键的初始状态,当按键输入为“1”时,表示按键处于开放,输出“0”(1/0),下一状态仍旧为“状态0”。当按键输入为“0”,表示按键闭合,但输出还是“0”(0/0)(没有经过消抖,不能确认按键真正按下),下一状态进入“状态1”。“状态1”为按键闭合确认状态,它表示了在10ms前按键为闭合的,因此当再次检测到按键输入为“0”时,可以确认按键被按下了(经过10ms的消抖),输出“1”表示确认按键闭合(0/1),下一状态进入“状态2”。而当再次检测到按键的输入为“1”时,表示按键可能处在抖动干扰,输出为“0”(1/0),下一状态返回到“状态0”。这样,利用状态1,实现了按键的消抖处理。“状态2”为等待按键释放状态,因为只有等按键释放后,一次完整的按键操作过程才算完成。从对上图的分析中可以知道,在一次按键操作的整个过程,按键的状态是从“状态0”->“状态1”->“状态2”,最后返回到“状态0”的。并且在整个过程中,按键的输出信号仅在“状态1”时给出了唯一的一次确认按键闭合的信号“1”(其它状态均输出“0”)。所以上面状态机所表示的按键系统,不仅克服了按键抖动的问题,同时也确保在一次按键整个的过程中,系统只输出一次按键闭合信号(“1”)。换句话讲,不管按键被按下的时间保持多长,在这个按键的整个过程中都只给出了一次确认的输出,因此在这个设计中,按键没有“连发”功能,它是一个最简单和基本的按键。一旦有了正确的状态转换图,就可以根据状态转换图编写软件了。在软件中实现状态机的方法和程序结构通常使用多分支结构(IF-ELSEIF-ELSE、CASE等)实现。下面是根据上图、基于状态机方式编写的简单按键接口函数GetKey()。

该简单按键接口函数GetKey()在整个系统程序中应每隔10ms调用执行一次,每次执行时进入用switch结构构成的状态机。switch结构中的case语句分别实现了3个不同状态的处理判别过程,在每个状态中将根据状态的不同,以及key4的值(状态机的输入)确定输出值(keyreturn),和确定下一次按键的状态值(keystate)。函数GetKey()的返回参数提供上层程序使用。返回值为0时,表示按键无动作;而返回1表示有一次按键闭合动作,需要进入按键处理程序做相应的键处理。在函数GetKey()中定义了2个局部变量,其中keyreturn为一般普通的局部变量,每次函数执行时,keyreturn为函数的返回值,总是先初始化为0,只有在状态1中重新置1,作为表示按键确认的标志返回。变量keystate非常重要,它保存着按键的状态值,该变量的值在函数调用结束后不能消失,必须保留原值,因此在程序中定义为“局部静态变量”。通过对按键的扫描程序后,就知道了哪一个独立键盘的按键被按下了,通过void keysure()函数来定义每一个按键的功能。

 

中断优先级的定义:

       LPC2103的向量中断控制器VIC(Vectored Interrupt Controller)具有32个中断请求输入。可将这些中断编程分为3类:FIQ、向量IRQ、非向量IRQ。其中快速中断请求FIQ(Fast Interrupt reQuest)具有最高的优先级。向量IRQ(Vectored IRQ)具有中等优先级。该级别可分配32个中断请求中的16个。32个请求中的任意一个都可分配到16个向量IRQ slot中的任意一个,其中slot0具有最高优先级,而slot15则为最低优先级。非向量IRQ(Non-vectored IRQ)的优先级最低。

       在这个多功能时钟的程序设计中,使用了两个中断都是分配为向量IPQ。定时器1作为时钟的基准计数时钟,有最高的优先级;定时器2分配为下一个优先级。相关的语句设置如下:

VICVectCntl0 = 0x20 | 5;                                        /*  定时器1分配为向量IRQ通道0 */

VICVectAddr0 = (UINT32) Timer1ISR;                    /*  分配中断服务程序地址0       */

VICVectCntl1 = 0x20 | 26;                                      /*  定时器2分配为向量IRQ通道1 */

VICVectAddr1 = (UINT32) Timer2ISR;                    /*  分配中断服务程序地址1       */

VICIntEnable = 1 << 26;                                   /*  定时器2中断使能            */

VICIntEnable = 1 << 5;                                 /*  定时器1中断使能             */

 

 

四、调试过程

      

由于这次的设计使用的是LPC2103的开发板,所以在硬件上不需要太多的去调试。在利用开发板硬件资源的基础上,由于这次的多功能闹钟设计使用的模块较多,基本上各个模块的调试是分开进行的。主要包括初始化的程序调试、按键子程序调试、LED显示调试这几部分子程序的调试。将这三部分调试成功,那么整个设计的软件部分也就基本完成了。在该课程设计中,采用的集成开发环境是uVision,在软件设计过程中,有时候不小心插入了一个中文的符号(如分号),就会使软件编译不通过,开始在这个错误上浪费不少时间,但后来注意到了这个情况,避免了类似的错误的发生。

       我首先进行的是键盘扫描模块的程序设计及调试。该模块主要由按键的状态确认函数(UINT8 GetKey())和按键确认函数(void keysure())共同完成。按键的状态函数主要是由一个返回值来确认按键的状态,开始的时候,由于缺少一个语句:keyreturn=0;即每次进入函数的时候要将按键的状态清零,导致按键在一次按下之后就出现了不正常的情况,最后找到问题的所在,就纠正了过来。由于这个模块是我最先进行的,所以开始的时候我并没有给每个按键定义相应的功能,每个按键的功能我都是定义为每次按下对相应的LED进行取反操作,在之后的设计中,再在相应的按键确认语句下增加入相应的功能,这也是模块化程序设计的一个体现。

       四位的数码管采用的是动态显示模式,刷新频率为50Hz,另外,由于开发板的硬件采用的是移位寄存器送笔段码,所以在软件设计方面要用到将8位笔段码不断循环右移,增加了设计的难度。起初我认为一切程序都编写得差不多的时候,烧进芯片的程序使数码管显示一片模糊,基本上显示的都是8,后来从程序的开始查起,终于找到原因,原来动态显示程序中,每次只能是一位的数码管点亮,但在程序设计中,在点亮下一位数码管时,忘记了将上一次点亮的位给关掉,导致四位数码管时同时被点亮的,最后,在点亮数码管前首先将四位数码管全部关闭,再以50Hz的频率进行点亮刷新,显示方回到正常状态。

       最后就是在这两个模块的基础上来对整体的程序进行相关的调试和完善。例如在原先设置有当进入时间设置或者闹钟挂起时有LED点亮进行提示,设置时间时相关的设置超过相应的极限值,这些在最后的调试过程中得到完善,使其工作在正常的状态,调试过程也就这样基本得到完成。

 

五、结论

       这次的课程设计基本上完成了任务书中所提出的要求。最终的成品具有如下功能:

通过数码管动态扫描的工作方式实现时分秒年月日星期的显示,利用键盘实现利用四位数码管可以进行如上时间的自由切换,时钟具有时间设置和随时的校准功能。有三组可随意设置打开或者关闭的闹钟,闹钟匹配时有蜂鸣器响和LED闪烁两种方式进行提醒。利用串口可以输出当前时间和被挂起的闹钟。

       综上所述,本次的课程设计达到预期的设计要求。

 

六、小结与讨论

  

    通过为期一个星期以来的单片机课程设计,感觉自己在这么的一个过程下来,还是很有收获的。这个设计的题目老师是在亚运放假之前就给我们的,我知道老师是希望我们用亚运放假的时间去思考、去准备的过程。

       从暑假以来,我就利用暑假空闲的时间,来自学ARM7TDMI-S内核的一款芯片LPC2103,其与单片机相识的一些功能我都有涉及性的学习过了,在9月份,我买了它的开发板,进行相关的实践性学习。基于上述的原因,所以这次的课程设计我就想用这款LPC2103的芯片开进行这次的课程设计,也是对我之前的学习的一种检验。以前用开发板学习的时候,都是针对其的单独一个功能进行相关程序的设计,而这次的课程设计会涉及比较多的功能模块的综合应用,所以,开始的时候有点摸不着头脑的感觉。最后经过几番的思考,我就决定,针对每一个模块,一个个进行攻破,最终实现了多功能电子时钟的全部的功能。

       首先,我利用LPC2103的实时时钟功能(RTC),先对其进行初始化,使其的时钟跑起来,在这个基础上,我最先是开始键盘模块的设计,这就涉及到:键盘扫描,键盘去抖动,键盘判断相关的问题,最后经过两天的编程,设计,调试,思考才把键盘模块的问题顺利地解决了。从最初的模型规划,到具体功能的实现,直到最后的软件设计和调试过程,每一个环节都让我加深了对实际问题的思考,有利于自己动手能力的提高。

       这次的课程设计让我学会了系统地去解决一个实际的问题,了解到了单片机设计的基本步骤、开发设计过程中需要注意的问题、学会处理调试过程中出现的问题.,学会了巧妙运用模块化设计的思想,在整个的程序化设计过程中,学会将功能细化,分成一个小功能来实现,在设计好一个功能之后,再在这个基础上去增加其他的功能,最后完成整个多功能电子时钟的设计。总之,通过这次的课程设计,检验了我所学习的知识,使我将平时书本上的理论知识与实践很好地结合起来,利于加深对理论知识的理解和提高自己的实际动手操作能力。

 

七、参考文献

 

1、《ARM微控制器基础与实战》      出版社:北京航空航天大学出版社           2005年

2、《ARM7易学通》                         出版社:人民邮电出版社                         2006年

3、《EasyARM2103教材》                出版社:北京航空航天大学出版社           2008年

4、《新编单片机原理与应用》           出版社:西安电子科技大学出版社           2007年

5、《新编单片机原理与应用实验》    出版社:西安电子科技大学出版社           2005年

 

       附录:

 

开发板实物图

单片机课程设计:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟 - 午夜阳光 - KISS THE RAIN
 
 
以下是完整的源程序:
 以下是名为main.c的文件
 #include                 /* prototype declarations for I/O functions */
#include               /* LPC21xx definitions                      */
#include "main.h"
#define  LED  (1<<23)
UINT8  keystate=0;        //按键的状态标志有0、1、2三种状态
UINT16  key4=1023;    //按键的扫描输入端
UINT8  keyreturn=0;       //按键的返回值
UINT8  time10=0;    //10ms标志位
UINT8  dis_bit=0;       //显示切换标志位
UINT8  settime=0;     //进入时间设置标志位
UINT8  alarm=0;     //闹钟设置有效标志位
UINT8  al_shi1=0;      // 以下是闹钟的序号和用数组储存的闹钟时、分位
UINT8  al_num=0;
UINT8  al_shi[4];
UINT8  al_fen[4];
UINT8  al_yunxu=0;         //闹钟才开始比较,确保设置期间不比较
UINT8  LS=0;        //闹钟时间到,铃声有效位,0为无效状态
UINT8  al_on3off[4]={0,0,0,0};   //用数组记录闹钟是否开启
UINT8 al_flag=0;    //闹钟组数1.2.3,0表示没有闹钟被挂起
UINT8  al_fen1=0;
static UINT8 g_Dot = 0;
static UINT16 display = 0;  //数码管显示缓存

UINT16  nian=2008;    //与时间相关的变量
UINT8   yue=8;
UINT8 ri=8;
UINT8 week=5;
UINT8 shi=20;
UINT8   fen=0;
UINT8 miao;
//--------------------------------------------------------------------------------
void UART1_Init (void)  
{
 UINT16 Fdiv;
 PINSEL0 = 0x00050000;
 U1LCR = 0x83;                  // DLAB = 1,可设置波特率
 Fdiv = (Fpclk / 16)/ UART_BPS;             // 设置波特率
 U1DLM = Fdiv / 256;       
 U1DLL = Fdiv % 256; 
 U1LCR = 0x03;
}

void GPIO_init(UINT8 GPIO_num)      // 初始为GPIO功能
{
 if(GPIO_num < 16)
  PINSEL0 &= ~(0x03 << (GPIO_num * 2));
 else
  PINSEL1 &= ~(0x03 << ((GPIO_num-16) * 2));
}
void GPIO_inout(UINT8 GPIO_num,UINT8 in_out)     //设置GPIO为输入0或者输出1
{
 if(in_out)
  IODIR |= (0x01 << GPIO_num);     //output   1
 else
  IODIR &= ~(0x01 << GPIO_num);     //input  0 
}
UINT8 GPIO_READ(UINT8 GPIO_num)       //读出GPIO的状态
{           
 if(IOPIN & (1 << GPIO_num))        
  return 1; 
 else
  return 0;    
}
void GPIO_SET(UINT8 GPIO_num,UINT8 High_Low)    //GPIO置1或者置0
{           
 if(High_Low)       
  IOSET |= (0x01 << GPIO_num);
 else
  IOCLR |= (0x01 << GPIO_num);

void LEDchange(UINT8 GPIO_num)      //对二极管进行取反
{
if ((IO0PIN & (0x01 << GPIO_num)) == 0) {
        IO0SET |= (0x01 << GPIO_num);              // 点亮发光二极管             
    } 
    else IO0CLR |= (0x01 << GPIO_num);              
}
UINT8  nian_deal()
{   if((nian%4==0&&nian%100!=0)||nian%400==0)
   return 1;
  else return 0;
}
 
UINT8  yue_deal()
{
 switch(yue)
 {
   case 1:
   case 3:
   case 5:
   case 7:
   case 8:
  case 10:
  case 12: return 31;
  case 2:
    {
       if(nian_deal())
         return 29;
     else return 28;
    } 
  case 4:
  case 6:
  case 9:
  case 11:  return 31;
  default:  return 1;
 }
}
 

void keysure()       //按键的确认 ,并执行相关功能
{
  if(GPIO_READ(14)==0)     //对每一位进行切换
   {     
   if(settime!=0)
    {
     switch(dis_bit)
     {  case 0:
       if(settime==1)
        {shi++;
       if(shi>23)
         shi=0;
      }
      else {fen++;
       if(fen>59)
       fen=0;
      
      }
      break;
     case 1:
      week++;
      if(week>7)
        week=1;
      break;
     case 2:
      nian++;
      break;
     case 3:
      if(settime==1)
       {yue++;
        if(yue>12)
        yue=1;
       }
       else 
       { ri++;
        if(ri>yue_deal())
        ri=1;
       }
       break;
      }
  
    }
    if(alarm!=0)
     { if(alarm==1)
    {
    al_shi1++;
    if(al_shi1>23)
      al_shi1=0;
     al_shi[al_num]=al_shi1;
    }
   else 
   {al_fen1++;
     if(al_fen1>59)
     al_fen1=0;
     al_fen[al_num]=al_fen1;
   }
     
     }
 
 }
 if (GPIO_READ(15)==0)
     {
  if(settime!=0)
    {
     switch(dis_bit)
     {  case 0:
       if(settime==1)
        {shi--;
       if(shi>23)
        shi=23;
      }
      else {fen--;
       if(fen>59)
        fen=59;
      }
      break;
     case 1:
      week--;
      if(week==0)
       week=7;
      break;
     case 2:
      nian--;
      break;
     case 3:
      if(settime==1)
       {yue--;
        if(yue==0)
         yue=12;
       }
       else 
       { ri--;
        if(ri==0)
        ri=yue_deal();
       }
       break;
      }
    }
  if(alarm!=0)
     { if(alarm==1)
    {
    al_shi1--;
     if(al_shi1>23)
      al_shi1=23;
   al_shi[al_num]=al_shi1;
    }
   else 
   {al_fen1--;
       if(al_fen1>59)
      al_fen1=59;
   al_fen[al_num]=al_fen1;
   }
   
     }
   }
 if(GPIO_READ(16)==0) 
     {
 
    if(dis_bit==3)
   dis_bit=0;
   else dis_bit++;
  
   }
 if(GPIO_READ(18)==0) 
     { if(settime>1)
     {
   settime=0;
    T1TCR  = 0x01;   
   GPIO_SET(23,1);
   }
  else {settime++;   
    T1TCR  = 0x00;    
   GPIO_SET(23,0); }
   }
  if(GPIO_READ(2)==0)
   { al_yunxu=0;
   alarm=1;
   al_num++;
   if(al_num>3)
     al_num=1;
  //al_num++;
  }
 if(GPIO_READ(3)==0)
   {
   alarm++;   //对闹钟的时分为进行设置切换
   if(alarm>2)
    alarm=1;
  }
 if(GPIO_READ(4)==0)
   { 
    if(alarm!=0)
     {alarm=0;
    al_shi1=0;
    al_yunxu=1;
    al_flag=0;
    for(al_num=0;al_num<4;al_num++)
    {  if(al_on3off[al_num]==1)
         al_flag++;
    }
    if(al_flag!=0)
    GPIO_SET(24,0);
   if(al_flag==0)
    GPIO_SET(24,1);
   }
   else
   { 
 
    LS=0;
     T0TCR=0x00;                            //启动对响铃进行关闭
    GPIO_SET(25,1);
  GPIO_SET(11,1);
  GPIO_SET(12,1);
 
  }
   }
  if(GPIO_READ(27)==0)
  { 
  if(alarm!=0)
  { al_on3off[al_num]=1;
  
  }
  if(settime!=0)
      nian=nian+10;
 
            //表示有闹钟挂起,要加上一些标示位 
  }
 if(GPIO_READ(6)==0)
 {  if(alarm!=0)
  {
    al_on3off[al_num]=0;
  }
  if(settime!=0)
      nian=nian-10;
 }
   if(GPIO_READ(7)==0)
    {
          //启动 输出开启的闹钟信息
    printf("RTC ----%02d -%02d -%02d _ %02d : %02d : %02d WEEK=%d-- \n",nian,yue,ri,shi,fen,miao,week);
  for(al_num=0;al_num<4;al_num++)
  {
   if(al_on3off[al_num]==1)
    {
    printf("The number%d alarm is on.---Alarm time--%d : %d --\n",al_num,al_shi[al_num],al_fen[al_num]);
   }
  }
    }
}
UINT8 GetKey()
{ keyreturn=0;
 key4=GPIO_READ(18)| (GPIO_READ(15)<<1)|(GPIO_READ(14)<<2)|(GPIO_READ(16)<<3)|(GPIO_READ(2)<<4)|(GPIO_READ(3)<<5)|(GPIO_READ(4)<<6)|(GPIO_READ(27)<<7)|(GPIO_READ(6)<<8)|(GPIO_READ(7)<<9);
 switch (keystate)
 {
    case 0:
      if(key4!=1023)   //检测到有按键,转到状态1,相当于是消抖过程
      {
       keystate=1; 
      }
    break;
    case 1:
      if(key4!=1023)    //再次检测到有按键,确认按键按下,返回一个值,并转到状态2
      {
    keyreturn=1;
       keystate=2; 
      }
     else
      {
       keystate=0; //没有检测到按键,说明状态0检测到是一个抖动,重新转到状态0
      }
    break;
    case 2:
      if(key4==1023)    //检测到按键松开,状态转到状态0,一次完整的按键过程结束
      {
       keystate=0;
      }
    break;
 }
return keyreturn;
}
 
void data_shift(UINT8 dat)
{
 UINT8 i;
 for(i=0; i<8; i++)
 {
  GPIO_SET(CLK,LOW); 
  if(dat & 0x01){
   GPIO_SET(DATA,0); 
  }
  else{
   GPIO_SET(DATA,1); 
  }
  
  GPIO_SET(CLK,HIGH); 
   
  dat >>= 1;
 } 
}
 
void Refresh_LED(UINT16 dat)
{
 static UINT8 i = 0; 
 UINT8 a,b,c,d;
 a = dat /1000;
 b = dat % 1000 / 100;
 c = dat % 1000 % 100 /10;
 d = dat % 1000 % 100 % 10; 
 
 switch(i)
 {
  case 0:
  i++;
  GPIO_SET(DIG_EN0,LOW); 
  data_shift(DIGData[d]);
  break;
   
  case 1:
  i++;
  GPIO_SET(DIG_EN1,LOW);  
  data_shift(DIGData[c]);
  break;
   
  case 2:
  i++;
  GPIO_SET(DIG_EN2,LOW);
  if(g_Dot)
   data_shift(DIGData[b] & ~(0x01 << 0));
  else
   data_shift(DIGData[b] | (0x01 << 0));
  break;
   
  case 3:
  i = 0;
  GPIO_SET(DIG_EN3,LOW);  
  data_shift(DIGData[a]);
  break;
 }
}
/*********************************************************************************************************
** Function name:       Timer1_ISR
** Descriptions:        定时器1中断主程序
** input parameters:    无
** ouput parameters:    无
** Returned value:      无
*********************************************************************************************************/
void  __irq Timer1ISR (void)
{  
  T1IR = 0x01;                                                        /*  清除中断标志                */
   miao++;
   if(g_Dot)
  g_Dot = 0;
 else
  g_Dot = 1;
    VICVectAddr = 0x00;                                                 /*  中断向量结束                */
}
void  __irq Timer2ISR (void)

 GPIO_SET(DIG_EN0,HIGH); 
 GPIO_SET(DIG_EN1,HIGH); 
 GPIO_SET(DIG_EN2,HIGH); 
 GPIO_SET(DIG_EN3,HIGH);
 Refresh_LED(display);
    time10++;                               
    T2IR = 0x01;                                                        /*  清除中断标志                */
    VICVectAddr = 0x00;                                                 /*  中断向量结束                */
}
void  Timer1Init(void)

    T1TCR  = 0x02;                                                      /*  定时器1复位                 */
    T1PR   = 0;                                       /*  不设时钟分频                */
    T1MCR  = 0x03;                                      /*  匹配后复位TC,并产生中断  */
    T1MR0  = Fpclk ;                                                    /*  设置1秒匹配值              */
    T1IR   = 0x01;                                                      /*  清除中断标志               */
    T1TCR  = 0x01;                                      /*  启动定时器1                 */
}
 
void timeupdate()  //时间更新函数
{

  if(miao>59)
  {
    fen++;
  if(al_flag&&al_yunxu)    //表示闹钟开启,bian a!! 
  {
   for(al_num=0;al_num<4;al_num++)
   {if(fen==al_fen[al_num]&&shi==al_shi[al_num]&&al_on3off[al_num]==1)
    {  al_flag--;
     al_on3off[al_num]=0;
     if(al_flag==0)
      GPIO_SET(24,1);
      LS=1;
           
    }
   }
  }
  miao=0;
  if(fen>59)
   {
    shi++;
    fen=0;
    if(shi>23)
    {
     ri++;
     week++;
     if(week>7){week=1;}
     shi=0;
     if(ri>yue_deal())
      {
       yue++;
       ri=1;
       if(yue>12)
       {
        nian++;
        yue=1;
        if(nian>9999)
         nian=1000;
       }
      }
     }
    }
  }
}
 
/*********************************************************************************************************
** Function name:       Timer0\2Init
** Descriptions:        定时器0&2初始化
** input parameters:    无
** ouput parameters:    无
** Returned value:      无
*********************************************************************************************************/
void  Timer2Init(void)        //这里也初始化了T0,用于pwm输出,驱动蜂鸣器

 PINSEL0 &= ~(3 << 10);
 PINSEL0 |= (2 << 10);       //P0.5 作MAT0.1输出
 
 T0TCR=0x02;                              //复位
 T0PR =0x00;                              //不预分频
 T0PWMCON=0x02;                            //MAT0.1为PWM输出,在P0.5脚
 
 T0MR0=Fcclk/1000;                       
 T0MCR=0x02;                             //每FCLK/1000复位一次T0
 T0MR1=((Fcclk/2000)/10)*10;            

    T2TCR  = 0x02;                                                      /*  定时器2复位                 */
    T2PR   = 0;                                       /*  不设时钟分频                */
    T2MCR  = 0x03;                                      /*  匹配后复位TC,并产生中断   */
    T2MR0  = Fpclk /200;                                                 /*  设置5毫秒匹配值           */
    T2IR   = 0x01;                                                      /*  清除中断标志               */
    T2TCR  = 0x01;                                      /*  启动定时器2                 */
}
void PLL_Init(void)
{
    PLLCON = 1;
 #if (Fcco / Fcclk) == 2
  PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5);
 #endif
 #if (Fcco / Fcclk) == 4
  PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5);
 #endif
 #if (Fcco / Fcclk) == 8
  PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5);
 #endif
 #if (Fcco / Fcclk) == 16
  PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5);
 #endif
  PLLFEED = 0xaa;
  PLLFEED = 0x55;
  while((PLLSTAT & (1 << 10)) == 0);
  PLLCON = 3;
  PLLFEED = 0xaa;
  PLLFEED = 0x55; 
}

int main (void)   
{  
 PLL_Init();
 
 UART1_Init();
 
 GPIO_init(14);                                           //  选择GPIO功能 
 GPIO_init(15);
 GPIO_init(16);
 GPIO_init(18);
 GPIO_init(2);
 GPIO_init(3);
 GPIO_init(4);
 GPIO_init(27);
 GPIO_init(6);
 GPIO_init(7);
    GPIO_inout(14,0);                                                      // 设置输入        
 GPIO_inout(15,0);
 GPIO_inout(16,0);
 GPIO_inout(18,0);
 GPIO_inout(2,0);
 GPIO_inout(3,0);
 GPIO_inout(4,0);
 GPIO_inout(27,0);
 GPIO_inout(6,0);
 GPIO_inout(7,0);
 GPIO_init(23);                //LED控制端的初始化
  GPIO_init(24);  
 GPIO_init(10);  
 GPIO_init(11); 
 GPIO_init(12);
 GPIO_init(25);
 GPIO_inout(23,1);
 GPIO_inout(24,1);
 GPIO_inout(10,1);
 GPIO_inout(11,1); 
 GPIO_inout(12,1); 
 GPIO_inout(25,1); 
 GPIO_SET(23,1);
 GPIO_SET(24,1);
 GPIO_SET(10,1);
 GPIO_SET(11,1);
 GPIO_SET(12,1);
 GPIO_SET(25,1);
 GPIO_init(DATA); 
 GPIO_init(CLK);
 GPIO_init(DIG_EN0);
 GPIO_init(DIG_EN1);
 GPIO_init(DIG_EN2);
 GPIO_init(DIG_EN3); 
 GPIO_inout(DATA,OUTPUT); 
 GPIO_inout(CLK,OUTPUT);
 GPIO_inout(DIG_EN0,OUTPUT);
 GPIO_inout(DIG_EN1,OUTPUT);
 GPIO_inout(DIG_EN2,OUTPUT);
 GPIO_inout(DIG_EN3,OUTPUT); 
 GPIO_SET(CLK,HIGH);  
 GPIO_SET(DATA,HIGH);
 //GPIO_init(5);
 //GPIO_inout(5,1);
 //GPIO_SET(5,1); 
 Timer1Init();
    Timer2Init();                                                       //  定时器初始化          

   VICIRQStatus=1<<26;                                                     //  IRQ中断使能                 
    VICIntSelect = 0<<26;                       //  定时器2分配为IRQ中断       
    VICVectCntl1 = 0x20 | 26;                                /*  定时器2分配为向量IRQ通道0   */
    VICVectAddr1 = (UINT32) Timer2ISR;                              /*  分配中断服务程序地址        */
    VICIntEnable = 1 << 26;                                    /*  定时器2中断使能             */
   VICIntSelect = 0<<5;
  VICVectCntl0 = 0x20 | 5;                                /*  定时器1分配为向量IRQ通道0   */
    VICVectAddr0 = (UINT32) Timer1ISR;                              /*  分配中断服务程序地址        */
    VICIntEnable = 1 << 5;                                    /*  定时器1中断使能             */

 while(1)
  {   
    timeupdate();
   if(alarm!=0)
    { 
    if(al_on3off[al_num]==0)
   display=al_num*1111;
     else 
     display=al_shi[al_num]*100+al_fen[al_num];
  }
 else
  {  switch(dis_bit)
    { case 0:
          display=shi*100+fen;
       break;
    case 1:
     display=miao*100+week;
     break;
    case 2:
     display=nian;
     break;
    case 3:
     display=yue*100+ri;
     break;
    }
  } 
  if(time10==1)
   { time10=0;
     if(GetKey()==1)
  {
     keysure();
   
  }
   }
 if(LS==1)
 {  if(miao%2==0)
  {   GPIO_SET(25,1);
   GPIO_SET(11,1);
   GPIO_SET(12,1);
   T0TCR=0x01;   
  
  }
    else
    {  GPIO_SET(25,0);
   GPIO_SET(11,0);
   GPIO_SET(12,0);
    T0TCR=0x00;   
   
     }
 
 }
  }
}  
                           
以下是名为main.h的文件
typedef unsigned char UINT8 ;
typedef unsigned int UINT16 ;
typedef unsigned int UINT32 ;
//--------------------------------------------------------------------------------
#define UART_BPS  115200
/* 系统设置, Fosc、Fcclk、Fcco、Fpclk必须定义*/
#define Fosc (11059200)  //晶振频率,10MHz~25MHz,应当与实际一至
#define Fcclk (Fosc * 4)   //66.3552 系统频率,必须为Fosc的整数倍(1~32),且<=60MHZ
#define Fcco (Fcclk * 4)  //CCO频率,必须为Fcclk的2、4、8、16倍,范围为156MHz~320MHz
#define Fpclk (Fcclk / 4) * 1 //016.5888,VPB时钟频率,只能为(Fcclk / 4)的1 ~ 4倍
//--------------------------------------------------------------------------------
typedef enum 
{
 LOW,
 HIGH 
}en_Level;
typedef enum 
{
 INPUT,
 OUTPUT 
}en_InOut;
enum 
{
 FALSE,
 TRUE 
};
#define SH  (0x01 << 0)
#define SG  (0x01 << 1)
#define SF  (0x01 << 2)
#define SE  (0x01 << 3)
#define SD  (0x01 << 4)
#define SC  (0x01 << 5)
#define SB  (0x01 << 6)
#define SA  (0x01 << 7)
const UINT8 DIGData[] =
{
 SA |SB |SC | SD |SE |SF,  //0
 SB | SC,      //01
 SA |SB |SG | SE | SD,   //02
 SA |SB |SC | SD | SG,   //03
 SB |SF | SG | SC,    //04
 SA |SF |SG |SC  | SD,   //05
 SA |SC | SD | SE | SG | SF, //06
 SA | SB| SC,     //07
 SA |SB |SC | SD | SE | SF | SG,//08
 SA |SB |SC|SD | SF | SG , //09
 0,       //mask - 10 
 SG       //minus - 11  
};
//--------------------------------------------------------------------------------
#define LED1  25
#define LED2  12
#define LED3  11
#define LED4  10
#define LED5  24
#define DATA  26
#define CLK   13
#define DIG_EN0  21
#define DIG_EN1  20
#define DIG_EN2  19
#define DIG_EN3  17
#define INT0  16
#define INT1  14
#define INT2  15
#define IR_IN  18
#define BUZZER  23
//--------------------------------------------------------------------------------

void PLL_Init(void);
void  Timer0_Init(void);
void UART1_Init (void);
UINT8 GPIO_READ(UINT8 GPIO_num) ;
void GPIO_init(UINT8 GPIO_num);
void GPIO_inout(UINT8 GPIO_num,UINT8 in_out);
//inline void GPIO_SET(UINT8 GPIO_num,UINT8 High_Low);
void __irq IRQ_Timer0 (void);
void GPIO_SET(UINT8 GPIO_num,UINT8 High_Low);
//--------------------------------------------------------------------------------

关键字:ARM7  TDMI-S  LPC2103  多功能电子钟 引用地址:基于ARM7 TDMI-S CPU的LPC2103的多功能电子钟

上一篇:车载GPS导航系统的设计
下一篇:使用STM32 的DSP库进行FFT变换

推荐阅读最新更新时间:2024-03-16 15:09

ARM7系列LPC2214芯片的调试报告
摘要:本文的主要内容是关于PHILIP公司ARM7系列LPC2214芯片的调试报告,以及在其基础上的网络通信程序设计的调试报告和KEIL公司的开源RTL操作系统下TCPNET不开源协议栈的工作报告;在具体论述我的调试过程的时候,我会把我查询的一些我认为正确的资料附在合适的位置,以供参考。 LPC2214启动代码部分 启动代码-汇编代码--做c语言的准备工作。包括向量表定义,堆栈初始化,系统变量初始化,中断系统初始化,i/o初始化,外围初始化,地址重映射等操作。 在开始之前我建议首先把ARM的指令系统熟悉一遍,然后结合启动代码熟悉指令的含义和具体操作,尤其需要的是要比较明确的知道startup.s文件中的伪指令的含义,这
[单片机]
基于便携式DAB接收机的MP3播放器设计方案
  引言   近年来,数字音频广播(Digital Audio Broadcasting,DAB)凭借其音质好,灵敏度高,频谱利用率高等诸多优点引起了国际通信广播行业的关注,并取得了飞速的进展。广电总局于2006年6月推出的《30~3000 MHz地面数字音频广播系统技术规范》,不仅使DAB在我国有了标准的支持,更对DAB在全国的普及产生了重大而积极的影响。考虑到便携式MP3播放器在当今社会的普及程度与消费者对其的依赖性,在DAB接收机中融合MP3解码功能对消费市场的开拓是很必要的。本文在不改动一款DAB接收整机原有性能的基础上,提出了一种适当加入MP3解码功能的可行性方案。   1 系统总体结构   1.1 DAB接收系统
[单片机]
智能防火防盗报警系统的设计
0 引言 现如今在学校的寝室里,学生贵重物品被盗、由于学生过失而引起着火等事故时有发生,这些都是一直以来困扰着学生、学工以及学校保卫处的“大问题”。传统的防范措施存在很大的弊端,比如当事故发生时,防护铁门、铁栏杆就会成为主人逃生的最大障碍。而采用智能防火防盗报警系统,便能很好地解决此类问题了。但是市场上防火防盗系统价格对大学生来讲过高,本系统便是针对大学宿舍,从低成本的角度来设计制作的。 1 系统组成及工作原理 本系统通过一个监控室和两个宿舍来模拟,通过RS 485总线来实现通信。考虑到现实中监控室要能监控整栋宿舍楼,因此采用功能强大的ARM7芯片LPC2103作为主机控制芯片,从机采用价格低廉的51系列单片机作为控制芯片。宿
[单片机]
智能防火防盗报警系统的设计
基于ARM7、AVR、UCOSII的发电厂大型除尘控制器设计方案
控制对象是 540脉冲控制阀,20个碟阀,3个温度检测点,2个冷风机组控制点,甲方要求控制器要有人机交互界面,温度控制点要可调,脉冲阀工作时间要可调,并且系统要能够在线检测出负载阀故障,比如开路,短路在系统运行时是不允许的必须及时的被检测出来。 整个系统有560阀,每个阀工作电流接近1A,如果按每个阀两根控制线的话将有1120根阀控制线,控制器距离现场有几百米,这样下来铜线价格超万元成本太高,所以系统采用矩阵扫描的方式进行阀控制大大节约用铜量。根据甲方要求我们将CCQ3000划分为4个硬件模块 : 1. 显示键盘模块,人机交互部分。 2. 温控模块,实现对关键测温点进行温度检测,和控制 ,温控模块并且负责CCQ3000机箱系
[单片机]
基于<font color='red'>ARM7</font>、AVR、UCOSII的发电厂大型除尘控制器设计方案
基于ARM7控制器的中英文翻译器的设计
为了改进某焊接设备只能输出打印英文单据的情况,设计了由高性能ARM7控制器——LPC2214为核心的英文转中文翻译器,详细论述了具体的硬件电路和优化的软件算法的设计原理,实验结果表明,翻译器对输入的英文数据量的大小无任何限制,能够显著降低系统硬件资源需求且能大大提升打印速度。   基于某焊接设备存储大量数据需要通过打印机输出,但由于该设备及其配套的微型热敏打印机只能英文打印,不能中文打印的问题,从而影响用户阅读。另外,原有的配套英文打印机具有打印速度缓慢、每一组数据间隔过大,浪费纸张等缺点。因此,为了解决上述问题,根据实际工程项目应用需要,提出一种基于ARM的英文转中文的翻译器设计方案,该设计是在原有设备和支持中文打印的热
[单片机]
Actel为嵌入ARM7功能的FPGA推出开发工具套装
Actel公司宣布推出CoreMP7开发工具套装,这是完整的软、硬件开发环境,针对该公司CoreMP7软ARM7处理器内核的执行而设。CoreMP7开发工具套装包含屡获殊荣的CoreMP7、具Actel ARM7功能的M7 ProASIC3器件和FPGA开发工具,为用户提供了一切所需工具,可以快速和简便地评估及设计以FPGA为基础的系统级芯片 (SoC) 应用。 Actel IP市务经理Mike Thompson称:“CoreMP7开发工具充分发挥了FPGA的灵活性结合快速推向市场和业界标准ARM7处理器技术的优势,简化了复杂SoC芯片的评估和开发工作。这套开发工具是一个完善的开发环境,包含构件组装、行为仿真、电路综合、布局、编
[新品]
ARM LPC2103定时器中断方式寄存器设置
定时器查询方式定时器初始化: 1、设置定时器分频数,为(x+1)分频 2、匹配通道X中断并复位TxTC 3、比较值(1S定时值) 4、启动并复位TxTC 如: T1PR = 99; // 设置定时器0分频为100分频,得110592Hz T1MCR = 0x03; // 匹配通道0匹配中断并复位T0TC T1MR0 = 110592/2; // 比较值(1S定时值) T1TCR = 0x03; // 启动并复位T0TC T1TCR = 0x01; 研究了好长一段时间,LPC210X的定时器,查询方式定时很简单如上面,但中断方式要操作好多寄存器,太麻烦,一直是一头雾水。好不容易理出了思路,现将一段例程粘贴备忘。 #include
[单片机]
ARM7单片机(学习ing)—(六)、SPI接口—02
六、SPI接口 六—(02)、SPI控制数码管(程序里有详细的步骤~~以及注意事项~~) 程序: MDK6_1.c //------------------------------------------------------------------------------ //SPI控制数码管显示 //首先还是先介绍一下大概的操作流程~~ //SPI时钟值计算如下:SPI时钟=Fpclk/SPCCR,式子中,SPCCR的值必须大于8的偶数 //------------------------------------------------------------------------------ //主机SPI的基
[单片机]
<font color='red'>ARM7</font>单片机(学习ing)—(六)、SPI接口—02
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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