第三章 3.5 Flash 使用的代码样例 #include "msp430g2553.h" /**************************************************** g2553 有 4 个数据段, 每个数据段有 64bytes, 共 256bytes D:0x10

Similar documents
Microsoft Word - MSP430 Launchpad 指导书.docx

(3)ADC12Ó¦Ó÷¶Àý

MSP430单片机简介

MSP430 Launchpad 指导书

bingdian001.com

untitled

Microsoft Word - 430实验说明.doc

学习MSP430单片机推荐参考书

RO 电容检测 : 其原理就是测震荡电路频率, 关键参数在电容 ----C1 的充放电,R5 和 C1 构成一阶 RC 震荡电路 比较器的输入电压时随着输出电压变化而变化的, 而比较器负输入端电压是由 C1 充放电决定 通过计算可以发现, 电容电压在 1/3VCC-2/3VCC 之间反复变化 其震荡

MSP430F KB+256B flash 10KB RAM 64 Quad Flat Pack QFP MSP430x1xx SLAU049 MSP430 MSP RISC CPU 16 DCO 6 MSP430x15x/16x/161x A/D 12 D/A

Microsoft Word - MSP_430学习笔记.doc

untitled

JLX

目录

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit

untitled

MSP430x11x1 T A -40 ~ SOWB 20 TSSOP (DW) (PW) MSP430F110IDW MSP430F110IPW MSP430F112IDW MSP430F112IPW + F11x 30kΩ

CC213

2 12

MSP430 串行异步通讯原理与实现 南京航空航天大学 魏小龙 本讲讲述串口功能与连接的实现 大多数 MSP430 芯片都有硬件异步通讯功能, 有一些器件有两个通讯端口, 也有少数没有 没有硬件串口的芯片可以实现软件 ( 模拟 ) 串口 下面表格为 430 系列芯片串口的情况 系列芯片 F11 系列

第 1 章 MSP430 快速入门 因为最近转入 MPS430 的技术支持工作, 所以现在开始学习 430 的开发 由于之前用过 51, 也用过 TI 的 ARM CORTEX-M3, 但是就是没有用过 TI 的 430, 所以将 我学习 430 的过程写出来, 给像我一样之前没有 430 开发经验

MSP430 MSP430 F149 MSP430F149 P USART MSP430F PWM 63#

变量名 :JAVA_HOME, 变量值 : 你的安装路径 \Java\jdk 版本号 3 接下来查看系统变量, 如果其中有 classpath 和 path 变量, 则在其值后面分别添加 : ; 你的安装路径 \Java\jdk 版本号 \jre\lib 和 ; 你的安装路径 \Java\jdk 版

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

untitled

C PICC C++ C++ C C #include<pic.h> C static volatile unsigned char 0x01; static volatile unsigned char 0x02; static volatile unsigned cha

Microsoft Word - 10

MSP430

12232A LED LED LED EL EL CCFL EL CCF

untitled

2005.book

Microsoft Word - ¹ØÓÚMSP430flash×ÔÉý¼¶µÄ³¢ÊÔ.doc

Microsoft Word - 18

51 C 51 isp 10 C PCB C C C C KEIL

Microsoft Word - LMB402CBC-AppNote-V0.1.doc

Hz 10MHz 0.5V 5V 0.01% 10s 2 0.5V 5V 1Hz 1kHz 10% 90% 1% 3 1Hz 1MHz 1% EPM7128SLC84-15 LM361 LM361 Zlg

<4D F736F F D20B9F9B0EABBCDBBAFAB48DEB3B4C1A5BDB3F8A7692E646F63>

C 1

Microsoft Word - MSP430F³£ÓÃÄ£¿éÓ¦ÓÃÔ�Àí.doc

Microsoft Word - IRFWX-A124_A_SM59D03G2_SM59D04G2_PCA_ APN_SC_.doc

议程 介绍 Value Line 系列 Code Composer Studio CPU 与基本时钟模块 中断与 GPIO Timer_A 与 WDT+ MSP430 低功耗设计 ADC10 和 Comparator_A+ 串行通信模块 Grace 电容式触摸按键解决方案

2 Keil µ vision 2.1 1) Keil µ vision2 V2.34 µ vision3 2) Sino_Keil.exe Keil c:\keil\ 3) JET51 USB PC C:\Keil\ USB PC 4) S-L

本文档为 TI 数字温度传感器 TMP104 的应用入门, 介绍如何利用 MSP430 及 TMP104 来进 行温度的读取及系统设计过程中的注意事项 文中涉及源代码仅供参考, 如需完整代码, 请邮件索取 准备文档 TMP104 Datasheet

中文摘要 本系統採用德州儀器 MSP430 系列的晶片, 配合具有 HID 人機介面的藍芽來遙控智慧行動裝置遊戲軟體 目的在於使用第三方裝置來無線操作 Android 手機裡的遊戲, 讓手機遊戲增加更多玩法及趣味性, 以此改變傳統的手機遊戲 英文摘要 The system uses a Texas

行业

Microsoft Word - 实用案例.doc

行业

ICD ICD ICD ICD ICD

行业

行业

单片机原理及应用实验指导书.doc

Microsoft Word - ~ doc

ARK-14013/14017/14018

DPJJX1.DOC

中文手册

SH79F161B I/O 1. SH79F161B SH79F161B IO 30 I/O I/O 4 I/O SH79F161B 30 I/O Px I/O PxCRy I/O PxPCRy x = 0-3 y = IO PxCRy IO x=0-3 y=0-7

FY.DOC

chap07.key

Microsoft Word - LM6029-AppNote-V0.2.doc

( RMB100,000)

C/C++语言 - C/C++数据

行业

Car DVD API User Manual V0.2 Feb 03, 2008

C语言的应用.PDF

新・明解C言語入門編『索引』

Microsoft Word - MAN2011A_CH_RTT.doc

作业四:

Microsoft Word - MAN2023A_CH_APPONE.doc

TH2512/TH2512A Tonghui Electronics reserves the right to make changes at any time without notice in order to improve design and supply the best possib

PCM-3386用户手册.doc

( CIP) /. :, ( ) ISBN TP CIP ( 2005) : : : : * : : 174 ( A ) : : ( 023) : ( 023)

FM1935X智能非接触读写器芯片

行业

Microsoft Word - µÚ14ÕÂ OA.doc

1-1 SH79F6431 A. 2( ) 9~15V ( 12V) U2 U3 3.3V SH79F B. 1(VCC/GND) SH79F6431 C. VDDIO SH79F6431 P4 P5 P0.6 P0.7 VDDIO VDDIO=5V D. 2 V 1.0

华恒家庭网关方案

(Load Project) (Save Project) (OffLine Mode) (Help) Intel Hex Motor

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++;

<4D F736F F D203034CAB5D1E9CBC D20B5C4494F20BDD3BFDACAB5D1E92E646F63>

ARM Cortex-M3 (STM32F) STMicroelectronics ( ST) STM32F103 Core: ARM 32-bit Cortex -M3 CPU 72 MHz, 90 DMIPS with 1.25 DMIPS/MHz Single-cycle multiplica

untitled

HCS08微控制器上有关内存分配的几个问题.doc

MSP430系统实验教程.doc

第 16 章 SPI 串行同步通讯接口模式 这个 5 系列通用串行通信接口支持一个硬件模块下的多通道串行通信模式 本章节主要讨论同步外围接口的运行或称 SPI 模式的运行 16.1 USCI 的概述通用串行通信接口模块支持多道串行通信模式 不同的 USCI 支持不同的模式 每一个不同的 USCI 模

untitled

1 TPIS TPIS 2 2

+00DE _01EN.book

untitled

/ / / LED DOCNO: SG D REV11-2 -

instructions.PDF

/ / / , DOCNO: SG J REV11-2 -

nooog

static unsigned int n250ms=o; n250ms++; if(n250ms==2){ // 延时 250ms 2=500ms n250ms=0; // 清零计数器 DelayTime&=~Delay500ms;// 复位标志位 WDTCTL=WDTHOLD+WDTPW; 1E

untitled

ATMEL AT90S8515 AVR CPU AVR AVR AVR ATMEL RISC 32 8 r0 r X Y Z R0 R1 R2 R13 R14 R15 R16 R17 R26 R27 R28 R29 R30 R31 0x00 0x

Bus Hound 5

技 术 支 持 电 话 传 真 电 子 邮 件 网 址 CONVERGE PRO 880/880T/840T/8i, CON

Transcription:

MSP-EXP430Launchpad 实验指南参考代码附录 本附录为 MSP-EXP430Launchpad 实验指南中各章节涉及示例程序的完整参考代码 目录 第三章... 2 3.5... 2 3.6... 5 第五章... 11 5.1.1... 11 5.1.2... 13 5.1.3... 14 5.1.4... 17 5.1.5... 18 5.1.6... 21 5.2.1... 22 5.2.2... 22 5.2.3... 25 5.2.4... 27 5.3.1... 29 5.3.2... 30 5.4.1... 30 5.4.2... 31 5.4.3... 34 5.5.1... 38 5.5.2... 42 5.5.3... 53 5.5.4... 53 5.5.5... 54 第六章... 58 6.1.3... 58 6.1.4... 59 6.2.3... 62 6.3.3 光照度检测模块程序设计... 65 6.4.3... 67 6.5.3... 73 6.6.3... 75 6.6.4... 77

第三章 3.5 Flash 使用的代码样例 #include "msp430g2553.h" /**************************************************** g2553 有 4 个数据段, 每个数据段有 64bytes, 共 256bytes D:0x1000 -- 0x003F C:0x1040 -- 0x107F B:0x1080 -- 0x10BF A:0x10C0 -- 0x10FF ****************************************************/ #define uint unsigned int #define uchar unsigned char #define SegA 0x010C0 #define SegB 0x01080 #define SegC 0x01040 #define SegD 0x01000 #define SegSize 64 /********************Flash 初始化 ********************/ void FlashInit() FCTL2=FWKEY+FSSEL_2+FN1; // 选择 SMLCK 作为时钟源, 二分频 /********************Flash 检测忙 ********************/ void FlashCheckBusy() while(busy==(fctl3&busy)); // 检测是否忙 /********************Flash 段擦除 *******************/ void FlashErase(int SegX) _DINT(); FlashCheckBusy(); FCTL3=FWKEY; FCTL1=FWKEY+ERASE; // 关闭总中断 // 检测 Flash 是否处于忙状态 //lock=0 开锁 // 使能段擦除

*((int *)SegX)=0x00; // 段擦除 -- 空写 FlashCheckBusy(); // 检测 Flash 是否处于忙状态 FCTL3=FWKEY LOCK; // 上锁 return; /********************Flash 写字节 ********************/ void FlashWriteChar(uint addr,char wdata) _DINT(); // 关闭总中断 FlashCheckBusy(); // 检测 Flash 是否处于忙状态 FCTL3=FWKEY; //lock=0 开锁 FCTL1=FWKEY+WRT; // 写使能 *((uchar *)addr)=wdata; // 将 wdata 存入 addr 变量地址中 FCTL1=FWKEY; // 写关闭 FCTL3=FWKEY+LOCK; // 上锁 return; /********************Flash 读字节 ********************/ char FlashReadChar(uint addr) char rdata; rdata=*(char*)addr; // 读取 addr 所指地址的值 return rdata; /********************Flash 写字 ********************/ void FlashWriteWord(uint addr,uint wdata) _DINT(); // 关闭总中断 FlashCheckBusy(); // 检测忙, 若忙, 则等待 FCTL3=FWKEY; //lock=0 开锁 FCTL1=FWKEY+WRT; // 写使能 *((uint *)addr)=wdata; // 向地址 addr 处写入 wdata FCTL1=FWKEY; // 写关闭 FCTL3=FWKEY+LOCK; // 上锁 return;

/********************Flash 读字 ********************/ uint FlashReadWord(uint addr) uint rdata; rdata=*(uint *)addr; // 读取变量 addr 地址的值 return rdata; /********************Flash 修改字节 ********************/ void FlashModifyChar(uint SegX,char AddrNum,char wdata) char i,temparry[segsize]; for(i=0;i<segsize;i++) // 读入内存 TempArry[i]=*(uint *)(SegX+i); TempArry[AddrNum]= wdata; // 在数组中的某一位置 AddrNum 写入 wdata FlashErase(SegX); // 段擦除 FCTL3=FWKEY; //lock=0 开锁 FCTL1=FWKEY+WRT; // 准备写 for(i=0;i<segsize;i++) // 向段中重新写数组 *(uint *)(SegX+i)=TempArry[i]; FCTL1=FWKEY; // 写关闭 FCTL3=FWKEY+LOCK; // 上锁 /********************Flash 批量写 ********************/ void FlashBurstWrite(int SegX,int *pstr) int i; FlashErase(SegX); // 段擦除 FCTL3=FWKEY; //lock=0, 开锁 FCTL1=FWKEY+WRT; // 写使能 for(i=0;i<2*sizeof(pstr);i++) // 将数组内容写入段中 *(uchar *)(SegX+i)=*(pStr+i);

FCTL1=FWKEY; // 写关闭 FCTL3=FWKEY+LOCK; // 上锁 main() char ReadChar; uint ReadWord; int p[]='a','b','c','d'; WDTCTL=WDTPW+WDTHOLD; // 关闭看门狗 P1DIR=0xff; //P1 口设为输出, 闲置的 I/O 不悬空 P2DIR=0xff; //P2 口设为输出, 闲置的 I/O 不悬空 P1OUT=0xff; //P1 口输出 1 P2OUT=0xff; //P2 口输出 1 FlashInit(); //Flash 初始化 FlashErase(SegD); FlashWriteChar(0x01007,0x12); // 向地址 01008h 写入 12h ReadChar=FlashReadChar(0x01007); // 读取地址 01008h 的值 FlashWriteWord(0x01008,0x3456); // 向地址 01009h 和 0100Ah 依次写入 56h 和 34h ReadWord=FlashReadWord(0x01008); // 读取从地址 01009h 起的一个字 FlashWriteChar(0x01017,ReadChar); // 向地址 01018h 写入 12h FlashWriteWord(0x01018,ReadWord); // 向地址 01019h 和 0101Ah 依次写入 56h 和 34h FlashBurstWrite(SegC,p); // 向 SegD 段从地址 0110h 依次写入 a b c d FlashModifyChar(SegB,0x02,0xef); // 将地址 0112h 和 0113h 内容改为 e 和 f _BIS_SR(CPUOFF); // 关闭 CPU 3.6 1. USCI 模块串行异步通信例程以 MSP430G2553 的 USCI 模块串行异步通信操作为例, 介绍串口寄存器配置及收发程序处理过程 (1) 初始化串口 void UART_init(void)

UCA0CTL1 =UCSWRST; UCA0CTL1 = UCSSEL_2; //SMCLK UCA0BR0 = 0x68; //32.768/9600= UCA0BR1 = 0x00; // 1000kHz/9600 = 104.166 =0X68 波特率 9600 UCA0MCTL = UCBRS_2; // Modulation UCBRSx = 1 UCA0CTL0 &=~UCPEN; UCA0CTL0 &=~UCSPB; UCA0CTL0 &=~UC7BIT; UCA0CTL1 &=~UCSWRST; P1SEL =BIT1+BIT2; P1SEL2 =BIT1+BIT2; //P1DIR =BIT2; 第二功能无需配置?? IE2 = UCA0RXIE+UCA0TXIE; unsigned int j; for(j=0;j<2000;j++); (2) 串口发送函数 /**************************************************************** 宏定义 ****************************************************************/ unsigned char RX_BUFF[RXBUF_SIZE]=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; // 接收缓冲区 unsigned int UART_InLen=16; // 输入数据长度 unsigned int RX_IndexR = 0; // 接收 FIFO 的读指针 unsigned int RX_IndexW = 0; // 接收 FIFO 的写指针 unsigned char TX_BUFF[TXBUF_SIZE]=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; // 发送缓冲区 unsigned int UART_OutLen =16; // 发送 FIFO 内待发送的字节数 unsigned int TX_IndexR = 0; // 发送 FIFO 的读指针 unsigned int TX_IndexW = 0; // 发送 FIFO 的写指针 uint8 ch=0; /**************************************************************** 串口发送一字节函数, 查询方式 ****************************************************************/ void UART_sent(uint8 Chr)

IFG2&=~UCA0TXIFG; UCA0TXBUF=Chr; while ((IFG2&UCA0TXIFG)==0); // USCI_A0 TX buffer ready? /**************************************************************** 串口发送一帧数据函数, 中断方式 ****************************************************************/ char UART0_PutFrame(unsigned char *Ptr,unsigned int Lenth) int i; if(ie2&uca0txie) return(0); if(lenth>txbuf_size) return(0); for(i=0;i<lenth;i++) delay_us(100); TX_BUFF[i]=Ptr[i]; TX_IndexR=0; UART_OutLen=Lenth; IFG2 =UCA0TXIFG; IE2 =UCA0TXIE; return(1); /***************************************************************** * 名称 :USCIxTX_ISR() * 功能 : 串口发送中断, 每发完 1 字节会发生一次中断 *****************************************************************/ #pragma vector=usciab0tx_vector interrupt void USCI0TX_ISR (void)

if (UART_OutLen > 0) UART_OutLen--; UCA0TXBUF = TX_BUFF[TX_IndexR]; while (!(IFG2&UCA0TXIFG)); // 查看上一字节是否发送完毕 if (++TX_IndexR >= TXBUF_SIZE) TX_IndexR = 0; else IE2 &=~UCA0TXIE; (3) 串口接收函数 /***************************************************************** 串口接收一字节函数, 查询方式, 此处虽定义但并未使用, 不保证其正确性 *****************************************************************/ uint8 UART_receive(void) while ((IFG2&UCA0RXIFG)==0); // 收到一字节? IFG2&=~UCA0RXIFG; return(uca0rxbuf); #pragma vector=usciab0rx_vector interrupt void USCI0RX_ISR(void) UART_InLen++; RX_BUFF[RX_IndexW] = UCA0RXBUF; // 保存在缓冲区中 if (++RX_IndexW >= RXBUF_SIZE) RX_IndexW = 0; 2.USART 模块异步串行通信操作例程 (1) 初始化串口

初始化串口 0, 允许接收和发送, 允许接收中断, 禁止发送中断,8bit 字符发送 时钟 ACLK = 32.768KHz, 波特率 4800 注意 : 对串口寄存器操作的时候务必保证 SWRST=1, 设置完成后 SWRST=0 // 串口初始化函数 void InitUSART(void) U0CTL = CHAR; // 8bit 字符 U0TCTL = SSEL0; // ACLK U0BR1 = 0x00 // 4800 波特率 U0BR0 = 0x06 U0MCTL = 0x6f U0CTL &= ~SWRST; // 设置完成 ME1 = UTXE0 + URXE0; // 接收发送允许 IE1 = URXIE0; // 接收发送中断 P3SEL = (0x80 + 0x40); // 引脚切换到特殊功能上 _EINT(); // 不要忘了开中断 (2) 串口发送函数 采用软件查询式发送, 将 1 个字节写入发送寄存器, 然后等待发送完成的标志 本方 法适合波特率较高的场合 ( 大于 4800) // 所涉及的全局变量 unsigned char TBuff[8]; // 发送缓冲区 unsigned char RBuff[8]; // 接收缓冲区 unsigned char Flag_Receive = 0; // 标志 : 接收到有效数据 // 串口发送函数 ( 不需要开发送中断 ) 发送一个数组 ( 共 8 个字节 ) void USART_Send(unsigned char *pdata) unsigned char i; for(i=0; i<8; i++) TXBUF0 = pdata[i]; // 装入发送寄存器 while ((IFG1 & UTXIFG0) == 0); // 判断 : 发送是否完成 IFG1 &= ~(UTXIFG0); (3) 串口接收函数

在 RAM 开辟接收缓冲区, 等到接收的数据组满足要求或者为一帧数据时才处理 中断中接收 // 所涉及的全局变量 unsigned char TBuff[8]; // 发送缓冲区 unsigned char RBuff[8]; // 接收缓冲区 unsigned char Flag_Receive = 0; // 标志 : 接收到有效数据 // 串口接收函数 ( 需要开接受中断 ) #pragma vector=uart0rx_vector interrupt void USART0_RXIRQ (void) unsigned char Temp; // 暂存接收数据 Temp = RXBUF0; // 8 字节接收缓冲队列 RBuff[0] = RBuff[1]; RBuff[1] = RBuff[2]; RBuff[2] = RBuff[3]; RBuff[3] = RBuff[4]; RBuff[4] = RBuff[5]; RBuff[5] = RBuff[6]; RBuff[6] = RBuff[7]; RBuff[7] = Temp; // 判断数据有效 ( 有效则设置标志位, 等待处理 ) if (RBuff[0] == 0xd0)Flag_Receive = 1; return; elseflag_receive = 0; (4) 串口校验 CRC16 函数常用函数, 使用的 CRCKey = 0xA001 输入一个数组和长度, 则计算出该部分的 CRC 值 // CRC-16 循环冗余效验函数 unsigned int Caculate_CRC16(unsigned char *DAT, unsigned char Lenth) // *DAT 指向要计算 CRC 的数组, Lenth 为数据的有效长度 unsigned int CRC = 0xffff; // CRC 的初始值为 FFFF unsigned char i; unsigned char j; for(i=0; i<lenth; i++)

CRC = CRC ^ DAT[i]; // 和当前字节异或一次 for(j=0; j<8; j++) // 循环 8 次 if(crc & 0x01) // 判断最低位, 如果为 1 CRC = CRC >> 1; // 右移一位 CRC = CRC ^ 0xA001; // 和多相式异或 else // 判断最低位, 如果为 0 CRC = CRC >> 1; // 右移一位 return(crc); 第五章 5.1.1 程序示例 #include <msp430g2553.h> typedef unsigned char uchar; typedef unsigned int uint; /*************** 全局变量 ***************/ uchar key_pressed; // 按键是否被按下 :1-- 是,0-- 否 uchar key_val; // 存放键值 uchar key_flag; // 按键是否已放开 :1-- 是,0-- 否 // 设置键盘逻辑键值与程序计算键值的映射 uchar key_map[] = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16; /******************************************* 函数名称 :Init_Keypad 功能 : 初始化扫描键盘的 IO 端口参数 : 无返回值 : 无 ********************************************/

void Init_Keypad(void) P1DIR = 0xf0; //P1.0~P1.3 设置为输入状态, P1.4~P1.7 设置为输出状态 P1OUT = 0xf0; // P1.4~P1.7 输出高电平 key_flag = 0; key_pressed = 0; key_val = 0; /********************************************* * Check_Key(), 检查按键, 确认键值 *********************************************/ /******************************************* 函数名称 :Check_Key 功能 : 扫描键盘的 IO 端口, 获得键值参数 : 无返回值 : 无 ********************************************/ void Check_Key(void) uchar row,col,tmp1,tmp2; tmp1 = 0x80; for(row = 0;row < 4;row++) // 行扫描 P1OUT = 0xf0; //P1.4~P1.7 输出全 1 P1OUT -= tmp1; //P1.4~p1.7 输出四位中有一个为 0 tmp1 >>=1; if ((P1IN & 0x0f) < 0x0f) // 是否 P1IN 的 P1.0~P1.3 中有一位为 0 tmp2 = 0x01; // tmp2 用于检测出那一位为 0 for(col = 0;col < 4;col++) // 列检测 if((p1in & tmp2) == 0x00) // 是否是该列, 等于 0 为是 key_val = key_map[row * 4 + col]; // 获取键值 return; // 退出循环 tmp2 <<= 1; // tmp2 左移 1 位 /******************************************* 函数名称 :delay 功能 : 延时约 15ms, 完成消抖功能参数 : 无返回值 : 无

********************************************/ void delay() uint tmp; for(tmp = 12000;tmp > 0;tmp--); /******************************************* 函数名称 :Key_Event 功能 : 检测按键, 并获取键值参数 : 无返回值 : 无 ********************************************/ void Key_Event(void) uchar tmp; P1OUT &= 0x00; // 设置 P1OUT 全为 0, 等待按键输入 tmp = P1IN; // 获取 p1in if ((key_pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) // 如果有键按下 key_pressed = 1; // 如果有按键按下, 设置 key_pressed 标识 delay(); // 消除抖动 Check_Key(); // 调用 check_key(), 获取键值 else if ((key_pressed == 1)&&((tmp & 0x0f) == 0x0f)) // 如果按键已经释放 key_pressed = 0; // 清除 key_pressed 标识 key_flag = 1; // 设置 key_flag 标识 else _NOP(); 5.1.2 程序示例 #include <MSP430g2553.h> #define Dis00 0x3F // 数码管显示字符 "0" #define Dis01 0x06 // 数码管显示字符 "1" #define Dis02 0x5B // 数码管显示字符 "2" #define Dis03 0x4F // 数码管显示字符 "3" #define Dis04 0x66 // 数码管显示字符 "4" #define Dis05 0x6D // 数码管显示字符 "5" #define Dis06 0x7D // 数码管显示字符 "6" #define Dis07 0x07 // 数码管显示字符 "7" #define Dis08 0x7F // 数码管显示字符 "8" #define Dis09 0x6f // 数码管显示字符 "9"

#define Dis0A 0X77 // 数码管显示字符 "A" #define Dis0B 0x7C // 数码管显示字符 "B" #define Dis0C 0x39 // 数码管显示字符 "C" #define Dis0D 0x5E // 数码管显示字符 "D" #define Dis0E 0x79 // 数码管显示字符 "E" #define Dis0F 0X71 // 数码管显示字符 "F" const unsigned char seg_[16] = 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71; void delay_(int m) int i; int j; for (i=m;i>0;i--) for(j=100;j>0;j--); // 延时子程序 void Display( signed char i ) // 数码管显示子程序 // unsigned char result(); if(0<=i<=15) P1OUT = seg_[i]; // 数码管显示数值 // delay_(100); // while(1); void main(void) WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗 P1SEL = 0; // 设置 P1 口全为普通 IO 口 P1DIR = 0xff; // 将 P1 所有端口设为输出 P1OUT = 0X00; //p1 口先全部输出低电平 unsigned char i; for(i=0;i<16;i++) // 依稀显示从 0 到 F Display(i); 5.1.3 程序示例 #include <msp430g2553.h> #include"key&display.h" // 自定义头文件 void main( void ) WDTCTL = WDTPW + WDTHOLD; // 停止开门狗 Init_4lines_Mode();// 初始化 4 线工作模式 Send_Command(CH452_RESET);//CH452 芯片内部复位 Send_Command(KeyDisplay_ON);// 允许显示驱动并启动键盘扫描 // 开中断,P2.0 接 CH452 的 DOUT 引脚, 当有键按下时,DOUT 上产生由高到低的脉冲 P2IE =BIT0; P2IES =BIT0;

P2IFG&=~BIT0; _EINT(); while(1) // 中断处理函数 #pragma vector = PORT2_VECTOR// 中断处理程序, 接收到 DOUT 脉冲信号时, 运行之 interrupt void Port2(void) unsigned char Keyvalue; Send_Command(CH452_GET_KEY);// 单片机向 CH452 发送读取按键代码命令 Keyvalue=Key_Read(); switch(keyvalue) case 0x40:// 按键 K0 按下 Send_Command( NDis1); // 第 1 位数码管不显示 Send_Command(Dis00);// 第 0 位数码管显示 0 case 0x41:// 按键 K1 按下 Send_Command( NDis1); // 第 1 位数码管不显示 Send_Command(Dis01);// 第 0 位数码管显示 1 case 0x42:// 按键 K2 按下 Send_Command( NDis1); // 第 1 位数码管不显示 Send_Command(Dis02);// 第 0 位数码管显示 2 case 0x43:// 按键 K3 按下 Send_Command( NDis1);// 第 1 位数码管不显示 Send_Command(Dis03);// 第 0 位数码管显示 3 case 0x48:// 按键 K4 按下 Send_Command( NDis1);// 第 1 位数码管不显示 Send_Command(Dis04);// 第 0 位数码管显示 4 case 0x49:// 按键 K5 按下

Send_Command( NDis1);// 第 1 位数码管不显示 Send_Command(Dis05);// 第 0 位数码管显示 5 case 0x4A:// 按键 K6 按下 Send_Command( NDis1);// 第 1 位数码管不显示 Send_Command(Dis06);// 第 0 位数码管显示 6 case 0x4B:// 按键 K7 按下 Send_Command( NDis1);// 第 1 位数码管不显示 Send_Command(Dis07);// 第 0 位数码管显示 7 case 0x50:// 按键 K8 按下 Send_Command( NDis1);// 第 1 位数码管不显示 Send_Command(Dis08);// 第 0 位数码管显示 8 case 0x51:// 按键 K9 按下 Send_Command( NDis1);// 第 1 位数码管不显示 Send_Command(Dis09);// 第 0 位数码管显示 9 case 0x52:// 按键 K10 按下 Send_Command(Dis00);// 第 0 个数码管显示字符 "0" Send_Command(Dis11);// 第 1 个数码管显示字符 "1" case 0x53:// 按键 K11 按下 Send_Command(Dis01);// 第 0 个数码管显示字符 "1" Send_Command(Dis11);// 第 1 个数码管显示字符 "1" case 0x58:// 按键 K12 按下 Send_Command(Dis02);// 第 0 个数码管显示字符 "2" Send_Command(Dis11);// 第 1 个数码管显示字符 "1" case 0x59:// 按键 K13 按下

Send_Command(Dis03);// 第 0 个数码管显示字符 "3" Send_Command(Dis11);// 第 1 个数码管显示字符 "1" case 0x5A:// 按键 K14 按下 Send_Command(Dis04);// 第 0 个数码管显示字符 "4" Send_Command(Dis11);// 第 1 个数码管显示字符 "1" case 0x5B:// 按键 K15 按下 Send_Command(Dis05);// 第 0 个数码管显示字符 "5" Send_Command(Dis11);// 第 1 个数码管显示字符 "1" default: P2IFG&=~BIT0; 5.1.4 程序示例 #include "msp430g2553.h" #include "LCD12864.h" unsigned char display[]= "==== 欢迎使用 ====" " 西安电子科技大学 " " 实验系统标准板 " "TexasInstruments" ; void main() WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗 P2SEL &= ~(BIT6+BIT7); // 关闭 P2.6 和 P2.7 的第二功能 P2DIR = BIT6+BIT7; //P2.6 和 P2.7 设置为输出 lcd_init(); // 初始化 LCD while(1)

chn_disp1 (display);// 显示数组 display 中的内容 5.1.5 程序示例 #include "msp430g2553.h" /* 定义用户配置 ( 根据具体的硬件平台可能要在相应修改 ) */ #define WDT_meas_setting (DIV_SMCLK_512)// 定义看门狗定时器的测量时间间隔 ( 时间较短 ) #define WDT_delay_setting (DIV_ACLK_512)// 定义看门狗定时器的测量间的延时 ( 时间较长 ) #define KEY_LVL 50 // 定义触摸板是否按下的阀值 /* 使用看门狗定时器可以使用的宏定义 */ #define DIV_ACLK_32768 (WDT_ADLY_1000) // ACLK/32768 #define DIV_ACLK_8192 (WDT_ADLY_250) // ACLK/8192 #define DIV_ACLK_512 (WDT_ADLY_16) // ACLK/512 #define DIV_ACLK_64 (WDT_ADLY_1_9) // ACLK/64 #define DIV_SMCLK_32768 (WDT_MDLY_32) // SMCLK/32768 #define DIV_SMCLK_8192 (WDT_MDLY_8) // SMCLK/8192 #define DIV_SMCLK_512 (WDT_MDLY_0_5) // SMCLK/512 #define DIV_SMCLK_64 (WDT_MDLY_0_064) // SMCLK/64 /* LED 相关定义 */ #define LED_1 (0x01) // P1.0 = LED1 输出 #define LED_2 (0x40) // P1.6 = LED2 输出 /* 用来测量的全局变量 */ unsigned int base_cnt, meas_cnt; // 电容 ( 实际是频率 ) 测量的基准值和测量值 int delta_cnt; // 电容 ( 实际是频率 ) 测量的基准值和测量值的差值 char key_pressed; // 状态量 :1 表示有按键按下 ;0 表示没有按键按下 int cycles; /* 系统功能函数 */ void measure_count(void); // Measures each capacitive sensor void pulse_led(void); // LED gradient routine /* 主函数从这里开始 */ void main(void) unsigned int i,j; WDTCTL = WDTPW + WDTHOLD; // 停止看门狗定时器

BCSCTL1 = CALBC1_1MHZ; // 设置 DCO 为 1MHz DCOCTL = CALDCO_1MHZ; // 设置 DCO 为 1MHz BCSCTL3 = LFXT1S_2; // LFXT1 为 VLO IE1 = WDTIE; // 使能看门狗定时器中断 P2SEL = 0x00; // 禁止外部晶振 P1DIR = LED_1 + LED_2; // P1.0 和 P1.6 设置为输出 P1OUT = 0x00; bis_sr_register(gie); // 使能全局中断 measure_count(); // 建立测量基准 base_cnt = meas_cnt; for(i=15; i>0; i--) // 重复测量来建立平均的基准值 measure_count(); base_cnt = (meas_cnt+base_cnt)/2; /* 主循环从这里开始 */ while (1) j = KEY_LVL; key_pressed = 0; // 假设现在没有按键按下 measure_count(); // 测量一次电容的大小 delta_cnt = base_cnt - meas_cnt; // 计算差值 : 指示电容的改变 /* 为基本的电容下降处理基准测量值 */ if (delta_cnt < 0) // 如果为负说明结果超出了基准值, 例如, 电容下降 base_cnt = (base_cnt+meas_cnt) >> 1; // 快速的得到新的平均值 delta_cnt = 0; // 差值清零 if (delta_cnt > j) // 根据预定的阀值检查是否有键按下 j = delta_cnt; key_pressed = 1; // 有按键按下 else key_pressed = 0; // 延时到下一次采样, 如果没有按键按下就采的更慢 if (key_pressed) BCSCTL1 = (BCSCTL1 & 0xCF) + DIVA_0; // ACLK/(0:1,1:2,2:4,3:8) cycles = 20; else

cycles--; if (cycles > 0) BCSCTL1 = (BCSCTL1 & 0xCF) + DIVA_0; // ACLK/(0:1,1:2,2:4,3:8) else BCSCTL1 = (BCSCTL1 & 0xCF) + DIVA_3; // ACLK/(0:1,1:2,2:4,3:8) cycles = 0; WDTCTL = WDT_delay_setting; // 采样间隔 ( 较 WDT_meas_setting 长 ) /* 为基本的电容上升处理基准测量值 */ if (!key_pressed) // 只当没有键按下时才缓慢的向下校准基准值 base_cnt = base_cnt - 1; // 应该缓慢的减少基准来适应真实的电容变化 pulse_led(); // 根据按键是否按下调整 LED ( 有按键按下就点亮 ) bis_sr_register(lpm3_bits); // 主循环结束 /* 测量每一个按键的计数值 ( 电容值 ) */ void measure_count(void) TA0CTL = TASSEL_3 + MC_2; // TA 时钟源选择 IO 振荡器, 连续模式 TA0CCTL1 = CM_3+CCIS_2+CAP; // 上升沿和下降沿都捕获, /* 为弛张振荡器设置端口 */ /* P2SEL2 寄存器允许 TA 从 GPIO 获取时钟 */ P2DIR &= ~ BIT1; // P2.1 设置为输入 P2SEL &= ~ BIT1; // P2.1 第二功能设置为电容感测 P2SEL2 = BIT1; // P2.1 第二功能设置为电容感测 /*Setup Gate Timer*/ WDTCTL = WDT_meas_setting; // 测量时间 ( 较 WDT_delay_setting 短 ) TA0CTL = TACLR; // 清除 TA 定时器 bis_sr_register(lpm0_bits+gie); // 等待看门狗中断 TA0CCTL1 ^= CCIS0; // 产生 CCR1 通道的软件捕获操作 meas_cnt = TACCR1; // 保存结果 WDTCTL = WDTPW + WDTHOLD; // 停止看门狗定时器 P2SEL2 &= ~BIT1; void pulse_led(void)//led 处理函数 ( 按下则亮灯 ) if(key_pressed)

P1OUT ^= LED_1 + LED_2; else P1OUT = 0; /* 看门狗定时中断 */ #pragma vector=wdt_vector interrupt void watchdog_timer(void) TA0CCTL1 ^= CCIS0; // 产生 CCR1 通道的软件捕获操作 bic_sr_register_on_exit(lpm3_bits); // 中断后推出睡眠 5.1.6 程序示例 #include "msp430g2553.h" void main( void ) WDTCTL=WDTPW+WDTHOLD; // 关闭看门狗 P1DIR =BIT0+BIT1+BIT2+BIT3; //GPIO 设置 P1DIR =BIT4+BIT5+BIT6; P1OUT&=~(BIT4+BIT5+BIT6); P1OUT &=~(BIT0+BIT1+BIT2+BIT3); P1OUT =BIT0+BIT1+BIT2+BIT3; TA0CCR0=65500; // 定时器 A 的设置 TA0CCR1=13107; TA0CCR2=45875; TA0CTL =MC_1+TASSEL_2+ID_3; TA0CTL =TAIE; TA0CCTL1 =CCIE; TA0CCTL2 =CCIE; _EINT(); while(1) // 定时器 A 中断函数 #pragma vector=timer0_a1_vector interrupt void TA1_ISR(void) switch(ta0iv)

case 2: P1OUT&=~(BIT4+BIT5+BIT6); P1OUT =BIT4; case 4:P1OUT&=~(BIT4+BIT5+BIT6); P1OUT =BIT5; case 10: P1OUT&=~(BIT4+BIT5+BIT6); P1OUT =BIT6; 5.2.1 程序示例 #include "msp430g2553.h" void ADC10_Init(void) ADC10CTL1=CONSEQ_2;// 单通道多次转换, 这句应当写在最前面 ADC10CTL0 = REFON+SREF_1+REF2_5V; // 打开 2.5V 正参考, 地为负参考 ADC10CTL0 = ADC10ON+ADC10SHT_3+ADC10IE;// 打开 ADC10 内核, 设定采样保持时间为 64 个 ADC10CLK, 使能 ADC10 中断 ADC10CTL1 = INCH_4+SHS_0+ADC10SSEL_2; // input A4, 采样保持 ADC10AE0 = 0x10; // P1.4 DC option select A4 模拟信号输入使能 void main() WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer ADC10_Init(); _BIS_SR(GIE);// 开中断 while(1); 5.2.2 程序示例 //**************************************************************************** ** // 程序名称 : 光照度检测模块

// 功能描述 : 光电池将光信号转化成电信号, 然后输入到单片机模拟量输入端 A4( 即 P1.4), // 经 AD 转换后, 由单片机处理, 将该信号转化成光照度, 最后显示在 LCD12864 上 // MCLK 采用 1M 的内部 DCO,SMCLK 采用 125K 的时钟, 参考电压选择内部 2.5V 正参考, // 地为负参考 // // MSP430G2553 // +-----------------------+ // // XOUT --p2.7(en) // // XIN --p2.6 (R/W) // // // 模拟输入 -- P1.4 // // P2.4 -- 小量程 // P2.3 -- 大量程 // +-----------------------+ //**************************************************************************** ** #include "msp430g2553.h" #include "LCD12864.h" unsigned char const tab1[]= " " " LaunchPad " " Welcome " " " ; unsigned char const tab2[]= "==== 欢迎使用 ====" " 西安电子科技大学 " " 光强检测模块 " "TexasInstruments" ; unsigned char const tab3[]= " 您正在使用 : " " 当前光照强度为 :" " 量程 " " Lx "

; unsigned char CHN1[]=" 大 ",CHN2[]=" 小 "; void IO_init() P2DIR&=~(BIT3+BIT4); P2REN =BIT3+BIT4; P2OUT =BIT3+BIT4;// 内部上拉 //P1REN =BIT4; //P1OUT =~BIT4;// 内部下拉 void ADC10_Init(void) ADC10CTL1=CONSEQ_2;// 单通道多次转换, 这句应当写在最前面 ADC10CTL0 = REFON+SREF_1+REF2_5V; // 打开 2.5V 正参考, 地为负参考, 默认 1.5V ADC10CTL0 = ADC10ON+ADC10SHT_3+ADC10IE;// 打开 ADC10 内核, 设定采样保持时间为 64 个 ADC10CLK, 使能 ADC10 中断 ADC10CTL1 = INCH_4+SHS_0+ADC10SSEL_2; // input A4, 采样保持 ADC10AE0 = 0x10; // P1.4 DC option select A4 模拟信号输入使能 int m,ave,n=0; unsigned long AD_Result,Lx; void main() WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer //BCSCTL1 = CALBC1_1MHZ; //DCOCTL = CALDCO_1MHZ;// 上面两句将内部 DCO 校准至 1MHz //BCSCTL2 = SELM_0;//MCLK 采用 1M 的内部 DCO //BCSCTL2 = DIVS_0;//SMCLK 采用 125K 的时钟 P2SEL &= ~(BIT6+BIT7); P2DIR = BIT6+BIT7; lcd_init(); ADC10_Init(); IO_init(); _BIS_SR(GIE);// 开中断 chn_disp1 (tab1); delay_ms(3000); chn_disp1 (tab2); delay_ms(3000); chn_disp1 (tab3);

while(1) Write_Num(0x98,Lx,0); delay_ms(100); ADC10CTL0 = ENC + ADC10SC; #pragma vector=adc10_vector interrupt void ADC10_ISR (void) ADC10CTL0 &= ~ENC; // Disable ADC conversion m++; // 计数变量加一, 记录进入 AD 中断的次数 AD_Result+=ADC10MEM; // 累加每次采样值 if(m>=8) // 判断采样的次数, 若采样次数等于 8, 作下面处理 m=0; ave=ad_result>>3; // 对累加和求平均 AD_Result=0; if((p2in&bit3)==0x00)// 切换量程 Lx=(long)((ave*2.5/1023*1000)/1.4);// 大量程, 将电压值换算成光强度 write_onechinese(2,2,chn1); else Lx=(long)((ave*2.5/1023*100)/1);// 小量程 write_onechinese(2,2,chn2); 5.2.3 程序示例 #include "msp430g2553.h" #include "LCD12864.h" #define ADC_0 0 #define ADC_F 679 #define VCAL 1 //ADC 测电压校准参数,1v unsigned char m=0; int ave,r_pt100,t_pt100,n=0;

unsigned long AD_Result; unsigned char const tab1[]= " " " " " Pt100 所测温度 : " " " ; /**************************************************************************** * 名称 :Calculate(int ADC_Result) * 功能 : 将计算采样值对应的电压 * 入口参数 :ADC_Result, 采样值 * 出口参数 : 无 ****************************************************************************/ float Calculate(int ADC_Result) float Vol; Vol=(float)(ADC_Result-ADC_0)*VCAL/(ADC_F-ADC_0); return(vol); void ADC10_Init(void) ADC10CTL1=CONSEQ_2;// 单通道多次转换, 这句应当写在最前面 ADC10CTL0 = REFON+SREF_1+REF2_5V; // 打开 2.5V 正参考, 地为负参考, 默认 1.5V ADC10CTL0 = ADC10ON+ADC10SHT_3+ADC10IE;// 打开 ADC10 内核, 设定采样保持时间为 64 个 ADC10CLK, 使能 ADC10 中断 ADC10CTL1 = INCH_6+SHS_0+ADC10SSEL_2; // input A6, 采样保持 ADC10AE0 = 0x10; // P1.4 DC option select A6 模拟信号输入使能 void main() WDTCTL = WDTPW + WDTHOLD; P2SEL &= ~(BIT6+BIT7); P2DIR = BIT6+BIT7; lcd_init(); ADC10_Init(); _BIS_SR(GIE);// 开中断 chn_disp1(tab1); while(1) // Stop watchdog timer

Write_Num(0x93,T_PT100,0); delay_ms(100); ADC10CTL0 = ENC + ADC10SC; #pragma vector=adc10_vector interrupt void ADC10_ISR (void) ADC10CTL0 &= ~ENC; // Disable ADC conversion m++; // 计数变量加一, 记录进入 AD 中断的次数 AD_Result+=ADC10MEM; // 累加每次采样值 if(m>=8) // 判断采样的次数, 若采样次数等于 8, 作下面处理 m=0; ave=ad_result>>3; // 对累加和求平均 AD_Result=0; R_PT100=Calculate(ave); R_PT100=R_PT100*1000/4.0; T_PT100=(int)((R_PT100/1.055-100)/0.03851); // 计算 PT100 所测温度 5.2.4 程序示例 #include "msp430g2553.h" #include "math.h" #include "LCD12864.h" unsigned char const tab1[]= " " " LaunchPad " " Welcome " " " ; unsigned char const tab2[]= "==== 欢迎使用 ====" " 西安电子科技大学 " " 声强检测模块 " "TexasInstruments" ; unsigned char const tab3[]= " "

" db " " 当前声强为 : " " " ; void IO_init() P2DIR =BIT0; void ADC10_Init(void) ADC10CTL1=CONSEQ_2;// 单通道多次转换, 这句应当写在最前面 ADC10CTL0 = REFON+SREF_1+REF2_5V; // 打开 2.5V 正参考, 地为负参考, 默认 1.5V ADC10CTL0 = ADC10ON+ADC10SHT_3+ADC10IE;// 打开 ADC10 内核, 设定采样保持时间为 64 个 ADC10CLK, 使能 ADC10 中断 ADC10CTL1 = INCH_3+SHS_0+ADC10SSEL_2; // input A3, 采样保持 ADC10AE0 = 0x02; // PA.3 DC option select A3 模拟信号输入使能 unsigned int m,ave; unsigned long AD_Result,sum=0; double db1; long db; void main() WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ;// 上面两句将内部 DCO 校准至 1MHz BCSCTL2 = SELM_0;//MCLK 采用 1M 的内部 DCO BCSCTL2 = DIVS_0;//SMCLK 采用 125K 的时钟 P2SEL &= ~(BIT6+BIT7); P2DIR = BIT6+BIT7; lcd_init(); ADC10_Init(); IO_init(); _BIS_SR(GIE);// 开中断 chn_disp1 (tab1); delay_ms(3000); chn_disp1 (tab2); delay_ms(3000); chn_disp1 (tab3); while(1)

Write_Num(0x88,dB,0); delay_ms(50); ADC10CTL0 = ENC + ADC10SC; #pragma vector=adc10_vector interrupt void ADC10_ISR (void) P2OUT&=~BIT0; ADC10CTL0 &= ~ENC; // Disable ADC conversion m++; // 计数变量加一, 记录进入 AD 中断的次数 AD_Result+=ADC10MEM; // 累加每次采样值 if(m>=8) // 判断采样的次数, 若采样次数等于 8, 作下面处理 m=0; ave=ad_result>>3; // 对累加和求平均 AD_Result=0; db1=ave*2.5/1023; db=(long)(70+120*log10(db1)); P2OUT =BIT0; 5.3.1 DAC8552 程序示例 void dac_init(void) P1OUT = 0x00; P1DIR = BIT5 +BIT7; P2DIR = BIT5; SYNC_H; P1SEL = BIT5 + BIT7; P1SEL2 = BIT5 + BIT7; UCB0CTL1 = UCSWRST; //SYNC 置为输出 //P2.5 做 SYNC //P1.5 7 分别作 SCLK 和 SIMO // 禁止 USCI 状态机 /* ~UCCKPH -- 数据在 UCLK 的第一个边沿变换, 在下一个边沿捕获 * ~UCCKPL -- 空闲状态为低 这两个就决定数据在下降沿写出 * UCMSB -- 最高位先出 * ~UC7BIT -- 8 位数据 * UCMST -- 主机模式 * UCMODE_0 -- 3 线制 SPI * UCSYNC -- 同步模式 */

UCB0CTL0 = UCMSB + UCMST + UCMODE_0 + UCSYNC;// UCB0CTL1 = UCSSEL_2 + UCSWRST; UCB0BR0 = 1; UCB0CTL1 &= ~UCSWRST; // 启动 USCI 状态机 5.3.2 程序示例 void sys_clock_init() // 时钟初始化为 1MHz; BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */ void PMW_OUT _Init () //PWM 输出初始化 P2DIR = BIT4; P2SEL = BIT4; TA1CTL = TASSEL_2+ID_0+MC_1; TA1CCTL2 = OUTMOD_7; // 选择高电平模式的 PWM 输出 TA1CCR0=2000; // TA1CCR0 写入 2000(1MHZ/2000) 输出达到了 500HZ 5.4.1 程序示例 /* 在本程序中, 使用了定时器的三种中断, 事件 1 2 和 3 事件 2 是在 P1.1 口产生 8.192KHZ 的方波, 事件 1 是在 P1.0 口产生 5HZ 的方波, 事件 3 是在 P1.2 口产生 2.048KHZ 的方波 在本程序中, 采用比较模式 4, 这种模式是当计数器计至 CCRX 时,TAX 管脚取反 特别注意 : 在本程序中千万不能将两种中断混淆 */ #include <MSP430G2553.H> int main( void ) WDTCTL = WDTPW + WDTHOLD; P1SEL = 0x06; P1DIR = 0x07; CCTL0 = OUTMOD_4 + CCIE; CCTL1 = OUTMOD_4 + CCIE; // 停止看门狗 // P1.1 - P1.2 的功能选择 // P1.0 - P1.2 方向 // CCR0 选择比较模式 4, 使能中断 // CCR1 选择比较模式 4, 使能中断

TACTL = TASSEL_1 + MC_2 + TAIE; 计数模式, 主计数器计满中断允许 _BIS_SR(LPM3_bits + GIE); // Timer A0 interrupt service routine #pragma vector=timer0_a0_vector interrupt void Timer_A0 (void) CCR0 += 4; // 时钟源选择 ACLK, 计数模式选择连续 // 进入低功耗模式 3, 打开全局中断 // 给 CCR0 赋初始值 // Timer_A2 Interrupt Vector (TA0IV) handler #pragma vector=timer0_a1_vector interrupt void Timer_A1(void) switch( TA0IV ) case 2: CCR1 += 16; // 给 CCR1 赋初始值 case 10: P1OUT ^= 0x01; // 主计数器计满溢出 5.4.2 程序示例 (1) 主程序 #include <DAC8552.h> #include "msp430g2553.h" #include "CLK.h" void main(void) WDTCTL = WDTPW + WDTHOLD; // 停止看门狗 sys_clock_init(mclk_1mhz); // 设置 DCO 频率可以是 1 8 12 16 MHz dac_init(); // 初始化 DAC 使用的 TA1_inittoDA(); out_v(1,5.0); out_v(2,2.0); (2) 时钟程序 #include "clk.h" void sys_clock_init(unsigned char FRQ)

BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; if (CALBC1_16MHZ!= 0xFF) DCOCTL = 0x00; switch(frq) case 1: //1Mhz BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */ case 8: //8Mhz BCSCTL1 = CALBC1_8MHZ; // Set range DCOCTL = CALDCO_8MHZ; // Set DCO step + modulation */ case 12: //12Mhz BCSCTL1 = CALBC1_12MHZ; // Set range DCOCTL = CALDCO_12MHZ; // Set DCO step + modulation*/ case 16: //16Mhz BCSCTL1 = CALBC1_16MHZ; // Set range DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation*/ default: BCSCTL1 = XT2OFF + DIVA_0; BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; void delayus(unsigned int us) unsigned int i; for(i=0;i<us;i++)

delay_cycles(16); (3)D/A 程序 #include "DAC8552.h" #include "sin_tab.h" #include "CLK.h" #include "msp430g2553.h" unsigned int frequency; unsigned int time_us; /*DAC8552 SPI 初始化 */ void dac_init(void) P1OUT = 0x00; P1DIR = BIT5 +BIT7; SYNC_H; P1SEL = BIT5 + BIT7; P1SEL2 = BIT5 + BIT7; P2DIR = BIT5; UCB0CTL1 = UCSWRST; //P1.4 做 SYNC //P1.5 7 分别作 SCLK 和 SIMO // 禁止 USCI 状态机 /* ~UCCKPH -- 数据在 UCLK 的第一个边沿变换, 在下一个边沿捕获 * ~UCCKPL -- 空闲状态为低 这两个就决定数据在下降沿写出 * UCMSB -- 最高位先出 * ~UC7BIT -- 8 位数据 * UCMST -- 主机模式 * UCMODE_0 -- 3 线制 SPI * UCSYNC -- 同步模式 */ UCB0CTL0 = UCMSB + UCMST + UCMODE_0 + UCSYNC;// UCB0CTL1 = UCSSEL_2 + UCSWRST; UCB0BR0 = 1; /* Enable USCI */ UCB0CTL1 &= ~UCSWRST; // 启动 USCI 状态机 void out_v(char channl,float voltage) unsigned int buf;

char high,low; buf=(voltage/4.95)*65535; low=buf&0xff; high=buf>>8; switch(channl) case 1: SYNC_L; // 选通拉低 UCB0TXBUF = 0X10; // 向 DA 写入命令 通道 A, 立即转换 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = high; // 写入高 8 位 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = low; // 写入低 8 位 while (!(IFG2 & UCB0TXIFG)); SYNC_H; // 选通拉高 case 2: SYNC_L; // 选通拉低 UCB0TXBUF = 0X24; // 向 DA 写入命令 通道 B, 立即转换 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = high; // 写入高 8 位 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = low; // 写入低 8 位 while (!(IFG2 & UCB0TXIFG)); SYNC_H; // 选通拉高 case 3: TA1CCR2=(voltage/3.54)*2000; 5.4.3 程序示例 #include "msp430g2433.h" #include "LCD12864.h" unsigned int TA_OverflowCntdi; // TA 溢出次数存放变量 ( 低通 ) unsigned int TA_OverflowCntdai; // TA 溢出次数存放变量 ( 带通 ) unsigned long int Perioddi; // 周期测量结果存放变量 ( 低通 ) unsigned long int Perioddai; // 周期测量结果存放变量 ( 带通 )

unsigned int PervCapValdi; // 前一次捕获值存放变量 ( 低通 ) unsigned int PervCapValdai; // 前一次捕获值存放变量 ( 带通 ) unsigned int Pulse_Cntdi=0; // 脉冲个数 ( 低通 ) unsigned int Pulse_Cntdai=0; // 脉冲个数 ( 带通 ) unsigned int Flagdi=0; // 低通标志 unsigned int Flagdai=0; // 带通标志 unsigned int timers; // 液晶显示汉字的频率设置 unsigned char const tab0[]= " 低通滤波器 " // 第一行 " Hz " // 第三行 " 频率值 " // 第二行 " " // 第四行 ; unsigned char const tab1[]= " 带通滤波器 " // 第一行 " Hz " // 第三行 " 频率值 " // 第二行 " " // 第四行 ; unsigned char const tab4[]= " 欢迎使用 " // 第一行 " 滤波器模块 " // 第三行 " " // 第二行 " " // 第四行 ; // 函数声明 /************************************************************************** * 名称 :FrequenceSet() * 功能 : 频率校准为 1MHZ * 入口参数 : 无 * 出口参数 : 无 ***************************************************************************/ void FrequenceSet(void) if (CALBC1_1MHZ ==0xFF CALDCO_1MHZ == 0xFF) FaultRoutine(); // If calibration data is erased // run FaultRoutine() BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation BCSCTL3 = LFXT1S_2; // LFXT1 = VLO

IFG1 &= ~OFIFG; // Clear OSCFault flag BCSCTL2 = SELM_0 ;//+ DIVM_3 + DIVS_3; // MCLK = SMCLK = 1M /************************************************************************** * 名称 :TA1_Init() * 功能 :TIMER_A 初始化, 捕获模块 1 启动, 选择 TA1(P2.1) 引脚作为捕获源, 上升沿捕获, 同步模式, 开启捕获中断捕获模块 0 启动, 选择 TA1(P2.0) 引脚作为捕获源, 上升沿捕获, 同步模式, 开启捕获中断 * 入口参数 : 无 * 出口参数 : 无 ***************************************************************************/ void TA1_Init(void) TA1CTL = TASSEL_2 + MC_2 + TAIE + TACLR; // TA 连续计数, 开始计时,SMCLK, 开中断 TA1CCTL1 = CAP + CM_1 + CCIS_0 + SCS + CCIE;// // 捕获模块 1 启动, 选择 TA1(P2.1) 引脚作为捕获源, 上升沿捕获, 同步模式, 开启捕获中断 TA1CCTL0 = CAP + CM_1 + CCIS_0 + SCS + CCIE; // 捕获模块 0 启动, 选择 TA1(P2.0) 引脚作为捕获源, 上升沿捕获, 同步模式, 开启捕获中断 TA0CCTL0 =CCIE; TA0CTL =TASSEL_2+MC_2;// 时钟源 SMCLK; 连续奇数模式 TA0CCR0=65535; /************************************************************************** * 名称 :IO_Init() * 功能 :IO 口初始化, 选择 P2.0,P2.1 的第二功能 ;P2.6,P2.7 为输入 * 入口参数 : 无 * 出口参数 : 无 ***************************************************************************/ void IO_Init(void) P2DIR&=~(BIT1+BIT0); //TA1.1 CCI1A P2.1 TA1.0 CCI0A P2.0 P2SEL =BIT1+BIT0; P2SEL &=~(BIT6+BIT7); P2DIR = BIT6+BIT7; P1DIR = BIT2+BIT1;

void main( void ) WDTCTL = WDTPW + WDTHOLD; FrequenceSet(); TA1_Init(); IO_Init(); lcd_init (); chn_disp1(tab4); // 开机界面显示 _EINT(); // 总中断允许 while(1) if(flagdi>=100) TA1CTL =TACLR; //TA 计数清零 TA1CCR1=0; chn_disp1(tab0); Write_Num(0x88, Pulse_Cntdi,2); // 显示低通频率值 Flagdi=0; if(flagdai>=100) TA1CTL =TACLR; TA1CCR0=0; chn_disp1(tab1); Write_Num(0x88, Pulse_Cntdai,2); Flagdai=0; // 显示带通频率值 /************************************************************************** 功能 :TA 中断, 被测信号的两次相邻上升沿都到达时,TA0 中断一次, 并计算频率值 **************************************************************************/ #pragma vector=timer1_a1_vector interrupt void TA_ISR(void) switch(ta1iv) // 带通中断源 case 2:

计算周期 用 +1 Flagdai++; Perioddai=TA_OverflowCntdai*65536 + TA1CCR1 - PervCapValdai;// PervCapValdai=TA1CCR1; // 保存捕获值, 供下一次使 TA_OverflowCntdai=0; // 溢出次数清零 Pulse_Cntdai=1000000/Perioddai+4; case 10: TA_OverflowCntdai++; //TA 每次溢出, 溢出次数变量 #pragma vector=timer1_a0_vector interrupt void TA1_ISR(void) // 低通中断源 Flagdi++; Perioddi=TA_OverflowCntdi*65536 + TA1CCR0 - PervCapValdi;// 计算周期 PervCapValdi=TA1CCR0; // 保存捕获值, 供下一次使用 TA_OverflowCntdi=0; // 溢出次数清零 Pulse_Cntdi=1000000/Perioddi+3; //+3 是频率补偿 该实例程序的性能和指标为 ( 假定系统时钟没有误差 = 1MHz): (1) 频率测量绝对误差 :±1Hz (2) 被测最高频率值 :2.5KHz (3) 测量频度 :1 次 / 秒 (4) 使用资源 : 两个定时器, 两个中断 5.5.1 程序示例主机程序 : #include "msp430g2433.h" #include "SPI.h" // 串口通讯程序库头文件 unsigned char TXBuff[5]=0x50,0x40,0x30,0x20,0x10; #define TXBUF_SIZE 32 #define FRAME_SIZE 5 /* 定长帧的长度 */ unsigned char TX_BUFF[TXBUF_SIZE]; unsigned char RX_BUFF[FRAME_SIZE];

unsigned char SPI_RcvCnt=0; // 接收计数 void SPI_M_Init(void) UCA0CTL1 = UCSWRST; // UCA0STAT = UCLISTEN; UCA0CTL1 = UCSSEL1; UCA0CTL0 = UCMST + UCSYNC+UCMSB; **SWRST** MSB 起始 UCA0BR0 = 0x02; UCA0BR1 = 0x00; UCA0MCTL = 0x00; UCA0CTL0 = UCMODE_0; UCA0CTL0 = UCCKPH; UCA0CTL0 &=~ UCCKPL; UCA0CTL1 &= ~UCSWRST; machine P1SEL = BIT4; P1SEL2 = BIT4; P1DIR = BIT4; P1SEL = BIT2; P1SEL2 = BIT2; P1DIR = BIT2; P1SEL = BIT1; P1SEL2 = BIT1; P1DIR &=~ BIT1; //ACLK // 8-bit SPI Master // no modulation // 3-pin mode // 下降沿发送, 上升沿接收 // Initalize USART state //UCA0CLK //SIMO //SOMI IE2 =UCA0RXIE; // 串口发送函数 void SpiWriteDat(unsigned char *Ptr,unsigned int Lenth) int i; for(i=0;i<lenth;i++) UCA0TXBUF=Ptr[i]; while ((IFG2&UCA0TXIFG)==0); // 等待上一字节发完 IFG2&=~UCA0TXIFG;

// 串口接收中断函数 #pragma vector=usciab0rx_vector interrupt void UartR0() RX_BUFF[SPI_RcvCnt]=UCA0RXBUF; // 接收该字节数据 SPI_RcvCnt++; // 指向下一单元 if(spi_rcvcnt>=frame_size) SPI_RcvCnt=0; // 接收数组清零 void main(void) WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO / 8 = 1MHz SPI_M_Init(); _EINT(); while(1) // 串口测试 SpiWriteDat(TXBuff,5); // delay_cycles(1000000); 从机程序 : #include "msp430g2433.h" #include "SPI.h" // 串口通讯程序库头文件 #define TXBUF_SIZE 32 #define FRAME_SIZE 5 /* 定长帧的长度 */ unsigned char TX_BUFF[TXBUF_SIZE];

unsigned char RX_BUFF[FRAME_SIZE]; unsigned char SPI_RcvCnt=0; // 接收计数 void SPI_S_Init(void) UCA0CTL1 = UCSWRST; UCA0CTL0 = UCMSB + UCSYNC; UCA0CTL0 = UCMODE_0; UCA0CTL0 = UCCKPH; UCA0CTL0 &=~ UCCKPL; UCA0CTL1 &= ~UCSWRST; machine P1SEL = BIT4; P1SEL2 = BIT4; P1DIR &=~ BIT4; P1SEL = BIT2; P1SEL2 = BIT2; P1DIR &=~ BIT2; P1SEL = BIT1; P1SEL2 = BIT1; P1DIR = BIT1; // 8-bit SPI Slave **SWRST** // 3-pin mode // 下降沿发送, 上升沿接收 // Initalize USART state //UCA0CLK //SIMO //SOMI IE2 =UCA0RXIE; // 串口发送函数 void SpiWriteDat(unsigned char *Ptr,unsigned int Lenth) int i; for(i=0;i<lenth;i++) UCA0TXBUF=Ptr[i]; while ((IFG2&UCA0TXIFG)==0); // 等待上一字节发完 IFG2&=~UCA0TXIFG; // 串口接收中断函数 #pragma vector=usciab0rx_vector

interrupt void UartR0() RX_BUFF[SPI_RcvCnt]=UCA0RXBUF; // 接收该字节数据 SPI_RcvCnt++; // 指向下一单元 if(spi_rcvcnt>=frame_size) SPI_RcvCnt=0; // 接收数组清零 // delay_cycles(1000); unsigned char TXBuff[5]=0xFF,0x20,0x30,0x40,0x50; void main( void ) // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; SPI_S_Init(); _EINT(); while(1) // 串口测试 SpiWriteDat(TXBuff,5); // delay_cycles(1000000); 5.5.2 程序示例 #include "msp430g2433.h" #include "spi.h" #include "LCD.h" #include "AD.h" #include "key.h" #include "TA.h" //unsigned int ADC10_Result; unsigned long int Voltage0; unsigned long int Voltage1; unsigned char flag=0;

unsigned char W0Buff[2]=0x2A,0x01; //1, 通道 1 unsigned char W1Buff[2]=0x2A,0x11; //2, 通道 1 unsigned char W2Buff[2]=0x2A,0x21; //4, 通道 1 unsigned char W3Buff[2]=0x2A,0x31; //8, 通道 1 unsigned char W4Buff[2]=0x2A,0x41; //16, 通道 1 unsigned char W5Buff[2]=0x2A,0x51; //32, 通道 1 unsigned char W6Buff[2]=0x2A,0x61; //64, 通道 1 unsigned char W7Buff[2]=0x2A,0x71; //128, 通道 1 volatile unsigned int num=1; volatile unsigned int val0; volatile unsigned int val1; #define TXBUF_SIZE 32 #define FRAME_SIZE 5 /* 定长帧的长度 */ unsigned char TX_BUFF[TXBUF_SIZE]; unsigned char RX_BUFF[FRAME_SIZE]; unsigned char SPI_RcvCnt=0; // 接收计数 unsigned char FrameRcvStatus=0; /* 帧接收状态 */ void SPI_M_Init(void) UCA0CTL1 = UCSWRST; // U0CTL = LISTEN; UCA0CTL1 = UCSSEL1; //ACLK UCA0CTL0 = UCMST + UCSYNC+UCMSB; // 8-bit SPI Master **SWRST** MSB 起始 UCA0BR0 = 0x02; UCA0BR1 = 0x00; UCA0MCTL = 0x00; // no modulation UCA0CTL0 = UCMODE0; // 3-pin mode UCA0CTL0 = UCCKPH; UCA0CTL0 &=~ UCCKPL; // 下降沿发送, 上升沿接收 // ME2 = USPIE0; // Enable USART0 SPI mode UCA0CTL1 &= ~UCSWRST; // Initalize USART state machine P1SEL = BIT4; P1SEL2 = BIT4;

P1DIR = BIT4; P1SEL = BIT2; P1SEL2 = BIT2; P1DIR = BIT2; // P1SEL = BIT5; // P1SEL2 = BIT5; // P1DIR = BIT5; //UCA0CLK //SIMO // IFG1 &= ~URXIFG0; IE2 =UCA0RXIE; // 串口发送函数 void SpiWriteDat(unsigned char *Ptr,unsigned int Lenth) int i; for(i=0;i<lenth;i++) UCA0TXBUF=Ptr[i]; while ((IFG2&UCA0TXIFG)==0); // 等待上一字节发完 IFG2&=~UCA0TXIFG; // 串口接收中断函数 #pragma vector=usciab0rx_vector interrupt void UartR0() RX_BUFF[SPI_RcvCnt]=UCA0RXBUF; // 接收该字节数据 SPI_RcvCnt++; // 指向下一单元 if(spi_rcvcnt>=frame_size) SPI_RcvCnt=0; // 接收数组清零 unsigned int ADC10_Result0; unsigned int ADC10_Result1; volatile unsigned long int ADC_Result[1];

volatile unsigned long int ADC_Result0; volatile unsigned long int ADC_Result1; //unsigned long int Voltage0; unsigned char ADC10_Flag=0; unsigned char i=1; unsigned int j=0; void Init_ADC10(void) ADC10CTL0 = ADC10SR+REFON+REF2_5V+ADC10ON+MSC; ADC10CTL0 = ADC10SHT_3+SREF_1; ADC10CTL1 = ADC10SSEL_3+ADC10DIV_1+INCH_1+SHS_0+CONSEQ_3; //OSC, 无分频 ADC10AE0 = BIT0+BIT1; void ADC10_Sample(unsigned int AverageNum) unsigned long int ADC10_Sum0=0; unsigned long int ADC10_Sum1=0; unsigned int i; ADC10CTL0 = ADC10IE; ADC10CTL0 = ADC10SC+ENC; for(i=0;i<averagenum;i++) while((adc10_flag)==0); ADC10_Flag=0; ADC10_Sum0+=(int)ADC_Result0; ADC10_Sum1+=(int)ADC_Result1; ADC10CTL0 &=~ ENC; ADC10CTL0 &=~ ADC10IE; ADC10_Result0=ADC10_Sum0/AverageNum; ADC10_Result1=ADC10_Sum1/AverageNum; #pragma vector=adc10_vector interrupt void ADC10ISR(void)

ADC_Result[i]=ADC10MEM; i--; if(i>2) i=1; ADC_Result1=ADC_Result[1]; ADC_Result0=ADC_Result[0]; ADC10_Flag=1; // 延时函数 void Delay(int n)// 延时, 时间为 n int i; for(i=0;i<n;i++);// 循环 n 次 // 初始化 4 线工作模式函数 void Init_4lines_Mode(void)// 初始化 4 线工作模式 // 初始化 P5 端口,P5.5 接 CH452 的 DCLK 引脚,P5.6 接 CH452 的 DIN 引脚,P5.7 接 CH452 的 LOAD 引脚 P2DIR =BIT1+BIT2+BIT3; P2DIR&=~BIT0; // 初始化 DCLK DIN 和 LOAD DCLK_1; DIN_1; LOAD_1; // 发送命令 void Send_Command(unsigned cmd)//msp430 单片机向 CH452 发送命令,Command 为 12 位数据 unsigned char i; LOAD_0; for(i=0;i!=12;i++) // 送入 12 位数据, 低位在前 if (cmd&1) DIN_1;

else DIN_0; // 输出位数据 DCLK_0 ; cmd>>=1; DCLK_1 ; // 上升沿有效 LOAD_1; Delay(1000); // 输入按键代码子程序, 从 CH452 读取 unsigned char Key_Read( void ) unsigned char i; unsigned char keycode; // 定义命令字, 和数据存储器 Send_Command(CH452_GET_KEY); keycode=0; // 清除 keycode for(i=0;i!=7;i++) keycode<<=1; // 数据移入 keycode, 高位在前, 低位在后 if (P2IN&BIT0) keycode++; // 从高到低读入 451 的数据 DCLK_0; // 产生时钟下升沿通知 CH451 输出下一位 DCLK_1; return(keycode); // 返回键值 void main( void ) // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; Init_4lines_Mode(); // 初始化 4 线工作模式 Send_Command(CH452_RESET); Send_Command(KeyDisplay_ON); P2IE =BIT0; 按下时,DOUT 上产生由高到低的脉冲 P2IES =BIT0; P2IFG&=~BIT0; // 开中断,P1.2 接 CH452 的 DOUT 引脚, 当有键 LCD_Port_Init(); LCD_Init(); Init_ADC10();

Init_TA(); SPI_M_Init(); P1DIR =BIT5; CHN_Disp(Start_Topic_0); delay_cycles(2000000); Clr_ram(); _EINT(); while(1) if(flag_count0==1) ADC10_Sample(100); Voltage0=ADC10_Result0*250000/10230; Voltage1=ADC10_Result1*250000/10230; val0=voltage0/num; Flag_Count0=0; if(flag_count1==1) if(flag==0) CHN_Disp(Start_Topic); Set_position_Dis(2,3); Write_Num(Voltage0,1); Set_position_Dis(3,4); Write_Num(num,0); Set_position_Dis(1,3); Write_Num(val0,1); else CHN_Disp(Start_Topic_1); Set_position_Dis(2,3); Write_Num(Voltage1,1); Set_position_Dis(1,3); Write_Num(178,1); Flag_Count1=0;

之 // 中断处理函数 #pragma vector = PORT2_VECTOR // 中断处理程序, 接收到 DOUT 脉冲信号时, 运行 interrupt void Port2(void) unsigned char Keyvalue; Send_Command(CH452_GET_KEY); Keyvalue=Key_Read(); switch(keyvalue) case Key0: P1OUT&=~BIT5; SpiWriteDat(W0Buff,2); P1OUT =BIT5; Send_Command( NDis1); Send_Command( NDis2); // Send_Command( NDis3); Send_Command(Dis01); num=1; case Key1: P1OUT&=~BIT5; SpiWriteDat(W1Buff,2); P1OUT =BIT5; Send_Command( NDis1); Send_Command( NDis2); // Send_Command( NDis3); Send_Command(Dis02); num=2; case Key2: P1OUT&=~BIT5; SpiWriteDat(W2Buff,2);

P1OUT =BIT5; Send_Command( NDis1); Send_Command( NDis2); // Send_Command( NDis3); Send_Command(Dis04); num=4; case Key3: P1OUT&=~BIT5; SpiWriteDat(W3Buff,2); P1OUT =BIT5; Send_Command( NDis1); Send_Command( NDis2); // Send_Command( NDis3); Send_Command(Dis08); num=8; case Key4: P1OUT&=~BIT5; SpiWriteDat(W4Buff,2); P1OUT =BIT5; Send_Command( NDis2); // Send_Command( NDis3); Send_Command(Dis06); Send_Command(Dis11); num=16; case Key5: P1OUT&=~BIT5; SpiWriteDat(W5Buff,2); P1OUT =BIT5; Send_Command( NDis2); // Send_Command( NDis3);

Send_Command(Dis02); Send_Command(Dis13); num=32; case Key6: P1OUT&=~BIT5; SpiWriteDat(W6Buff,2); P1OUT =BIT5; Send_Command( NDis2); // Send_Command( NDis3); Send_Command(Dis04); Send_Command(Dis16); num=64; case Key7: P1OUT&=~BIT5; SpiWriteDat(W7Buff,2); P1OUT =BIT5; // Send_Command( NDis3); Send_Command( NDis1); Send_Command(Dis08); Send_Command(Dis12); Send_Command(Dis21); num=128; case 0x50: // Send_Command(Dis08); case 0x51:

// Send_Command(Dis09); case 0x52: // Send_Command(Dis00); // Send_Command(Dis11); case 0x53: // Send_Command(Dis01); // Send_Command(Dis11); case 0x58: // Send_Command(Dis02); // Send_Command(Dis11); case 0x59: // Send_Command(Dis03); // Send_Command(Dis11); case 0x5A: Clr_ram(); flag=1; case 0x5B: Clr_ram(); flag=0; default: P2IFG&=~BIT0;

5.5.3 程序示例程序功能为接收 PC 机发送来的数据后自动回发给 PC 机 #include "msp430g2553.h" void main(void) WDTCTL = WDTPW + WDTHOLD; // 停止看门狗 UCA0CTL1 = UCSWRST; // USCI_A0 进入软件复位状态 UCA0CTL1 = UCSSEL_2; // 时钟源选择 SMCLK BCSCTL1 = CALBC1_1MHZ; // 设置 DCO 频率为 1MHz DCOCTL = CALDCO_1MHZ; P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD P1DIR = BIT0; UCA0BR0 = 0x68; // 时钟源 1MHz 时波特率为 9600 UCA0BR1 = 0x00; // 时钟源 1MHz 时波特率为 9600 UCA0MCTL = UCBRS0; // 小数分频器 UCA0CTL1 &= ~UCSWRST; // 初始化 USCI_A0 状态机 IE2 = UCA0RXIE; // 使能 USCI_A0 接收中断 _EINT(); // 开总中断 while(1) #pragma vector = USCIAB0RX_VECTOR // 接收中断 interrupt void USCI0RX_ISR(void) while (!(IFG2&UCA0TXIFG) ); // 确保发送缓冲区准备好 P1OUT ^= BIT0; // 接收指示灯状态改变 UCA0TXBUF = UCA0RXBUF; // 发送接收到的数据 5.5.4 程序示例本范例由 MSP430 单片机作为 RS485 总线上的从机,PC 机作为主机 功能是由 PC 机发送字符到从机, 从机接收到后再发回主机 此实验的程序部分之比上一小节的 RS232 实验中多了一个 IO 的方向控制, 用来控制 485 芯片的接收与发送 #include "msp430g2553.h" void main(void)

WDTCTL = WDTPW + WDTHOLD; // 停止看门狗 UCA0CTL1 = UCSWRST; // USCI_A0 进入软件复位状态 UCA0CTL1 = UCSSEL_2; // 时钟源选择 SMCLK BCSCTL1 = CALBC1_1MHZ; // 设置 DCO 频率为 1MHz DCOCTL = CALDCO_1MHZ; P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD P1DIR = BIT0+BIT3; //P1.0 用于控制接收指示灯,P1.3 用于控制 485 收发状态 UCA0BR0 = 0x68; // 时钟源 1MHz 时波特率为 9600 UCA0BR1 = 0x00; // 时钟源 1MHz 时波特率为 9600 UCA0MCTL = UCBRS0; // 小数分频器 UCA0CTL1 &= ~UCSWRST; // 初始化 USCI_A0 状态机 IE2 = UCA0RXIE; // 使能 USCI_A0 接收中断 _EINT(); // 开总中断 while(1) #pragma vector = USCIAB0RX_VECTOR // 接收中断 interrupt void USCI0RX_ISR(void) while (!(IFG2&UCA0TXIFG) ); // 确保发送缓冲区准备好 P1OUT ^= BIT0; // 接收指示灯状态改变 P1OUT =BIT3; // 使 485 为发送 状态 UCA0TXBUF = UCA0RXBUF; // 发送接收到的数据 delay_ms(10); P1OUT&=~BIT3; // 使 485 为接收状态 5.5.5 程序示例 #include "msp430g2553.h" #define CPU_F ((double)1000000) #define delay_us(x) delay_cycles((long)(cpu_f*(double)x/1000000.0)) // 延时 x 微秒 #define DQ_H P1DIR&=~BIT1 //P1.1 设为输入, 上拉电阻把总线拉高, 即电阻上 拉 #define DQ_L P1DIR =BIT1

#define DQ_0 P1OUT&=~BIT1 //P1.1 设为输入, 输出低电平, 把总线拉低, 即总 线主器件拉低 unsigned char temp1,temp2; /************************************************************************** * 名 称 :reset() * 功 能 : 检测 DS18B20 初始化序列 * 入口参数 : 无 * 出口参数 :int t t=1,ds18b20 初始化 ;t=0,ds18b20 没有初始化 ***************************************************************************/ int reset() int t; DQ_H; delay_us(50); _NOP(); _NOP(); DQ_L; DQ_0; // 主器件拉低 delay_us(500); // 最少 480us DQ_H; // 电阻上拉 delay_us(60); // 等待 15~60us if((p2in&bit3)==0) t=1; // 判断存在脉冲,DS18B20 是否拉低 else t=0; delay_us(480); // 最小 480us return(t); // 若 DS18B20 复位, 返回值 t=1 /************************************************************************** * 名 称 :writebit() * 功 能 : 单片机对 DS18B20 写时隙 * 入口参数 :unsigned char bit bit=1, 写 1 时隙 ;bit=0, 写 0 时隙 * 出口参数 : 无 ***************************************************************************/ void writebit(unsigned char bit) DQ_L; // 主器件拉低开始 DQ_0; delay_us(3); // 最少延时 1us if(bit) DQ_H; // 电阻上拉, 写 1 else DQ_L; // 主器件拉低, 写 0 DQ_0;

delay_us(80); // 写时隙必须至少持续 60μs DQ_H; delay_us(60); // 大于 1us 延时即可 /************************************************************************** * 名称 :readbit() * 功能 : 单片机对 DS18B20 读时隙 * 入口参数 : 无 * 出口参数 :char bit bit=1, 读 1 时隙 ;bit=0, 读 0 时隙 ***************************************************************************/ unsigned char readbit() char bit; DQ_L; // 主器件拉低开始 DQ_0; delay_us(3); // 延时大于 1us DQ_H; //IO 口设为输出,DS18B20 拉低, 则读出 0; 电阻上拉拉高, 则读出 1 delay_us(3); // 延时小于 15us if(p1in&bit1) bit=1; // 判断 IO 输入状态 else bit=0; delay_us(80); // 延时大于 45us DQ_H; delay_us(60); return(bit); /************************************************************************** * 名称 :write_byte() * 功能 : 单片机向 DS18B20 写入一个字节 * 入口参数 :unsigned char byte byte 为单片机写入的数据 * 出口参数 : 无 ***************************************************************************/ void write_byte(unsigned char byte) int i; for(i=0;i<8;i++) writebit(byte&0x01); //byte 最后一位为 1, 这写 1 时隙 ; 若为 0, 则写 0 时隙 byte=byte>>1; //byte 右移一位,byte 从低位到高位, 逐位写入 _NOP();

/************************************************************************** * 名称 :read_byte() * 功能 : 单片机从 DS18B20 读出一个字节 * 入口参数 : 无 * 出口参数 :unsigned char ans ans 为单片机从 DS18B20 读出的数据 ***************************************************************************/ unsigned char read_byte() int t; unsigned char ans=0; for(t=0;t<8;t++) ans>>=1; //ans 右移一位 if(readbit()) ans =0x80; // 若读出 1 则,ans 最高位写入 1, 写满 8 位 _NOP(); return(ans); // 返回读出的数据 void main() WDTCTL=WDTPW+WDTHOLD; float t; while(1) while(!reset()) // 访问 DS18B20 以一个初始化序列未开始 write_byte(0xcc); // 总线上只有一个 DS18B20, 因此可直接跳过寻址 write_byte(0x44); // 开始温度转换 delay_us(5000); // 等待转换 while(!reset()) // 等待 DS18B20 复位 write_byte(0xcc); write_byte(0xbe); // 读暂存器 temp1=read_byte(); // 读出 LS temp2=read_byte(); // 读出 MS reset(); t=(float)temp1*0.0625+(float)temp2*16; // 计算温度值 t=t*10+0.5; // 放大 10 倍, 四舍五入

第六章 6.1.3 //================================================================ // 调整 PID 的三个系数, 达到最佳的控制效果 #define P_Coefficient 40 #define D_Coefficient 480 #define I_Coefficient 0.08 //================================================================= #define U_MAX 5000 //D/A 能输出的最大电压值 5V unsigned int Integral; // 积分累计 int Prev_Error; // 记录前一次误差 int P,I,D; //PID 分量 float Ek,E; // 误差临时变量 unsigned char FirstFlag=1; // 第一次执行表示 /************************************************************************* * * 名称 :PID_Caculate() * 功能 :PID 控制算法 * 入口参数 :Error: 实际温度与设定温度的误差,10 代表 1 * 出口参数 :OutPut: 单片机应控制 D/A 输出的电压值,1000=1000mV ************************************************************************** / int PID_Caculate(int Error) int i; float OutPut; if(firstflag) // 判断第一次上电 FirstFlag=0; Prev_Error=Error; // 上电第一次时, 没有前一次测量, 赋当前值, 以免微分计算错误 Ek=Error-Prev_Error; // 相邻两侧测量值去差分 Prev_Error=Error; // 保存当前采样值, 下一次使用 E=0.8*E+Ek*0.2; // 微分通过 IIR 滤波器, 降噪 P=P_Coefficient*Error; // 计算比例分量 I=I_Coefficient*Integral; // 计算积分分量 D=D_Coefficient*E; // 计算微分分量

OutPut=P+D+I; //PID 合成输出 if((output>10000) (Error>100) (Error<-100)) // 输出饱和或偏差大时不积分 //if((integral>0)&&(error<0)) Integral+=Error; //if((integral<0)&&(error>0)) Integral+=Error; Else // 偏差较小时启动积分 Integral+=Error; if(integral<0) Integral=0; if(output>1000) OutPut=1000; else if(output<0) OutPut=0; OutPut= U_MAX*OutPut/10000; // 计算 D/A 应输出的电压值 return(output); 6.1.4 #define DAC_PORT P2OUT #define SYNC BIT5 #define SCLK BIT1 #define DIN BIT2 #define SYNC_L DAC_PORT &=~ SYNC #define SYNC_H DAC_PORT = SYNC #define SCLK_L DAC_PORT &=~ SCLK #define SCLK_H DAC_PORT =SCLK #define DIN_L DAC_PORT &=~ DIN #define DIN_H DAC_PORT = DIN unsigned int frequency; unsigned int time_us; /*DAC8552 SPI 初始化程序 */ void dac_init(void) P1OUT = 0x00; P1DIR = BIT5 +BIT7; //P1.4 做 SYNC SYNC_H; P1SEL = BIT5 + BIT7; //P1.5 7 分别作 SCLK 和 SIMO P1SEL2 = BIT5 + BIT7; P2DIR = BIT5; UCB0CTL1 = UCSWRST; // 禁止 USCI 状态机 UCB0CTL0 = UCMSB + UCMST + UCMODE_0 + UCSYNC;// UCB0CTL1 = UCSSEL_2 + UCSWRST;

UCB0BR0 = 1; UCB0CTL1 &= ~UCSWRST; // 启动 USCI 状态机 /************************************************************************** * 名称 :out_v() * 功能 :D/A 电压输出 * 入口参数 :channl:d/a 输出通道选择, 共有三个通道 ;voltage: 要输出的电压值 (mv) * 出口参数 : 无 **************************************************************************/ void out_v(char channl,float voltage) unsigned int buf; char high,low; buf=(voltage/4950)*65535; low=buf&0xff; high=buf>>8; switch(channl) case 1: SYNC_L; // 选通拉低 UCB0TXBUF = 0X10; // 向 DA 写入命令 通道 A, 立即转换 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = high; // 写入高 8 位 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = low; // 写入低 8 位 while (!(IFG2 & UCB0TXIFG)); SYNC_H; // 选通拉高 case 2: SYNC_L; // 选通拉低 UCB0TXBUF = 0X24; // 向 DA 写入命令 通道 B, 立即转换 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = high; // 写入高 8 位 while (!(IFG2 & UCB0TXIFG)); UCB0TXBUF = low; // 写入低 8 位 while (!(IFG2 & UCB0TXIFG)); SYNC_H; // 选通拉高 case 3:

TA1CCR2=(voltage/3540)*2000; 根据上面的程序流程图, 结合 DS18B20 测温程序和 D/A 输出程序, 本应用的程序如下 : #define T_Aralm 320 // 报警温度值 32.0 #define T_Set 300 // 设定恒定温度值 30.0 void main() WDTCTL = WDTPW + WDTHOLD; // 停止看门狗 BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; BCSCTL2 = SELM_0; //MCLK 采用 1M 的内部 DCO BCSCTL2 = DIVS_0; // 配置时钟 int T, Error; float V_OUT; dac_init(); //D/A 模块初始化 lcdreset(); //LCD12864 液晶初始化 while(1) T=ReadTemp(); // 从 DS18B20 中读取温度,10=1 wr_lcd(comm,0x80); printstring(" 当前温度值 :"); Write_Num(0x92,T,1); //LCD12864 显示温度值 T if(t>t_aralm) //T 大于报警值 P1DIR =BIT0; P1OUT =BIT0; // 点亮红灯 else P1DIR =BIT0; P1OUT&=~BIT0; if(t>t_set) //T 大于设定恒温值 Error=T-T_Set; else Error=T_Set-T; V_OUT=PID_Caculate(Error); //PID 算法 out_v(2,v_out); //D/A 输出电压

6.2.3 AD 采样软件实现 : void Init_ADC10(void) //ADC10 初始化 ADC10CTL0 = REFON+REF2_5V+ADC10ON+ADC10IE+MSC; // 参考电压 2.5V 多次采样模式打开 ADC10 模块中断 ADC10 允许 ADC10CTL0 = ADC10SHT_3+SREF_1; ADC10CTL1 =ADC10SSEL_3+ADC10DIV_0+INCH_0+SHS_0+CONSEQ_2; //SMCLK, 无分频, 通道 0 单通道多次转换 ADC10AE0 = 0x01; void ADC10_Sample(unsigned int AverageNum) //ADC10 采样函数 unsigned long int ADC10_Sum0=0; unsigned int i; ADC10CTL0 = ADC10IE; ADC10CTL0 = ADC10SC+ENC; // 开始采样 for(i=0;i<averagenum;i++) while((adc10_flag)==0); ADC10_Flag=0; ADC10_Sum0+=(int)ADC_Result0; ADC10CTL0 &=~ ENC; // 禁止采样 ADC10CTL0 &=~ ADC10IE; ADC10_Result0=ADC10_Sum0/(AverageNum); // 多次采样求平均 #pragma vector=adc10_vector // 采样中断内读取采样 值 interrupt void ADC10ISR(void) ADC_Result0=ADC10MEM; ADC10_Flag=1; 按键控制程控放大倍数的软件实现 : #pragma vector = PORT2_VECTOR // P2 口中断函数 interrupt void Port2(void) unsigned char Keyvalue;