计时器中断。设单片机计时器的晶振频率为12MHz,使用计时器0,在方式1下由P1.2输出25HZ的方波,通过P1.0输出,用中

已知单片机晶体振荡器的频率是12MHz,利用定时器0采用方式1在P1.0脚上输出0.2秒的方波_百度知道
已知单片机晶体振荡器的频率是12MHz,利用定时器0采用方式1在P1.0脚上输出0.2秒的方波
1)写出程序初始化步骤, 2)初值的计算过程畅阀扳合殖骨帮摊爆揩,3)在Proteus中画出原理图,并在Keil C51中编写程序.
我有更好的答案
按默认排序
#include&reg51.h&  sbit out = P1^0;void main(){  TMOD = 0x01;
//定时器0 16位定时器  TH0 = ()/256;
  TL0 = ()%256;
//0.02秒中断一次  EA=1;
//开总中断  ET0=1;
//开定时器0中断  TR0=1;
//允许计数  while(1);}void Time0() interrupt 1{
static num = 0;
TH0 = ()/256;  TL0 = ()%256;
//重新填初值 保证下次中断时间0.02s
if(num&=10)
//到0.畅阀扳合殖骨帮摊爆揩2s
//输出取反
}}对于初值的计算用12M晶振 单片机内部12分频 也就是说计数器每增加一个数的时间为 1/(12M/12) = 1us对于定时器来说最大定时时间为65536*1us=65.536ms &0.2s=200ms所以程序中设置定时时间为20ms 中断10次就是0.2s 然后输出引脚输出电平取反对于原理图 搭建一个最小系统就行以上程序现写的 你自己测试一下 应该没什么问题
其他类似问题
晶体振荡器的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁一个8031应用系统扩展了l片8155,晶振为12MHz,具有上电复位功能,P2.1~P2&#4..
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
单片机系统的扩展
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口当前位置: >>
MSP430单片机使用和对比
各类单片机的比较与 MSP430 的应用 付宇鹏概述:本文将市面上的主要型号的单片机进行比较和分析。主要以 MSP430 为核心阐述 其在电子设计竞赛中的主要编程应用。目录1、常用单片机比较 2、MSP430 特点与介绍 3、MSP430 编程技巧 4、电子设计竞赛中菜单框架的结构 5、单片机周围模块与程
序 6、 MSP430 常见应用附录:2005 年 A 题编程 1、常用单片机比较目前,我们常用的单片机有 8 位和 16 位的,八位单片机由于内部构造简单,体积小, 成本低廉,在一些较简单的控制器中应用很广。即便到了本世纪,在单片机应用中,仍占有 相当的份额。我接触过的 16 位的机型主要是 MSP430。AVR,C51 和 PIC 在基础型号上是八位 的,下面将这几种 8 位单片机性能进行比较。 a. 51 系列 应用最广泛的八位单片机首推 Intel 的 51 系列,由于产品硬件结构合理,指令系统规 范,加之生产历史“悠久” ,有先入为主的优势。世界有许多著名的芯片公司都购买了 51 芯片的核心专利技术,并在其基础上进行性能上的扩充,使得芯片得到进一步的完善,形成 了一个庞大的体系,直到现在仍在不断翻新,把单片机世界炒得沸沸扬扬。有人推测,51 芯片可能最终形成事实上的标准 MCU 芯片。51 系列单片机内部结构 51 系列优点之一是它从内部的硬件到软件有一套完整的按位操作系统, 称作位处理器, 或布尔处理器。 它的处理对象不是字或字节而是位。 它不光能对片内某些特殊功能寄存器的 某位进行处理,如传送、置位、清零、测试等,还能进行位的逻辑运算,其功能十分完备, 使用起来得心应手。 虽然其他种类的单片机也具有位处理功能, 但能进行位逻辑运算的实属 少见。51 系列在片内 RAM 区间还特别开辟了一个双重功能的地址区间,十六个字节,单元 地址 20H~2FH,它既可作字节处理,也可作位处理(作位处理时,合 128 个位,相应位地 址为 00H~7FH) ,使用极为灵活。这一功能无疑给使用者提供了极大的方便,因为一个较复 杂的程序在运行过程中会遇到很多分支,因而需建立很多标志位,在运行过程中,需要对有 关的标志位进行置位、清零或检测,以确定程序的运行方向。而实施这一处理(包括前面所 有的位功能) ,只需用一条位操作指令即可。 51 系列的另一个优点是乘法和除法指令,这给编程也带来了便利。八位除以八位的除 法指令,商为八位,精度嫌不够,用得不多。而八位乘八位的乘法指令,其积为十六位,精 度还是能满足要求的,用的较多。作乘法时,只需一条指令就行了,即 MULAB(两个乘数分 别在累加器 A 和寄存器 B 中。积的低位字节在累加器 A 中,高位字节在寄存器 B 中)。很多 的八位单片机都不具备乘法功能,作乘法时还得编上一段子程序调用,十分不便。 在 51 系列中,还有一条二进制-十进制调整指令 DA,能将二进制变为 BCD 码,这对于 十进制的计量十分方便。而在其他的单片机中,则也需调用专用的子程序才行。 Intel 公司 51 系列的典型产品是 8051, 片内有 4K 字节的一次性程序存储器 (OTP)Atmel 。 公司就将其改为电可改写的闪速存储器(Flash) ,容许改写 1000 次以上,这给编程和调试 带来极大的便利,其产品 AT89C51、AT89C52 ??等成为了当今最流行的八位单片机。51 系列的 I/O 脚的设置和使用非常简单,当该脚作输入脚使用时,只须将该脚设置为 高电平(复位时,各 I/O 口均置高电平) 。当该脚作输出脚使用时,则为高电平或低电平均 可。低电平时,吸入电流可达 20mA,具有一定的驱动能力;而为高电平时,输出电流仅数 十μ A 甚至更小(电流实际上是由脚的上拉电流形成的) ,基本上没有驱动能力。其原因是 高电平时脚也同时作输入脚使用, 而输入脚必须具有高的输入阻抗, 因而上拉的电流必须 很小才行。作输出脚使用,欲进行高电平驱动时,得利用外电路来实现,I/O 脚不通,电流 经 R 驱动 LED 发光;低电平时,I/O 脚导通,电流由该脚入地,LED 灭(I/O 脚导通时对地 的电压降小于 1V,LED 的域值 1.5~1.8V) 。 51 系列 I/O 脚使用简单,但高电平时无输出能力,可谓有利有弊。故其他系列的单片 机 (如 PIC 系列、 系列等) I/O 口进行了改进, AVR 对 增加了方向寄存器以确定输入或输出, 但使用也变得复杂。 一些简装的 51 产品也相应出现,如 Atmel 公司的 AT89C1051、AT89C2051、AT89C4051 等(闪速存储器分别为 1K、2K、4K 等,但不能外接数据存储器) ,指令系统与 AT89C51 完全 兼容,但引脚均为 20 脚,不光体积小,而且价格低廉,这使得其他的公司竞相仿照。 不过, 51 系列也有许多值得改进之处, 原 如运行速度过慢等。 当晶振频率为 12MHz 时, 机器周期达 1μ s,显然适应不了现代高速运行的需要。华邦公司(Winbond)生产的产品型号 为 W77 系列和 W78 系列, 系列与 AT89C 系列完全兼容。 系列为增强型, W78 W77 对原有的 8051 的时序作了改进, 每个机器周期从 12 个时钟周期改为 4 个周期, 使速度提高了三倍, 同时, 晶振频率最高可达 40MHz。W77 系列还增加了看门狗 WatchDog、两组 UART、两组 DPTR 数据 指针、ISP 等多种功能。 单片机的提速运行、双数据指针及 ISP 功能并非是 W77 系列所特有的,一些新的型号 的 51 系列产品大都有该功能,如 Philips 的 51LPC 系列、AT89 系列中的某些型号、STC89C 系列等等。有的单片机还附有 A/D、D/A 转换、片内 EEPROM 数据存储器、PWM 输出、I2C 总 线、上电复位检测、欠压复位检测等等,这些新系列的单片机,它们都兼容 8051 的指令系 统。增强功能的实现,大都是由片内新增的特殊功能寄存器来进行设置,这些寄存器被安排 在片内特殊功能寄存器区间(80~FFH)的预留地址上。 比较有代表性的产品还有 STC89C51RC、C 等等。可以这么说,新的 51 产 品几乎可以涵盖所有新的功能。由于新型号的芯片种类太多,此处不可能一一列举。 b.PIC 系列(Peripheral Interface Controller)PIC 单片机系列是美国微芯公司(Microship)的产品,是当前市场份额增长最快的单 片机之一。CPU 采用 RISC 结构,分别有 33、35、58 条指令(视单片机的级别而定) ,属精 简指令集。 51 系列有 111 条指令, 单片机有 118 条指令, 而 AVR 都比前者复杂。 采用 Harvard 双总线结构,运行速度快(指令周期约 160~200ns),它能使程序存储器的访问和数据存储 器的访问并行处理,这种指令流水线结构,在一个周期内完成两部分工作,一是执行指令, 二是从程序存储器取出下一条指令,这样总的看来每条指令只需一个周期(个别除外) ,这 也是高效率运行的原因之一。此外,它还具有低工作电压、 低功耗、驱动能力强等特点。PIC 系列单片机共分三个级别, 即基本级、 中级、 高级。 其中又以中级的 PIC16F873 A) PIC16F877 ( 、 (A) 用的 最 多, 本 文以这 两 种 单片 机 为例 进 行说 明 。 这两 种 芯片 除了引 出 脚 不同 外 (PIC16F873(A)为 28 脚的 PDIP 或 SOIC 封装;PIC16F877(A)为 40 脚的 PDIP 或 44 脚的 PLCC/QFP 封装) ,其他的差别并不很大。 PIC 系列单片机的 I/O 口是双向的, 其输出电路为 CMOS 互补推挽输出电路。 I/O 脚增加 了用于设置输入或输出状态的方向寄存器(TRISn , 其中 n 对应各口,如 A、B、C、D、E 等)从而解决了 51 系列 I/O 脚为高电平时同为输入和输出的状态。 , 当置位 1 时为输入状态, 且不管该脚呈高电平或低电平,对外均呈高阻状态;置位 0 时为输出状态,不管该脚为何种 电平,均呈低阻状态,有相当的驱动能力,低电平吸入电流达 25mA,高电平输出电流可达 20mA。相对于 51 系列而言,这是一个很大的优点,它可以直接驱动数码管显示且外电路简 单。它的 A/D 为 10 位,能满足精度要求。具有在线调试及编程(ISP)功能。 该系列单片机的专用寄存器 (SFR) 并不像 51 系列那样都集中在一个固定的地址区间内 (80~FFH), 而是分散在四个地址区间内, 即存储体 0 (Bank0: 00~7FH) 存储体 1(Bank1 : 、 80~FFH)、存储体 2(Bank2 :100~17FH)、存储体 3(Bank3 :180~1FFH)。只有 5 个专用 寄存器 PCL、STATUS、FSR、PCLATH、 INTCON 在 4 个存储体内同时出现。在编程过程中,少 不了要与专用寄存器打交道,得反复地选择对应的存储体,也即对状态寄存器 STATUS 的第 6 位(RP1)和第 5 位(RP0)置位或清零。 这多少给编程带来了一些麻烦。 对于上述的单片机, 它的位指令操作通常限制在存储体 0 区间(00~7FH) 。 数据的传送和逻辑运算基本上都得通过工作寄存器 W(相当于 51 系列的累加器 A)来进行,而 51 系列的还可以通过寄存器相互之间直接传送(如:MOV 30H, 20H;将寄存器 20H 的内容直接传送至寄存器 30H 中),因而 PIC 单片机的瓶颈现象比 51 系 列还要严重,这在编程中很有感受。 c、AVR 系列 AVR 单片机吸取了 PIC 及 8051 等单片机的优点, 同时在内部结构上还作了一些重大改进, 其主要的优点如下:程序存储器为价格低廉、 可擦写 1 万次以上、 指令长度单元为 16 位(字)的 FlashROM (即程序存储器宽度为 16 位,按 8 位字节计算时应乘 2) 。而数据存贮器为 8 位。因此 AVR 还是属于 8 位单片机。 采用 CMOS 技术和 RISC 架构, 实现高速(50ns)、 低功耗(μ A)、 具有 SLEEP(休眠)功能。AVR 的一条指令执行速度可达 50ns(20MHz),而耗电则在 1uA~ 2.5mA 间。AVR 采用 Harvard 结构,以及一级流水线的预取指令功能,即对程序的读取和 数据的操作使用不同的数据总线,因此,当执行某一指令时,下一指令被预先从程序存储器 中取出,这使得指令可以在每一个时钟周期内被执行。 高度保密。可多次烧写的 Flash 且具有多重密码保护锁定(LOCK)功能,因此可低价快 速完成产品商品化,且可多次更改程序(产品升级),方便了系统调试,而且不必浪费 IC 或 电路板,大大提高了产品质量及竞争力。 工业级产品。具有大电流 10~20mA(输出电流) 或 40mA(吸电流)的特点, 可直接驱动 LED、 或继电器。 SSR 有看门狗定时器(WDT)安全保护, 可防止程序走飞, 提高产品的抗干扰能力。超功能精简指令。 具有 32 个通用工作寄存器(相 当于 8051 中的 32 个累加器),克服了单一累加器数据处理造成的瓶颈现象。片内含有 128-4K 字节 SRAM, 可灵活使用指令运算, 适合使用功能很强的 C 语言编程, 易学、 易写、 易移植。 程序写入器件时, 可以使用并行方式写入(用编程器写入), 也可使用串行在线下载(ISP)、 在应用下载(IAP)方法下载写入。也就是说不必将单片机芯片从系统板上拆下拿到万用编 程器上烧录,而可直接在电路板上进行程序的修改、烧录等操作,方便产品升级,尤其是对 于使用 SMD 表贴封装器件,更利于产品微型化。通用数字 I/O 口的输入输出特性与 PIC 的 HI/LOW 输出及三态高阻抗 HI-Z 输入类 同, 同时可设定类同与 8051 结构内部有上拉电阻的输入端功能, 便于作为各种应用特性所 需(多功能 I/O 口),AVR 的 I/O 口是真正的 I/O 口,能正确反映 I/O 口的输入/输出的 真实情况。 单片机内集成有模拟比较器,可组成廉价的 A/D 转换器。像 8051 一样,有多个固定 中断向量入口地址,可快速响应中断,而不是像 PIC 一样所有中断都在同一向量地址,需 要以程序判别后才可响应,这会浪费且失去控制时机的最隹机会。同 PIC 一样,带有可设 置的启动复位延时计数器。AVR 单片机内部有电源上电启动计数器,当系统 RESET 复位上 电后,利用内部的 RC 看门狗定时器,可延迟 MCU 正式开始读取指令执行程序的时间。这 种延时启动的特性,可使 MCU 在系统电源、外部电路达到稳定后再正式开始执行程序,提 高了系统工作的可靠性,同时也可节省外加的复位延时电路。 许多 AVR 单片机具有内部的 RC 振荡器,提供 1/2/4/8MHz 的工作时钟,使该类单片 机无需外加时钟电路元器件即可工作,非常简单和方便。 有多个带预分频器的 8 位和 16 位功能强大的计数器/定时器 (C/T) 除了实现普通的定时和计数功能外, , 还具有输入捕获、 产生 PWM 输出等更多的功能。 性能优良的串行同/异步通讯 USART 口,不占用定时器。可 实现高速同/异步通信。 Mega8515 及 Mega128 等芯片具有可并行扩展的外部接口,扩展 能力达 64KB。 工作电压范围宽 2.7V~6.0V,具有系统电源低电压检测功能,电源抗干扰 性能强。有多通道的 10 位 A/D 及实时时钟 RTC。许多 AVR 芯片内部集成了 8 路 10 位 A/D 接口,如:mega8、mega16、mega8535 等。 AVR 单片机还在片内集成了可擦写 10 万次的 EEPROM 数据存储器, 等于又增加了一个 芯片,可用于保存系统的设定参数、固定表格和掉电后的数据的保存。即方便了使用,减小 了系统的空间,又大大提高了系统的保密性。 2、MSP430 特点与介绍A.处理能力强 MSP430 系列单片机是一个 16 位的单片机,采用了精简指令集(RISC)结构,具有丰富 的寻址方式(7 种源操作数寻址、4 种目的操作数寻址) 、简洁的 27 条内核指令以及大量 的模拟指令; 大量的寄存器以及片内数据存储器都可参加多种运算; 还有高效的查表处理指 令。这些特点保证了可编制出高效率的源程序。 B.运算速度快 MSP430 系列单片机能在 25MHz 晶体的驱动下,实现 40ns 的指令周期。16 位的数据宽 度、40ns 的指令周期以及多功能的硬件乘法器(能实现乘加运算)相配合,能实现数字信 号处理的某些算法(如 FFT 等) 。 C.超低功耗 MSP430 单片机之所以有超低的功耗,是因为其在降低芯片的电源电压和灵活而可控的 运行时钟方面都有其独到之处。 首先, MSP430 系列单片机的电源电压采用的是 1.8-3.6V 电 压。因而可使其在 1MHz 的时钟条件下运行时,芯片的电流最低会在 165μ A 左右,RAM 保 持模式下的最低功耗只有 0.1μ A。其次,独特的时钟系统设计。在 MSP430 系列中有两个 不同的时钟系统:基本时钟系统、锁频环(FLL 和 FLL+)时钟系统和 DCO 数字振荡器时钟 系统。可以只使用一个晶体振荡器(32768Hz) ,也可以使用两个晶体振荡器。由系统时钟系 统产生 CPU 和各功能所需的时钟。并且这些时钟可以在指令的控制下,打开和关闭,从而 实现对总体功耗的控制。 由于系统运行时开启的功能模块不同, 即采用不同的工作模式, 芯片的功耗有着显著的 不同。在系统中共有一种活动模式(AM)和五种低功耗模式(LPM0~LPM4) 。在实时时钟模式 下,可达 2.5μ A ,在 RAM 保持模式下,最低可达 0.1μ A 。 D.片内资源丰富 MSP430 系列单片机的各系列都集成了较丰富的片内外设。它们分别是看门狗(WDT) 、 模拟比较器 A、 定时器 A0 (Timer_A0) 定时器 A1 、 (Timer_A1) 定时器 B0 、 (Timer_B0) UART、 、 SPI、I2C、硬件乘法器、液晶驱动器、10 位/12 位 ADC、16 位Σ -Δ ADC、DMA、I/O 端口、 基本定时器(Basic Timer) 、实时时钟(RTC)和 USB 控制器等若干外围模块的不同组合。 其中,看门狗可以使程序失控时迅速复位;模拟比较器进行模拟电压的比较,配合定时器, 可设计出 A/D 转换器;16 位定时器(Timer_A 和 Timer_B)具有捕获/比较功能,大量的 捕获/比较寄存器,可用于事件计数、时序发生、 PWM 等;有的器件更具有可实现异步、同 步及多址访问串行通信接口可方便的实现多机通信等应用; 具有较多的 I/O 端口, P1、 P0、 P2 端口能够接收外部上升沿或下降沿的中断输入;10/12 位硬件 A/D 转换器有较高的转换 速率,最高可达 200kbps ,能够满足大多数数据采集应用;能直接驱动液晶多达 160 段; 实现两路的 12 位 D/A 转换;硬件 I2C 串行总线接口实现存储器串行扩展;以及为了增加 数据传输速度,而采用的 DMA 模块。MSP430 系列单片机的这些片内外设为系统的单片解决 方案提供了极大的方便。 另外,MSP430 系列单片机的中断源较多,并且可以任意嵌套,使用时灵活方便。当系 统处于省电的低功耗状态时,中断唤醒只需 5μ s。 E.方便高效的开发环境 MSP430 系列有 OPT 型、 FLASH 型和 ROM 型三种类型的器件, 这些器件的开发手段不 同。 对于 OPT 型和 ROM 型的器件是使用仿真器开发成功之后烧写或掩膜芯片; 对于 FLASH 型则有十分方便的开发调试环境, 因为器件片内有 JTAG 调试接口, 还有可电擦写的 FLASH 存储器,因此采用先下载程序到 FLASH 内,再在器件内通过软件控制程序的运行,由 JTAG 接口读取片内信息供设计者调试使用的方法进行开发。这种方式只需要一台 PC 机和一个 JTAG 调试器,而不需要仿真器和编程器。开发语言有汇编语言和 C 语言。[1]F.MSP430 单片机家族 MSP430x1xx 系列 基于闪存或 ROM 的超低功耗 MCU,提供 8MIPS,工作电压为 1.8V - 3.6V,具有高达 60KB 的闪存和各种高性能模拟及智能数字外设。 超低功耗低至: 0.1μ A RAM 保持模式 0.7 μ A 实时时钟模式 200μ A/MIPS 工作模式 在 6μ s 之内快速从待机模式唤醒 。 器件参数: 闪存选项:1KB C 60KB ROM 选项:1KB C 16KB RAM 选项:512B C 10KB GPIO 选项:14、 22、48 引脚 ADC 选项:10 和 12 位斜率 SAR 其它集成外设:模拟比较器、DMA、硬件乘 法器、SVS、12 位 DAC MSP430F2xx 系列 基于闪存的超低功耗 MCU,在 1.8V - 3.6V 的工作电压范围内性能高达 16MIPS。包含 极低功耗振荡器 (VLO)、 内部上拉/下拉电阻和低引脚数选择。 超低功耗低至: 0.1μ A RAM 保 持模式 0.3μ A 待机模式 (VLO) 0.7μ A 实时时钟模式 220μ A/MIPS 工作模式 在 1μ s 之内超快速地从待机模式唤醒。 器件参数: 闪存选项: 1KB C 120KB RAM 选项: 128B C 8KB GPIO 选项:10、16、24、32、48、64 引脚 ADC 选项:10 和 12 位斜率 SAR、16 位 Σ Δ ADC 其它集成外设:模拟比较器、硬件乘法器、DMA、SVS、12 位 DAC、运算放大器 MSP430C3xx 系列 旧款的 ROM 或 OTP 器件系列, 工作电压为 2.5V - 5.5V, 高达 32KB ROM、 4MIPS 和 FLL。 超低功耗低至: 0.1μ A RAM 保持模式 0.9μ A 实时时钟模式 160μ A/MIPS 工作模式 在 6 μ s 之内快速从待机模式唤醒 。 器件参数: ROM 选项: 2KB C 32KB RAM 选项: 512B C 1KB GPIO 选项:14、40 引脚 ADC 选项:14 位斜率 SAR 其它集成外设:LCD 控制器、硬件乘 法器 。 MSP430x4xx 系列 基于 LCD 闪存或 ROM 的器件系列,提供 8-16MIPS,包含集成 LCD 控制器,工作电压 为 1.8V-3.6V,具有 FLL 和 SVS。低功耗测量和医疗应用的理想选择。超低功耗低至: 0.1μ A RAM 保持模式 0.7μ A 实时时钟模式 200μ A/MIPS 工作模式 在 6μ s 之内快速从 待机模式唤醒。器件参数:闪存/ROM 选项:4kB C 120KB RAM 选项:256B C 8KB GPIO 选 项:14、32、48、56、68、72、80 引脚 ADC 选项:10 和 12 位斜率 SAR、16 位 Σ -Δ ADC 其它集成外设: LCD 控制器、 模拟比较器、 位 DAC、 12 DMA、 硬件乘法器、 运算放大器、 USCI 模块 。 MSP430F5xx 系列 新款基于闪存的产品系列,具有最低工作功耗,在 1.8V-3.6V 的工作电压范围内性能 高达 25MIPS。包含一个用于优化功耗的创新电源管理模块。超低功耗低至:0.1μ A RAM 保 持模式 2.5μ A 实时时钟模式 165μ A/MIPS 工作模式 在 5μ s 之内快速从待机模式唤醒。 器件参数:闪存选项:高达 256KB RAM 选项:高达 16KB ADC 选项:10 和 12 位 SAR 其 它集成外设:USB、模拟比较器、DMA、硬件乘法器、RTC、USCI、12 位 DAC [2] G.MSP430 与 89C51 的比较 首先,89C51 单片机是 8 位单片机。其指令是采用的是复杂指令集(CISC) ,共具有 111 条指令,12 个时钟周期 = 1 个指令周期。而 MSP430 单片机是 16 位单片机,采用了精简指 令集(RISC)结构,只有简洁的 27 条指令,1 个时钟周期 = 1 个指令周期,大量的指令则 是模拟指令, 众多的寄存器以及片内数据存储器都可参加多种运算。 这些内核指令均为单周 期指令,功能强,运行的速度快。 其次,89C51 单片机本身的电源电压是 5V,有两种低功耗方式:待机方式和掉电方式。 正常情况下消耗的电流为 24mA ,在待机状态下,其耗电电流仍为 3mA ;即使在掉电方式 下,电源电压可以下降到 2V ,但是为了保存内部 RAM 中的数据,还需要提供约 50μ A 的 电流。而 MSP430 系列单片机在低功耗方面的优越之处,则是 89C51 系列不可比拟的。正因 为如此,MSP430 更适合应用于使用电池供电的仪器、仪表类产品中。 再者,89C51 系列单片机由于其内部数据总线是 8 位的,其内部功能模块基本上都是 8 位的虽然经过各种努力其内部功能模块有了显著增加, 但是受其结构本身的限制很大, 尤其 模拟功能部件的增加更显困难。 MSP430 系列其基本架构是 16 位的,同时在其内部的数据 总线经过转换还存在 8 位的总线,在加上本身就是混合型的结构,因而对它这样的开放型 的架构来说,无论扩展 8 位的功能模块,还是 16 位的功能模块,即使扩展模/数转换或数/ 模转换这类的功能模块也是很方便的。 最后,在开发工具上面,对于 89C51 来说,不能在线编程。对于 MSP430 系列而言,由 于引进了 Flash 型程序存储器和 JTAG 技术,不仅可以实现在线编程和仿真,而且使开发 工具变得简便,价格也相对低廉。3、MSP430 编程技巧常用语句:1、条件语句 语句表达形式有 3 种(a、b、c): a if(条件表达式) 语句 b if(条件表达式) 语句 1 else 语句 2 c if(条件表达式) 语句 1 else if(条件表达式) 语句 2 else if(条件表达式) 语句 3 ?? 2、开关语句 switch(表达式) { case 常量表达式 1:语句 1 case 常量表达式 2:语句 2 ?? default: 语句 d }3、循环语句 while(条件表达式) 语句; 当条件满足时, 就反复执行后面的语句, 一直执行到条件不满足时。 以软件延时程序 为例说明该语句是如何执行的。 void delay(long v) { while(v!=0)v--; } do 语句 while(条件表达式) 先执行一次循环体的语句, 再判断条件 是否满足,以决定是否再执行循环体。下面 的程序将数组 BUFF[20]中的全部数据相加。 Int x=0; Char I=0; Do{ x =BUFF[I] + I=I+1; } while(I&20); for([初值设定表达式]; [循环条件表达式]; [条件更新表达式])语句 for 语句常用于需固定循环次数的循环。 下面的程序段同样实现将数组 BUFF[20]中 的全部数据相加的功能。 Int x=0; Char I=0; for(I=0;I&20;I++) x =BUFF[I] + ?? goto 语句标号 goto 语句常用于跳转到一个固定的地 址标号。其中固定的地址标号是一个带“: 的标志符。比如: ?? MM:?? ?? goto MMM ?? 4、函数的定义与调用 函数类型 函数名(形式参数表) 形式参数说明 { 局部变量定义函数体语句 } [存储变量类型] interrupt [中断矢量变量] 函数类型 函数名(形式参数表) 形式参数说明 { 局部变量定义 函数体语句 } 经常使用的延时函数 void delay(long v) { while(v!=0)v--; } delay(100)究竟延时多久呢?就是这句话 执行需要的时间。 时间等于:机器周期×需要的机器周期数 (在仿真环境中可以测试出来) PnDIR 方向寄存器 1 为输出、0 为输入 PnOUT 输出寄存器 1 输出高、0 为低 PnIN 输入寄存器 读出口线的状态 PnSEL 第二功能寄存器 n=1,2,3,4,5,6,7,8 引脚使用举例:控制连接在 P5.1 口线的发 光二极管的亮与熄: 首先、P51 为输出 ---P5DIR = 2; 亮 输出 1 ---P5OUT = 2 ; 熄灭 输出 0 ---P5OUT = 0 ;4、电子设计竞赛中菜单框架的结构程序设计就是用一行行源程序来实现完成一定的设计任务。 根据设计任务的类型和复杂 程度的不同,程序设计的方法是多种多样的,但总的来说还是可以归纳 以下几个设计步骤: 1、确定算法和思路,这包括软硬件实现的方法。确定算法和思路,实际上就是确定完 成任务的方案,一般思路可用流程图去体会能否实现。它是非常重要的步骤。 2、确定数据量,主要是工作单元的数据量,以确定分配存放的单元,这里对芯片的选型 很重要。 3、确定使用的功能模块,主要根据实现的目标而定。 4、确定使用的符号变量,标注符号的含义。 5、用流程图来描述程序流程。 6、根据流程图用汇编指令要求来编写汇编指令代码 7、进行代码编译、调试、分析、查纠错、运行直到完成 CCS 集成开发环境简介用于 TI 嵌入式处理器的集成型开发环境(IDE) ? 包括 debugger, compiler, editor, simulator, OS? ? 该环境基于 Eclipse 开源软件框架 ? TI 对其扩展,支持全系列的 TI 嵌入式控制器(430,DSP,ARM, OMAP?) ? 目前软件版本――CCS v5 ? 集成更多的工具 ? 操作系统应用程序开发(Linux, Android?) ? 代码分析,源控制? ? 支持 Linux 我在本次竞赛中使用 MSP5529 单片机, 利用 CCS5v3 开发环境。 主要利用到的资源有 GPIO 口,定时器,AD 等,下面先做简单介绍。 1、GPIO 寄存器概述 GPIO 口都是按组规划,有的芯片是 8 个 GPIO 口一组,有的是 16 个或 32 个为一组。一般每 个 GPIO 口都需要做两个寄存器位: 一是选择口线方向 (输入输出) 二是需要一个数据位 (用 于设置输出数据和读取输入数据) 。所以一组 GPIO 口至少会有两个寄存器 GPIOxDIR 和 GPIOxDATA。 GPIOxDIR:控制各个 GPIO 口的方向; GPIOxDATA:用于各个 GPIO 口的输入输出数 据 具有中断能力的端口:P1 和 P2。 端口 P1 和 P2 具有输入输出、 中断和外部模块功能。 这些功能可以通过它们各自 9 个控制寄 存器的设置来实现。不具有中断能力的端口:P3 和其他端口 P3 和其他端口没有中断能力, 其余功能同 P1 和 P2,可以实现输入/输出功能和外围模块功能。端口 COM 和 S 这些端口实 现与液晶片的直接接口。COM 端口为液晶片的公共端,S 口为液晶片的段码端。 2、MSP430 定时器功能 定时功能模块是 MSP430 应用系统中经常用到的重要部分,可用来实现定时控制、延迟、频 率测量、脉宽测量和信号产生、信号检测等等。?一般来说,MSP430 所需的定时信号可以 用软件和硬件两种方法来获得。? MSP430 系列有丰富定时器资源:看门狗定时器(WDT) , 定时器 A(Timer_A) ,定时器 B(Timer_B)和定时器 D(Timer_D)等。 下图是开发板例程中的程序框图, 基本思路是固定化的, 不同的地方主要是在于个实验 不同功能的模块中,因此我将其作为模仿,通过所需要的开设模块化,实现简单的移植,能 够实现方便快捷的编程。这么说可能无法比较出这么设计框架的优越性,下面以我校赛中以 MSP430F149 的程序 框架为例,如下图。 首先,移植性方面,基本思路是一样的,将各个基本外设模块化,使用时初始化后即可 使用,比较方便。 其次,编程方面,下图的程序依靠扫瞄按键,消耗资源。例程中尽量使用中断,包括按 键中断,定时器中断,看门狗中断和 AD 中断,因此,效率和功耗方面更胜一筹。在第一次 培训的 A 题中我就一次为思路进行编写。程序将贴在附录中。 开始初 始化主 菜 单是否为功能 选项?等待进入功能界面是否有键按 下?是否返回主 菜单?判断按键功能结束 MSP430 微控制器标准软件设计流程 MSP430 微控制器软件设计的标准流程均可参考图。该标准的软件流程可将系统整体功耗降至最低。 图所描述的软件流程代码是基于中断程 序的,平时 MCU 处于睡眠状态,直到有中断产生时 MCU 被唤醒,最大程度降低系统功耗,优 化电源效率。MSP430 微控制器的低功耗模式由状态寄存器 SR 的控制位控制,在执行中断服 务子程序之前,状态寄存器 SR 的低功耗模式控制位可以被优先压栈。当中断服务子程序返 回时,主程序调用中断之前的低功耗模式控制位,从而进入中断之前的低功耗模式状态。当 然,如果我们在 ISR 中断服务子程序返回前修改了保存在 SR 中的低功耗模式控制位,那么 ISR 中断子程序执行完之后,主程序流程可以转到另一个不同的低功耗工作模式。中断唤醒 机制作为 MSP430 微控制器内部低功耗模式的一部分,允许系统快速唤醒,响应中断事件。 例如,当一中断事件发生之前 MSP430 微控制器处于低功耗 LPM0 模式,MCU 在执行中断服务 子程序之前首先向堆栈保存 SR 中的低功耗模式控制位值然后清除 SR 值,清除 SR 值使 MCU 从 LPM0 模式进入到执行中断活动模式状态。在 ISR 中断服务子程序中,软件设计者可以写 一条语句清除雷奥 SR 中的低功耗模式控制位,当中断程序完成后,MCU 从堆栈中重新装载 调用各自寄存器的状态值。如果没有修改 SR 的低功耗模式控制位,退出中断后系统仍然返 回进入 LPM0 低功耗模式,若此时已修改 SR 控制位,当从 ISR 中断程序退出后,系统会工作 于活动模式时,并且按进入中断之前的 PC 指针所指的地址继续执行程序。由于可以在 ISR 中断服务子程序中改变低功耗模式, 所以设计者可以选择在 ISR 程序中执行全部任务, 也可 以选择在 ISR 唤醒 MCU 后在主程序中处理任务。 ISR 程序中处理时确保能立即响应中断事 在 件,中断事件发生时即能立刻处理中断任务,但是,在处理一个中断事件时,其它中断将不 能被载入,直到该中断任务完成,而这样长时间的中断将会降低系统的响应灵敏,所以设计 者须根据不同系统要求选择最佳处理方式。 5、单片机周围模块与程序集成在开发板上的模块: Dogs102-6 液晶屏液晶显示电路中,液晶为 102× 点阵 LCD,采用 SPI 模式实现数据的传输,在该电路中数 64 据传输是单向的,数据只允许写入,其中 LCD_CS(P7.4)为片选信号、LCD_D/C(P5.6) 为 命 令 数 据 切 换 信 号 、 SCLK ( P4.3/PM_UCB1CLK ) 为 数 据 传 输 时 钟 信 号 、 SIMO (P4.1/PM_UCB1SIMO)为从设备输入主设备输出信号、LCD_RST(P5.7)为液晶复位信 号、VCC 为显示电源提供信号,液晶引脚说明如图 3.2 所示,液晶显示模块电路引脚设置 如下(在 Board_init()函数中) extern void Dogs102x6_init(void); extern void Dogs102x6_backlightInit(void); extern void Dogs102x6_disable(void); extern void Dogs102x6_writeCommand(uint8_t* sCmd, uint8_t i); extern void Dogs102x6_writeData(uint8_t* sData, uint8_t i); extern void Dogs102x6_setAddress(uint8_t pa, uint8_t ca); extern uint8_t Dogs102x6_getContrast(void); extern uint8_t Dogs102x6_getBacklight(void); extern void Dogs102x6_setContrast(uint8_t newContrast); extern void Dogs102x6_setBacklight(uint8_t brightness); extern void Dogs102x6_setInverseDisplay(void); extern void Dogs102x6_clearInverseDisplay(void); extern void Dogs102x6_scrollLine(uint8_t lines); extern void Dogs102x6_setAllPixelsOn(void); extern void Dogs102x6_clearAllPixelsOn(void); extern void Dogs102x6_clearScreen(void); extern void Dogs102x6_charDraw(uint8_t row, uint8_t col, uint16_t f, uint8_t style); extern void Dogs102x6_charDrawXY(uint8_t x, uint8_t y, uint16_t f, uint8_t style); extern void Dogs102x6_stringDraw(uint8_t row, uint8_t col, char *word, uint8_t style); extern void Dogs102x6_stringDrawXY(uint8_t x, uint8_t y, char *word, uint8_t style); extern void Dogs102x6_clearRow(uint8_t row); extern void Dogs102x6_pixelDraw(uint8_t x, uint8_t y, uint8_t style); extern void Dogs102x6_horizontalLineDraw(uint8_t x1, uint8_t x2, uint8_t y, uint8_t style); extern void Dogs102x6_verticalLineDraw(uint8_t y1, uint8_t y2, uint8_t x, uint8_t style); extern void Dogs102x6_lineDraw(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t style); extern void Dogs102x6_circleDraw(uint8_t x, uint8_t y, uint8_t radius, uint8_t style); extern void Dogs102x6_imageDraw(const uint8_t IMAGE[], uint8_t row, uint8_t col); extern void Dogs102x6_clearImage(uint8_t height, uint8_t width, uint8_t row, uint8_t col);齿轮电位计(1)下面函数的功能为齿轮电位计的初始化。extern void Wheel_init(void);(2)下面函数的功能为确定齿轮电位计的位置,其返回值为齿轮电位计的位置,取值范围 为0~7。 extern uint8_t Wheel_getPosition(void); (3)下面函数的功能为得到并返回齿轮电位计的采样值,注意,该函数内部包含采样软件 消抖。extern uint16_t Wheel_getValue(void);(4)下面函数的功能为禁用齿轮电位计。extern void Wheel_disable(void);(5)下面函数的功能为启用齿轮电位计。extern void Wheel_enable(void);扫描型矩阵键盘 扫描键盘为行列扫描 扫描键盘的完整程序为: 1、判断是否有按键按下; 2、判断是哪个按键按下; 3、判断是否按键松开。 电路原理图 行线 P11、P12、P13 列线 P14、P15、P16、P17 全上拉 首先、 设置端口: 行线为输出、 列线为输入。 然后、行线输出为低电平 最后判断:如果有按键按下,则列线不全为 高电平, 如果没有键按下, 则列线全部为 高电平。 char Keyj(void) { P1DIR = 0x0E; // set p1.1~p1.3 设置为输出模式 P1OUT = 0x00; // p1.1~p1.3 输 出值清零 return(P1IN & 0x f 0 ) ; } 如果返回值为 0xf0 则 有按键按下吗? 以后直接调用这个函数, 即可判断有否按键 按下。 注意:有键按下后,需要消抖动 使用延时再判断的方法即可消除抖动 If(Keyj() != 0xf0 ) { delay(200); //延时消除抖动 If(Keyj() == 0xf0 ) //没有按键 为抖动 else //确实有键按下 { //处理 } } 如何查找哪个按键按下 方法为:一个一个地查找。 AD 键盘先第一行输出 0,检查列线是否非全高 否则第二行输出 0,检查列线是否非全高 否则第三行输出 0,检查列线是否非全高 如果某行输出 0 时,查到列线非全高,则该 行有按键按下。 根据第几行线输出 0 与第几列线读入为 0, 即可判断在具体什么位置的按键按下。 下页具体程序。 void check_Key(void){ unsigned char row ,col,tmp1,tmp2; // tmp1 用来设置 P1OUT 的值, P1.1~P1.3 中有一个为 0 tmp1 = 0x08; for(row=0;row&3;row++){ P1OUT |= 0x0E; // p1.1~P1.3=1; P1OUT -= tmp1; // P1.1~p1.3 中有一 个为 0 tmp1 = tmp1/2; // tmp1 右移一位 if ((P1IN & 0xf0) &0xf0){ // 是否 P1IN 的 P1.4~P1.7 中有一位为 0 tmp2 = 0x80;//tmp2 用于检测出那为 0 for(col=0;col&0x04;col++){ // 列检测 if((P1IN &tmp2)==0x00){ // 是否是该列 key_val =key_Map[ row*4 +col] ; // 获取键值 // 退出循环 } tmp2 /= 2; // tmp2 右移 虽然矩阵键盘非常便利,比如这次新做的 MSP4306638 就接入了矩阵键盘。但是由于单 片需要很多外设, 引脚不够用, 所以这次 F5529 所使用的是 AD 键盘, 这样可以节省 7 个 GPIO 口,用一个 AD 就可以读出选择的值。程序如下:uint8_t Key_getValue(void) { uint8_t K ADC12IE = 0x01; ADC12CTL0 |= ADC12ENC; ADC12CTL0 |= ADC12SC; __bis_SR_register(LPM0_bits + GIE); interrupts __no_operation(); ADC12IE = 0x00; Key = (KeyData && 4) & 0xFF; if(Key&0x02)return '0'; if(Key&0x12&&Key&0x0d)return '1'; if(Key&0x22&&Key&0x1d)return '2'; if(Key&0x32&&Key&0x2d)return '3'; if(Key&0x42&&Key&0x3d)return '4'; if(Key&0x52&&Key&0x4d)return '5'; if(Key&0x62&&Key&0x5d)return '6'; if(Key&0x72&&Key&0x6d)return '7'; if(Key&0x82&&Key&0x7d)return '8'; if(Key&0x92&&Key&0x8d)return '9'; if(Key&0xa2&&Key&0x9d)return 'A'; if(Key&0xb2&&Key&0xad)return 'B'; if(Key&0xc2&&Key&0xbd)return 'C'; if(Key&0xd2&&Key&0xcd)return 'D'; // For debugger // Enable conversions // Start convn - software trigger // Enter LPM4, Enable if(Key&0xe2&&Key&0xdd)return 'E'; if(Key&0xf2&&Key&0xed)return 'F'; return 'N'; }利用中断方式读出键入的值。使用很方便。 AD 和 DA 模块 单片机内部有 12 个独立的 12 位 ADC,是永恒方便,但测试的幅度范围有限,因此我们 选用了 ADS8509 串行 AD,他的优点在于能够单电源供电,并且可以测量负电平这对于实际 测量应用价值很大,不过我没弄好使它,这里先不写了。 DA 我们使用的是 TLV5638,没有外接电路,两路输出,对于做比较电路,产生参考电压 等十分方便,我把代码贴在下面。/* * TLV_5638.c * * * */ #include &TLV_5638.h& #include &msp430.h& void InitIO(void) { PinDIN_ PinCS_ PinSCLK_ PinDIN_ PinCS_ PinSCLK_ } //向SPI写16位数据函数:SPIWrite( ) void SPIWrite(uint16_t temp) { uint8_ PinCS_ for(i=0;i&16;i++){ if(temp&0x8000)PinDIN_else PinDIN_ PinSCLK_ temp&&=1; __delay_cycles(10); PinSCLK_ __delay_cycles(10); } Created on:
Author: Administrator PinCS_ } //将电压值转换为对应的12位数字量函数:VoltToData( ) uint16_t VoltToData(uint16_t ref,float ex_ref,float out_volt) { uint16_ switch(ref){ case EXTERNAL:temp=(int)((out_volt*4096)/(2*ex_ref)); case IN_1024:temp=(int)((out_volt*4096)/(2*1.024)); case IN_2048:temp=(int)((out_volt*4096)/(2*2.048)); default: } return(temp&0xfff); } //设置DAC A(即A通道)输出函数:SetDAC_A( ) void SetDAC_A(uint16_t speed,uint16_t ref,float ex_ref,float temp) { uint16_t ModCMD; uint16_t D ModCMD=0x9000|(speed&&14)|(ref); Data=VoltToData(ref,ex_ref,temp); Data=Data|0x8000|(speed&&14); SPIWrite(ModCMD); __delay_cycles(1000); SPIWrite(Data); } //设置DAC B(即B通道)输出函数:SetDAC_B( ) void SetDAC_B(uint16_t speed,uint16_t ref,float ex_ref,float temp) { uint16_t ModCMD; uint16_t D ModCMD=0x9000|(speed&&14)|(ref); Data=VoltToData(ref,ex_ref,temp); Data=Data|0x0000|(speed&&14); SPIWrite(ModCMD); __delay_cycles(1000); SPIWrite(Data); }//设置DAC A与DAC B同时输出函数SetDAC_AB( ) void SetDAC_AB(uint16_t speed,uint16_t ref,float ex_ref,float temp1,float temp2) { uint16_t ModCMD; uint16_t DataA,DataB; ModCMD=0x9000|(speed&&14)|(ref); DataA=VoltToData(ref,ex_ref,temp1); DataA=DataA|0x8000|(speed&&14); DataB=VoltToData(ref,ex_ref,temp2); DataB=DataB|0x1000|(speed&&14); SPIWrite(ModCMD); SPIWrite(DataB); SPIWrite(DataA); }DDS 模块 AD9850 AD9850 能够接 125M 有源晶振,信号产生范围非常广,并且能够产生两路互补的方波和 正弦波。参考资料和例程都很多,我在这里就不赘述了,基本只要改下引脚就可以了。6、MSP430 常见应用在嵌入式系统设计中,PWM 脉宽调制信号常常用来产生模拟信号。大多数嵌入式微控制 器的系统均需要产生不同的模拟信号,通常采用集成或独立的 DA 转换器来实现。PWM 信号 常常也可以用来产生系统所需的模拟信号,包括产生直流和交流信号。下面以 MSP430F149 微控制器 Timer B 模块的 DA 转换为例,可以产生上文提到的正弦波、斜波、直流电平以及 在直流电平上增加正弦波产生的交流偏置信号。 PWM 信号为频率固定、占空比变化的数字信号,基本波形如图 1 所示。如果 PW M 信号 的占空比随时间而改变,那么信号经滤波后将输出幅度变化的模拟信号。因此通过改变 PWM 信号的占空比,即可产生不同的模拟信号。PWM 信号实现 DA 转换(简称 PWM DAC)的原理框图 如图 2 所示。TI 公司的一些语言处理技术也通常采用 PWM DAC 方式实现。 图1图2通常PWM 信号的输出频率等于DAC的刷新频率,因为可以将PWM 占空比的每一次变化等效于 一次DA转换的采样。PWM定时器的频率取决于PWM信号的频率和所需的分辨率,表示为 FcdcI=F×K ,其中F k为PWM定时器频率,F 为PWM信号频率,即DAC的更新频率,n为DAC所 需的比特分辨率。 接下来将描述如何利用8一bit PWM DAC产生一个250Hz的正弦波和1 25Hz的斜波信号。 采样频率为8kHz,每个正弦波周期采样32个值(16x过采样),每个斜波周期采样64次(32x过 采样)。即PWM信号所需的频率为8kHz,所需的PWM时钟为2.048MHz。设计中,PWM 信号的频 率应高于正弦波频率或产生该信号的带宽,因为产生PWM信号频率越高,所需滤波器要求越 低,且越容易确定合适的滤波器。叠加的DC和AC信号通过PWM DAC产生的信号可以叠加在一起,将2/3VCC电平加到正弦波上, 产生一个偏置的正弦波信号的电路原理图如图6所示。 通过PWM输出可以很容易独立地调整交 流和直流信号。例如,正弦信号保持不变,直流偏置可以简单的通过改变PWM占空比产生所 需的直流电平。当然,使用其它单独的滤波器和加法放大器也可以达到相同的结果。 附录:本次培训A题参考程序: Main.c#include &msp430.h& #include &HAL_Dogs102x6.h& #include &HAL_Board.h& #include &HAL_PMM.h& #include &HAL_UCS.h& #include &Key_Wheel.h& #include &MainMenu.h& /* * main.c */ void main(void) { uint8_t contrast = *((unsigned char *)contrastSetpointAddress); //读取FLASH中对比度值 uint8_t brightness = *((unsigned char *)brightnessSetpointAddress); //读取FLASH中背光值 WDTCTL = WDTPW | WDTHOLD; Board_init(); SetVCore(3); LFXT_Start(XT1DRIVE_0); 为时钟参考 // Set system clock to max (25MHz) Init_FLL_Settle(2); 钟设为最大25MHZ SFRIFG1 = 0; SFRIE1 |= OFIE; // Globally enable interrupts __enable_interrupt(); // Set up LCD Dogs102x6_init(); Dogs102x6_backlightInit(); // Contrast not programed in Flash Yet if (contrast == 0xFF) 将对比度值设为11(默认) // Set Default Contrast contrast = 11; // Brightness not programed in Flash Yet //若当前FLASH中无对比度值,则 //使能全局中断 //初始化LCD //背光初始化 //清中断标志 //使能晶振失效中断 //利用FLL(锁频环)将系统时 //设VCore为最大 //利用LFXT1(32.768kHZ)作 // Stop watchdog timer if (brightness == 0xFF) 背光值设为11(默认) // Set Default Brightness brightness = 11; Dogs102x6_setBacklight(brightness); Dogs102x6_setContrast(contrast); Dogs102x6_clearScreen(); Dogs102x6_stringDraw(3, 0, & DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(4, 0, & DOGS102x6_DRAW_NORMAL); Welcome to//若当前FLASH中无背光值,则将//设置初始背光值 //设置初始对比度值 //清屏 &, &,Our Team FLCDogs102x6_stringDraw(6, 0, &Wait for a moment&, DOGS102x6_DRAW_INVERT); Dogs102x6_stringDraw(7, 0, & Fuck You Bitch! &, DOGS102x6_DRAW_INVERT); __delay_cycles(2400000); Dogs102x6_clearScreen(); InitADC(); while(1) { Menu_one(); } } 菜单 /* * MainMenu.c * * * */ #include &msp430.h& #include &MainMenu.h& #include &stdint.h& #include &HAL_Dogs102x6.h& #include &Key_Wheel.h& #include &ADS_8509.h& #include &TLV_5638.h& #include &AD9850.h& #include &FPGA_Interface.h& static const char *const MenuText[] = { &Sin Generator&, Created on:
Author: Administrator //清屏 &1. Sin&, &2. FM&, &3. AM&, &4. ASK&, &5. PSK& }; static const char *const FMText[] = { &Shift Sel&, &1. 5KHz&, &2. 10KHz&, }; static const char *const SIN_Text[] = { &Sin_generator&, &1. Fre Set Up&, &2. Fre Step Set& }; uint8_t Menu_Select(char **menuText, uint8_t numItems); void ReDraw(char **menuText , int menu_num , int numItems); void SubMenu_1(void); void SubMenu_2(void); void SubMenu_3(void); void SubMenu_4(void); void SubMenu_5(void); void Menu_one(void) { uint8_t selection_wheel = 0; Init_Sin(); //====================== USE WHEEL TO SELECT MENU AND BUTTON TO CONFIRM================ selection_wheel = Menu_Select((char **)MenuText, 5); switch(selection_wheel) { case 1 : Menu_Sel_En_ __delay_cycles(10); Menu_Sel0_ Menu_Sel1_ Menu_Sel2_ __delay_cycles(10); Menu_Sel_En_ SubMenu_1(); case 2 : Menu_Sel_En_ __delay_cycles(10); Menu_Sel0_ Menu_Sel1_ Menu_Sel2_ __delay_cycles(10); Menu_Sel_En_ SubMenu_2(); case 3 : Menu_Sel_En_ __delay_cycles(10); Menu_Sel0_ Menu_Sel1_ Menu_Sel2_ __delay_cycles(10); Menu_Sel_En_ SubMenu_3(); case 4 : Menu_Sel_En_ __delay_cycles(10); Menu_Sel0_ Menu_Sel1_ Menu_Sel2_ __delay_cycles(10); Menu_Sel_En_ SubMenu_4(); case 5 : Menu_Sel_En_ __delay_cycles(10); Menu_Sel0_ Menu_Sel1_ Menu_Sel2_ __delay_cycles(10); Menu_Sel_En_ SubMenu_5(); default: Dogs102x6_stringDraw(7, 0, &Press B 2 confirm&, DOGS102x6_DRAW_INVERT); }//=================================================================== ================== } uint8_t Menu_Select(char **menuText, uint8_t numItems) { uint8_ uint8_t position = 0; uint8_t lastPosition = 9; char key_confirm = ' '; if (numItems & 7){ 8 lines tall = 1 // title line + 7 items max numItems = 7; } Dogs102x6_clearImage(numItems + 1, 102, 0, 0); Dogs102x6_stringDraw(0, 0, menuText[0], DOGS102x6_DRAW_NORMAL); // Print the title //key_confirm = Key_getValue(); while (key_confirm != 'B') active until selection // is made { position = Wheel_getPosition(); if (position & numItems){ position = numI } else if (position == 0){ position = 1; } if (position != lastPosition) position if it is // changed { for (i = 1; i & numItems + 1; i++) menu items // Display // Update // Menu // Screen is { if (i != position){ Dogs102x6_stringDraw(i, 0, menuText[i], DOGS102x6_DRAW_NORMAL); } else { // Highlight item at current position Dogs102x6_stringDraw(i, 0, menuText[i], DOGS102x6_DRAW_INVERT); } } lastPosition = } key_confirm = Key_getValue(); __delay_cycles(1000); if(key_confirm == 'F') return 0; } } void SubMenu_1(void) { uint8_t selection_wheel = 0; Dogs102x6_clearScreen(); char selection_key = 'N'; selection_key = Key_getValue(); while(selection_key != 'F'){ while(selection_key != 'N') { __delay_cycles(1000); selection_key = Key_getValue(); } Dogs102x6_clearScreen(); selection_wheel = Menu_Select((char **)SIN_Text, 2); Dogs102x6_stringDraw(7, 0, &Press B to sel&, DOGS102x6_DRAW_INVERT); switch(selection_wheel) { case 1:Sin_SEL_Sin_Menu_1(); case 2:Sin_SEL_Sin_Menu_2(); default: } selection_key = Key_getValue(); } } void Sin_Menu_1(void) { int32_t Frequency = 0; int8_t Position = 0; char selection_key = 'N'; char Old_Key = 'N'; Dogs102x6_clearScreen(); Dogs102x6_stringDraw(1, 0, &Sin_generator&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(2, 0, &Fre Set Up&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(7, 0, &Enter the Fre&, DOGS102x6_DRAW_INVERT); InitIn(); while(selection_key != 'F'){ selection_key = Key_getValue(); if(Old_Key == 'N') switch(selection_key) { case '0':Frequency = Frequency*10 + 0;Dogs102x6_charDraw(4, Position, selection_key, 6; case '1':Frequency = Frequency*10 + 1;Dogs102x6_charDraw(4, Position, selection_key, 6; case '2':Frequency = Frequency*10 + 2;Dogs102x6_charDraw(4, Position, selection_key, 6; case '3':Frequency = Frequency*10 + 3;Dogs102x6_charDraw(4, Position, selection_key, 6; case '4':Frequency = Frequency*10 + 4;Dogs102x6_charDraw(4, Position, selection_key, 6; case '5':Frequency = Frequency*10 + 5;Dogs102x6_charDraw(4, Position, selection_key, 6; case '6':Frequency = Frequency*10 + 6;Dogs102x6_charDraw(4, Position, selection_key, 6; case '7':Frequency = Frequency*10 + 7;Dogs102x6_charDraw(4, Position, selection_key, 6; case '8':Frequency = Frequency*10 + 8;Dogs102x6_charDraw(4, Position, selection_key, DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + DOGS102x6_DRAW_NORMAL);Position = Position + 6; case '9':Frequency = Frequency*10 + 9;Dogs102x6_charDraw(4, Position, selection_key, 6; case 'B':Frequency = Frequency/10;Position = Position 6;if(Position & 0){Position = 0;Frequency = 0;}Dogs102x6_charDraw(4, Position, ' ', DOGS102x6_DRAW_NORMAL);//backspace case 'C':SendDATA(Frequency); case 'F': default: } Old_Key = selection_ __delay_cycles(100000); } while(selection_key != 'N') { __delay_cycles(100); selection_key = Key_getValue(); } } void Sin_Menu_2(void) { char selection_key = 'N'; char Old_Key = 'N'; Dogs102x6_clearScreen(); Dogs102x6_stringDraw(2, 0, &Sin Fre Step&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(3, 0, &Press 1 to Up&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(4, 0, &Press 2 to Down&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(7, 0, &Press B to sel&, DOGS102x6_DRAW_INVERT); while(selection_key != 'F'){ selection_key = Key_getValue(); if(Old_Key == 'N') switch(selection_key) { case '1':Sin_UP_Sin_UP_ case '2':Sin_DOWN_Sin_DOWN_ default: } Old_Key = selection_ __delay_cycles(10000); } while(selection_key != 'N') DOGS102x6_DRAW_NORMAL);Position = Position + { __delay_cycles(100); selection_key = Key_getValue(); } } void SubMenu_2(void) { char selection_key = 'N'; uint8_t selection_wheel = 0; Dogs102x6_clearScreen(); Dogs102x6_stringDraw(3, 0, &FM_TEST&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(7, 0, &Press B to sel&, DOGS102x6_DRAW_INVERT); __delay_cycles(1000); while( selection_key != 'F' ){ selection_wheel = Menu_Select((char **)FMText, 2); selection_key = Key_getValue(); __delay_cycles(1000); switch(selection_wheel) { case 1:FM_Sel_5; case 2:FM_Sel_10; default: } } while(selection_key != 'N') { __delay_cycles(100); selection_key = Key_getValue(); } } void SubMenu_3(void) { char selection_key = 'N'; char Tag[4]; int16_t WheelPositionData = 0; int8_t WheelPosition = 0; int8_t OldWheelPosition = 0; init_as9850(); InitIO(); ad9850_wr_serial(0,1000); Dogs102x6_clearScreen(); Dogs102x6_stringDraw(3, 0, &AM_TEST&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(7, 0, &Car Fre: 1MHz&, DOGS102x6_DRAW_INVERT); while( selection_key != 'F' ){ WheelPositionData = Wheel_getValue(); WheelPosition = WheelPositionData/40; if(WheelPosition & 100)WheelPosition = 100; Tag[0] = WheelPosition/100%10+48; Tag[1] = WheelPosition/10%10+48; Tag[2] = WheelPosition%10+48; Tag[3] = '%'; Dogs102x6_stringDraw(5, 0, Tag, DOGS102x6_DRAW_NORMAL); if(OldWheelPosition != WheelPosition){ SetDAC_B(FASTSP,IN_.0); } selection_key = Key_getValue(); __delay_cycles(1000); switch(selection_key) { case 'F': default: } OldWheelPosition = WheelP } while(selection_key != 'N') { __delay_cycles(100); selection_key = Key_getValue(); } } void SubMenu_4(void) { char selection_key = 'N'; Dogs102x6_clearScreen(); Dogs102x6_stringDraw(3, 0, &ASK_TEST&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(6, 0, &Sig Fre: 1KHz&, DOGS102x6_DRAW_INVERT); while( selection_key != 'F' ){ selection_key = Key_getValue(); __delay_cycles(1000); switch(selection_key) { case 'F': default: } } while(selection_key != 'N') { __delay_cycles(100); selection_key = Key_getValue(); } } void SubMenu_5(void) { char selection_key = 'N'; Dogs102x6_clearScreen(); Dogs102x6_stringDraw(3, 0, &PSK_TEST&, DOGS102x6_DRAW_NORMAL); Dogs102x6_stringDraw(6, 0, &Sig Fre: 1KHz&, DOGS102x6_DRAW_INVERT); while( selection_key != 'F' ){ selection_key = Key_getValue(); __delay_cycles(1000); switch(selection_key) { case 'F': default: } } while(selection_key != 'N') { __delay_cycles(100); selection_key = Key_getValue(); } } void Init_Sin(void) { Menu_Sel_En_ Menu_Sel0_ Menu_Sel1_ Menu_Sel2_ Menu_Sel_En_ Menu_Sel0_ Menu_Sel1_ Menu_Sel2_ Sin_SEL_ Sin_UP_ Sin_DOWN_ FM_Sel_ FM_Sel_5; }其他头文件不在赘述。
MSP430单片机使用和对比―汇集和整理大量word文档,专业文献,应用文书,考试资料,教学教材,办公文档,教程攻略,文档搜索下载下载,拥有海量中文文档库,关注高价值的实用信息,我们一直在努力,争取提供更多下载资源。

我要回帖

更多关于 单片机计时器 的文章

 

随机推荐